Documentation
¶
Index ¶
- Constants
- Variables
- func AggregateMetricNames(metrics map[string]Metric) []string
- func DimensionAlias(dimension string) string
- func EvaluateExpression(expr string, values map[string]float64) (float64, error)
- func ExpressionMetrics(metrics map[string]Metric) []string
- func GenerateDimensionalSQL(source *Source, allMetrics map[string]Metric, metricNames []string, ...) (string, error)
- func GenerateMetricsSQL(source *Source, metrics map[string]Metric, dateFilter map[string]any) (string, error)
- func IsTSXFile(name string) bool
- func ResolveDatePreset(key string) map[string]any
- func Validate(d *Dashboard) error
- func ValidateAll(dashboards []*Dashboard) error
- type AxisEncoding
- func (a *AxisEncoding) FieldList() []string
- func (a *AxisEncoding) FieldString() string
- func (a *AxisEncoding) MarshalJSON() ([]byte, error)
- func (a *AxisEncoding) MarshalYAML() (any, error)
- func (a *AxisEncoding) UnmarshalJSON(data []byte) error
- func (a *AxisEncoding) UnmarshalYAML(node *yaml.Node) error
- type Dashboard
- func FindByName(dashboards []*Dashboard, name string) *Dashboard
- func LoadDir(dir string, opts ...TSXOption) ([]*Dashboard, error)
- func LoadFile(path string) (*Dashboard, error)
- func LoadOneByName(dir, name string, opts ...TSXOption) (*Dashboard, error)
- func LoadTSXFile(path string, opts ...TSXOption) (*Dashboard, error)
- func (d *Dashboard) DateRangeFilterName() string
- func (d *Dashboard) DefaultFilters() map[string]any
- func (d *Dashboard) ResolveSemanticModel(ref string) (*sem.Model, string, error)
- func (d *Dashboard) ResolveWidgetSemanticJob(w *Widget) (*SemanticJob, bool, error)
- func (d *Dashboard) SemanticDimensions() map[string]Dimension
- func (d *Dashboard) SemanticMetrics() map[string]Metric
- func (d *Dashboard) SemanticSource() *Source
- func (d *Dashboard) SetProjectContext(projectRoot string, semanticModels map[string]*sem.Model, ...)
- func (d *Dashboard) SourceConnection() string
- type Dimension
- type Filter
- type FilterOptions
- type Metric
- type NoQueryError
- type ProjectPaths
- type Query
- type QueryNotFoundError
- type RefreshConfig
- type Row
- type SemanticDimensionRef
- type SemanticJob
- type SemanticLayer
- type SemanticQueryFilter
- type SemanticSort
- type Source
- type TSXOption
- type TableColumn
- type ValidationError
- type ValidationSetError
- type ValueEncoding
- type Widget
Constants ¶
const ( WidgetTypeMetric = "metric" WidgetTypeChart = "chart" WidgetTypeTable = "table" WidgetTypeText = "text" WidgetTypeDivider = "divider" WidgetTypeImage = "image" )
Widget type constants.
Variables ¶
var ValidAggregates = map[string]bool{ "count": true, "count_distinct": true, "sum": true, "avg": true, "min": true, "max": true, }
ValidAggregates lists the supported aggregate functions.
Functions ¶
func AggregateMetricNames ¶
AggregateMetricNames returns sorted names of all non-expression metrics.
func DimensionAlias ¶
DimensionAlias returns a clean column alias for a dimension expression. e.g. "geo.country" -> "country", "event_date" -> "event_date".
func EvaluateExpression ¶
EvaluateExpression evaluates a simple arithmetic expression with metric name substitution. Supports +, -, *, /, parentheses, and numeric literals. Division by zero returns 0.
func ExpressionMetrics ¶
ExpressionMetrics returns sorted names of all expression metrics.
func GenerateDimensionalSQL ¶
func GenerateDimensionalSQL(source *Source, allMetrics map[string]Metric, metricNames []string, dim *Dimension, dateFilter map[string]any, limit int) (string, error)
GenerateDimensionalSQL builds a SELECT that computes the given metrics grouped by a dimension column. Used for declarative chart widgets.
func GenerateMetricsSQL ¶
func GenerateMetricsSQL(source *Source, metrics map[string]Metric, dateFilter map[string]any) (string, error)
GenerateMetricsSQL builds a single SELECT that computes all aggregate (non-expression) metrics from the source table. The returned SQL may contain Jinja template expressions (e.g. in the table name) and should be rendered through the template engine before execution.
func ResolveDatePreset ¶
ResolveDatePreset converts a preset key like "last_30_days" into a map with "start" and "end" date strings. Returns nil if the key is unknown.
func ValidateAll ¶
Types ¶
type AxisEncoding ¶ added in v0.2.1
type AxisEncoding struct {
Field any `yaml:"field" json:"field"`
Type string `yaml:"type,omitempty" json:"type,omitempty"`
Title string `yaml:"title,omitempty" json:"title,omitempty"`
Format string `yaml:"format,omitempty" json:"format,omitempty"`
}
func (*AxisEncoding) FieldList ¶ added in v0.2.1
func (a *AxisEncoding) FieldList() []string
func (*AxisEncoding) FieldString ¶ added in v0.2.1
func (a *AxisEncoding) FieldString() string
func (*AxisEncoding) MarshalJSON ¶ added in v0.2.1
func (a *AxisEncoding) MarshalJSON() ([]byte, error)
func (*AxisEncoding) MarshalYAML ¶ added in v0.2.1
func (a *AxisEncoding) MarshalYAML() (any, error)
func (*AxisEncoding) UnmarshalJSON ¶ added in v0.2.1
func (a *AxisEncoding) UnmarshalJSON(data []byte) error
func (*AxisEncoding) UnmarshalYAML ¶ added in v0.2.1
func (a *AxisEncoding) UnmarshalYAML(node *yaml.Node) error
type Dashboard ¶
type Dashboard struct {
Schema string `yaml:"schema,omitempty" json:"schema,omitempty"`
Name string `yaml:"name" json:"name"`
Description string `yaml:"description,omitempty" json:"description,omitempty"`
Connection string `yaml:"connection,omitempty" json:"connection,omitempty"`
Model string `yaml:"model,omitempty" json:"model,omitempty"`
Models map[string]string `yaml:"models,omitempty" json:"models,omitempty"`
Theme string `yaml:"theme,omitempty" json:"theme,omitempty"`
Refresh *RefreshConfig `yaml:"refresh,omitempty" json:"refresh,omitempty"`
Filters []Filter `yaml:"filters,omitempty" json:"filters,omitempty"`
Queries map[string]Query `yaml:"queries,omitempty" json:"queries,omitempty"`
Semantic *SemanticLayer `yaml:"semantic,omitempty" json:"semantic,omitempty"`
Rows []Row `yaml:"rows" json:"rows"`
// FilePath is the source file path, not serialized to JSON for API consumers.
FilePath string `yaml:"-" json:"-"`
// FileType indicates the source format: "yaml" or "tsx".
FileType string `yaml:"-" json:"file_type,omitempty"`
// contains filtered or unexported fields
}
Dashboard represents a complete dashboard definition loaded from YAML.
func FindByName ¶
FindByName returns the dashboard with the given name from a slice, or nil.
func LoadDir ¶
LoadDir discovers and loads all dashboard files from the project's dashboards directory.
func LoadOneByName ¶
LoadOneByName finds a dashboard by name using a two-pass approach: first a cheap metadata scan (no query execution) to find the file path, then a full load of just that one file. Returns nil, nil if not found.
func LoadTSXFile ¶
LoadTSXFile loads a single .dashboard.tsx file by transpiling it with esbuild and executing it with goja to produce a Dashboard struct.
func (*Dashboard) DateRangeFilterName ¶
DateRangeFilterName returns the name of the first date-range filter, or "".
func (*Dashboard) DefaultFilters ¶
DefaultFilters returns a map of filter names to their default values. For date-range filters, string defaults like "last_30_days" are resolved to {start, end} maps so that query templating works correctly.
func (*Dashboard) ResolveSemanticModel ¶
func (*Dashboard) ResolveWidgetSemanticJob ¶
func (d *Dashboard) ResolveWidgetSemanticJob(w *Widget) (*SemanticJob, bool, error)
func (*Dashboard) SemanticDimensions ¶
SemanticDimensions returns the semantic layer's dimensions, or nil.
func (*Dashboard) SemanticMetrics ¶
SemanticMetrics returns the semantic layer's metrics, or nil.
func (*Dashboard) SemanticSource ¶
SemanticSource returns the semantic layer's source, or nil.
func (*Dashboard) SetProjectContext ¶
func (*Dashboard) SourceConnection ¶
SourceConnection returns the connection for the semantic source, falling back to the dashboard default.
type Dimension ¶
type Dimension struct {
Column string `yaml:"column" json:"column"` // the SQL column expression (e.g. "geo.country")
Type string `yaml:"type,omitempty" json:"type,omitempty"` // "date" for chronological ordering, empty for top-N
}
Dimension defines a named grouping column for dimensional queries.
type Filter ¶
type Filter struct {
Name string `yaml:"name" json:"name"`
Type string `yaml:"type" json:"type"`
Multiple bool `yaml:"multiple,omitempty" json:"multiple,omitempty"`
Default any `yaml:"default,omitempty" json:"default,omitempty"`
Options *FilterOptions `yaml:"options,omitempty" json:"options,omitempty"`
}
type FilterOptions ¶
type FilterOptions struct {
Values []string `yaml:"values,omitempty" json:"values,omitempty"`
Query string `yaml:"query,omitempty" json:"query,omitempty"`
Connection string `yaml:"connection,omitempty" json:"connection,omitempty"`
Presets []string `yaml:"presets,omitempty" json:"presets,omitempty"` // date-range: which presets to show
}
type Metric ¶
type Metric struct {
Aggregate string `yaml:"aggregate,omitempty" json:"aggregate,omitempty"` // count, count_distinct, sum, avg, min, max
Column string `yaml:"column,omitempty" json:"column,omitempty"`
Filter map[string]string `yaml:"filter,omitempty" json:"filter,omitempty"`
Expression string `yaml:"expression,omitempty" json:"expression,omitempty"`
}
Metric defines a named scalar value computed from the source table. Use Aggregate for database-computed metrics, or Expression for client-side arithmetic over other metrics.
func (*Metric) IsExpression ¶
IsExpression returns true if this metric is computed from other metrics.
type NoQueryError ¶
type NoQueryError struct {
Widget string
}
func (*NoQueryError) Error ¶
func (e *NoQueryError) Error() string
type ProjectPaths ¶
func ResolveProjectPaths ¶
func ResolveProjectPaths(dir string) ProjectPaths
func ResolveProjectPathsForFile ¶
func ResolveProjectPathsForFile(path string) ProjectPaths
type Query ¶
type Query struct {
SQL string `yaml:"sql,omitempty" json:"sql,omitempty"`
File string `yaml:"file,omitempty" json:"file,omitempty"`
Connection string `yaml:"connection,omitempty" json:"connection,omitempty"`
Model string `yaml:"model,omitempty" json:"model,omitempty"`
Dimensions []SemanticDimensionRef `yaml:"dimensions,omitempty" json:"dimensions,omitempty"`
Metrics []string `yaml:"metrics,omitempty" json:"metrics,omitempty"`
Filters []SemanticQueryFilter `yaml:"filters,omitempty" json:"filters,omitempty"`
Segments []string `yaml:"segments,omitempty" json:"segments,omitempty"`
Sort []SemanticSort `yaml:"sort,omitempty" json:"sort,omitempty"`
Limit int `yaml:"limit,omitempty" json:"limit,omitempty"`
}
Query represents a named query definition.
func (*Query) IsSemantic ¶
type QueryNotFoundError ¶
func (*QueryNotFoundError) Error ¶
func (e *QueryNotFoundError) Error() string
type RefreshConfig ¶
type RefreshConfig struct {
Interval string `yaml:"interval" json:"interval"`
}
type SemanticDimensionRef ¶
type SemanticJob ¶
type SemanticLayer ¶
type SemanticLayer struct {
Source *Source `yaml:"source,omitempty" json:"source,omitempty"`
Metrics map[string]Metric `yaml:"metrics,omitempty" json:"metrics,omitempty"`
Dimensions map[string]Dimension `yaml:"dimensions,omitempty" json:"dimensions,omitempty"`
}
SemanticLayer groups the declarative source, metrics, and dimensions.
type SemanticQueryFilter ¶
type SemanticQueryFilter struct {
Dimension string `yaml:"dimension,omitempty" json:"dimension,omitempty"`
Operator string `yaml:"operator,omitempty" json:"operator,omitempty"`
Value any `yaml:"value,omitempty" json:"value,omitempty"`
Expression string `yaml:"expression,omitempty" json:"expression,omitempty"`
}
type SemanticSort ¶
type Source ¶
type Source struct {
Table string `yaml:"table" json:"table"`
DateColumn string `yaml:"date_column,omitempty" json:"date_column,omitempty"`
DateFormat string `yaml:"date_format,omitempty" json:"date_format,omitempty"`
Connection string `yaml:"connection,omitempty" json:"connection,omitempty"`
}
Source defines the base table for declarative metrics.
type TableColumn ¶
type ValidationError ¶
ValidationError holds all validation issues for a dashboard.
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
type ValidationSetError ¶
type ValidationSetError struct {
Errors []error
}
func (*ValidationSetError) Error ¶
func (e *ValidationSetError) Error() string
type ValueEncoding ¶ added in v0.2.1
type ValueEncoding struct {
Field string `yaml:"field" json:"field"`
Type string `yaml:"type,omitempty" json:"type,omitempty"`
Format string `yaml:"format,omitempty" json:"format,omitempty"`
}
func (*ValueEncoding) FieldString ¶ added in v0.2.1
func (v *ValueEncoding) FieldString() string
func (*ValueEncoding) MarshalJSON ¶ added in v0.2.1
func (v *ValueEncoding) MarshalJSON() ([]byte, error)
func (*ValueEncoding) MarshalYAML ¶ added in v0.2.1
func (v *ValueEncoding) MarshalYAML() (any, error)
func (*ValueEncoding) UnmarshalJSON ¶ added in v0.2.1
func (v *ValueEncoding) UnmarshalJSON(data []byte) error
func (*ValueEncoding) UnmarshalYAML ¶ added in v0.2.1
func (v *ValueEncoding) UnmarshalYAML(node *yaml.Node) error
type Widget ¶
type Widget struct {
Name string `yaml:"name" json:"name"`
Description string `yaml:"description,omitempty" json:"description,omitempty"`
Type string `yaml:"type" json:"type"` // metric, chart, table, text
Col int `yaml:"col,omitempty" json:"col,omitempty"`
// Query source (pick one)
QueryRef string `yaml:"query,omitempty" json:"query,omitempty"` // reference to queries map key
SQL string `yaml:"sql,omitempty" json:"sql,omitempty"`
File string `yaml:"file,omitempty" json:"file,omitempty"`
MetricRef string `yaml:"metric,omitempty" json:"metric,omitempty"` // reference to metrics map key
Model string `yaml:"model,omitempty" json:"model,omitempty"`
// Connection override for inline queries
Connection string `yaml:"connection,omitempty" json:"connection,omitempty"`
// Metric fields
Column string `yaml:"column,omitempty" json:"column,omitempty"`
Prefix string `yaml:"prefix,omitempty" json:"prefix,omitempty"`
Suffix string `yaml:"suffix,omitempty" json:"suffix,omitempty"`
Format string `yaml:"format,omitempty" json:"format,omitempty"`
// Declarative chart fields (use with source + metrics)
Dimension string `yaml:"dimension,omitempty" json:"dimension,omitempty"` // GROUP BY column
Granularity string `yaml:"granularity,omitempty" json:"granularity,omitempty"`
Dimensions []SemanticDimensionRef `yaml:"dimensions,omitempty" json:"dimensions,omitempty"`
MetricRefs []string `yaml:"metrics,omitempty" json:"metrics,omitempty"` // metric names to aggregate
Filters []SemanticQueryFilter `yaml:"filters,omitempty" json:"filters,omitempty"`
Segments []string `yaml:"segments,omitempty" json:"segments,omitempty"`
Sort []SemanticSort `yaml:"sort,omitempty" json:"sort,omitempty"`
Limit int `yaml:"limit,omitempty" json:"limit,omitempty"` // LIMIT for dimensional queries
// Chart fields
Chart string `yaml:"chart,omitempty" json:"chart,omitempty"` // line, bar, area, pie, scatter, bubble, combo, histogram, boxplot, funnel, sankey, heatmap, calendar, sparkline, waterfall, xmr, dumbbell, gauge, treemap, radar, candlestick
X *AxisEncoding `yaml:"x,omitempty" json:"x,omitempty"`
Y *AxisEncoding `yaml:"y,omitempty" json:"y,omitempty"`
Label string `yaml:"label,omitempty" json:"label,omitempty"` // for pie/funnel/treemap
Value *ValueEncoding `yaml:"value,omitempty" json:"value,omitempty"`
Stacked bool `yaml:"stacked,omitempty" json:"stacked,omitempty"` // for bar/area charts
Size string `yaml:"size,omitempty" json:"size,omitempty"` // bubble: size dimension column
Source string `yaml:"source,omitempty" json:"source,omitempty"` // sankey: source column
Target string `yaml:"target,omitempty" json:"target,omitempty"` // sankey: target column, gauge: target (max) column
Bins int `yaml:"bins,omitempty" json:"bins,omitempty"` // histogram: number of bins
Lines []string `yaml:"lines,omitempty" json:"lines,omitempty"` // combo: which y series render as lines
YMin string `yaml:"yMin,omitempty" json:"yMin,omitempty"` // xmr: min control limit column
YMax string `yaml:"yMax,omitempty" json:"yMax,omitempty"` // xmr: max control limit column
Open string `yaml:"open,omitempty" json:"open,omitempty"` // candlestick: open price column
High string `yaml:"high,omitempty" json:"high,omitempty"` // candlestick: high price column
Low string `yaml:"low,omitempty" json:"low,omitempty"` // candlestick: low price column
Close string `yaml:"close,omitempty" json:"close,omitempty"` // candlestick: close price column
// Table fields
Columns []TableColumn `yaml:"columns,omitempty" json:"columns,omitempty"`
// Text fields
Content string `yaml:"content,omitempty" json:"content,omitempty"`
// Image fields
Src string `yaml:"src,omitempty" json:"src,omitempty"`
Alt string `yaml:"alt,omitempty" json:"alt,omitempty"`
}
Widget represents a single dashboard widget. Query resolution priority: query (named ref) > sql (inline) > file (external).
func (*Widget) IsSemantic ¶
func (*Widget) ResolvedQuery ¶
ResolvedQuery returns the SQL and connection for this widget, resolving named query references. Widgets with MetricRef are handled separately and should not call this method.