dataface 0.3.2.dev111__py3-none-any.whl → 0.3.2.dev150__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. dataface/DATAFACE_SYNTAX.md +15 -4
  2. dataface/agent_api/docs/yaml-reference.md +33 -133
  3. dataface/agent_api/serve.py +0 -2
  4. dataface/agent_api/validate.py +8 -0
  5. dataface/cli/commands/render.py +6 -0
  6. dataface/cli/commands/serve.py +0 -6
  7. dataface/cli/main.py +20 -14
  8. dataface/core/aliases.py +27 -0
  9. dataface/core/compile/__init__.py +0 -8
  10. dataface/core/compile/channel.py +0 -13
  11. dataface/core/compile/compiler.py +73 -71
  12. dataface/core/compile/introspection.py +2 -13
  13. dataface/core/compile/models/chart/authored/_base.py +1 -1
  14. dataface/core/compile/models/chart/normalized/__init__.py +2 -0
  15. dataface/core/compile/models/chart/normalized/_base.py +26 -0
  16. dataface/core/compile/models/config.py +5 -0
  17. dataface/core/compile/models/face/authored.py +24 -89
  18. dataface/core/compile/models/query/authored.py +1 -119
  19. dataface/core/compile/models/refs.py +0 -2
  20. dataface/core/compile/models/source.py +73 -159
  21. dataface/core/compile/models/style/theme/variables.py +0 -3
  22. dataface/core/compile/normalize_charts.py +4 -152
  23. dataface/core/compile/normalize_layout.py +20 -284
  24. dataface/core/compile/normalize_queries.py +3 -506
  25. dataface/core/compile/normalizer.py +4 -10
  26. dataface/core/compile/palette.py +19 -7
  27. dataface/core/compile/validator.py +121 -44
  28. dataface/core/compile/yaml_error_formatter.py +107 -2
  29. dataface/core/dashboard.py +3 -1
  30. dataface/core/defaults/default_config.yml +4 -0
  31. dataface/core/defaults/themes/_base.yaml +0 -1
  32. dataface/core/defaults/themes/editorial.yaml +3 -0
  33. dataface/core/defaults/themes/stark.yaml +8 -0
  34. dataface/core/diagnostics/__init__.py +10 -0
  35. dataface/core/diagnostics/codes_compile.py +4 -2
  36. dataface/core/diagnostics/codes_execute.py +70 -0
  37. dataface/core/diagnostics/codes_render.py +58 -4
  38. dataface/core/execute/adapters/__init__.py +1 -1
  39. dataface/core/execute/cache_keys.py +4 -9
  40. dataface/core/execute/executor.py +25 -3
  41. dataface/core/execute/file_source_materializer.py +185 -32
  42. dataface/core/execute/trivial_local_cache.py +5 -2
  43. dataface/core/inspect/__init__.py +0 -1
  44. dataface/core/project.py +6 -2
  45. dataface/core/render/chart/mark_extents.py +339 -0
  46. dataface/core/render/chart/rendering.py +97 -34
  47. dataface/core/render/conditions.py +122 -0
  48. dataface/core/render/controls.py +60 -187
  49. dataface/core/render/data_format.py +1 -1
  50. dataface/core/render/face_resolve.py +7 -0
  51. dataface/core/render/faces.py +94 -30
  52. dataface/core/render/layout_sizing.py +46 -0
  53. dataface/core/render/renderer.py +14 -1
  54. dataface/core/render/sizing.py +42 -105
  55. dataface/core/render/svg_utils.py +60 -14
  56. dataface/core/render/terminal.py +1 -1
  57. dataface/core/render/variables_layout.py +211 -0
  58. dataface/core/render/variables_resolve.py +376 -0
  59. dataface/core/render/variables_strip.py +291 -368
  60. dataface/core/render/warnings/base.py +18 -0
  61. dataface/core/render/warnings/layout_min_exceeds_height.py +68 -0
  62. dataface/core/render/warnings/registry.py +2 -0
  63. dataface/core/serve/alias_index.py +16 -22
  64. dataface/data/schemas/board-resolved/board-resolved.schema.json +1 -499
  65. {dataface-0.3.2.dev111.dist-info → dataface-0.3.2.dev150.dist-info}/METADATA +1 -3
  66. {dataface-0.3.2.dev111.dist-info → dataface-0.3.2.dev150.dist-info}/RECORD +69 -67
  67. dataface/core/inspect/partials/categorical.yml +0 -38
  68. dataface/core/inspect/partials/date.yml +0 -38
  69. dataface/core/inspect/partials/numeric.yml +0 -53
  70. dataface/core/inspect/templates/charts.yml +0 -94
  71. {dataface-0.3.2.dev111.dist-info → dataface-0.3.2.dev150.dist-info}/WHEEL +0 -0
  72. {dataface-0.3.2.dev111.dist-info → dataface-0.3.2.dev150.dist-info}/entry_points.txt +0 -0
  73. {dataface-0.3.2.dev111.dist-info → dataface-0.3.2.dev150.dist-info}/licenses/LICENSE +0 -0
@@ -252,8 +252,9 @@ aliases:
252
252
  ```
253
253
 
254
254
  Rules:
255
- - An alias must not collide with a real face file path — the server raises an error at startup if it does.
256
- - Each alias must be unique across the project — two faces claiming the same alias is a startup error.
255
+ - Every alias must be absolute (leading `/`) — a relative entry fails validation on that face.
256
+ - An alias must not collide with a real face file path — `dft serve` raises an error at startup if it does.
257
+ - Each alias must be unique across the project — two faces claiming the same alias is a startup error under `dft serve`. A host with no startup step resolves a duplicate to the first face by slug instead of reporting it.
257
258
  - Aliasing a generated system route (data or inspector view) is allowed: the redirect takes precedence, letting you override what that URL serves.
258
259
 
259
260
  #### Parameterized aliases (capture a path segment into a variable)
@@ -613,7 +614,11 @@ Each block below shows the minimum-viable shape for one chart type. They are sta
613
614
  type: bar
614
615
  x: category
615
616
  y: value
616
- color: group # Optional second dimension; stacks by default
617
+ color: group # Optional second dimension; grouped side by side by default
618
+ style:
619
+ orientation: vertical # vertical = column chart; horizontal = horizontal bar chart.
620
+ # Auto-resolves from x's column type when omitted: categorical x → horizontal.
621
+ stack: zero # see the stack table under "area" — bar takes the same values
617
622
 
618
623
  # line — temporal/ordered x, numeric y
619
624
  type: line
@@ -625,8 +630,14 @@ color: segment # Optional: one line per segment
625
630
  type: area
626
631
  x: date
627
632
  y: value
633
+ color: segment # Required for stacking — stack modes split by this field
628
634
  style:
629
- stack: normalize # 100% stacked
635
+ # stack names the shape you get. All four values work on bar and area alike:
636
+ stack: zero # stacked
637
+ # stack: none # overlapping — bar groups side by side, area overlays.
638
+ # The default when color: is set.
639
+ # stack: normalize # 100% stacked — every column fills the full height
640
+ # stack: center # streamgraph — stacked around a centered baseline
630
641
 
631
642
  # scatter — x and y numeric
632
643
  type: scatter
@@ -15,10 +15,10 @@ AuthoredFace (dataface) definition from YAML.
15
15
  | `source` | str | ✓ | Default source name for all queries in this face. Inheritable via meta.yaml cascade. |
16
16
  | `cache` | [Cache](#cache) | ✓ | Cache policy for every query in this dashboard, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts the whole dashboard out. Inheritable via the meta.yaml cascade. |
17
17
  | `variables` | dict[str, [Variable](#variable) \| VariableRef] | ✓ | Variable definitions for dynamic filtering and UI controls. |
18
- | `queries` | dict[str, [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| [LookmlQuery](#lookmlquery) \| [LookmlMergeQuery](#lookmlmergequery) \| QueryRef] | ✓ | Named query definitions (SQL, CSV, MetricFlow, HTTP, etc.). |
18
+ | `queries` | dict[str, [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| QueryRef] | ✓ | Named query definitions (SQL, CSV, MetricFlow, HTTP, etc.). |
19
19
  | `charts` | dict[str, [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart) \| ChartRef] | ✓ | Named chart definitions. When no explicit layout is present, charts render as an implicit row layout in authored order. |
20
- | `rows` | list[str \| [Face](#face) \| [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart) \| [ForeachItem](#foreachitem) \| dict[str, [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart)]] | ✓ | Vertical stack layout: list of chart names or inline chart/face definitions. |
21
- | `cols` | list[str \| [Face](#face) \| [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart) \| [ForeachItem](#foreachitem) \| dict[str, [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart)]] | ✓ | Horizontal layout: list of chart names or inline chart/face definitions. |
20
+ | `rows` | list[str \| [Face](#face) \| [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart) \| dict[str, [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart)]] | ✓ | Vertical stack layout: list of chart names or inline chart/face definitions. |
21
+ | `cols` | list[str \| [Face](#face) \| [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart) \| dict[str, [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart)]] | ✓ | Horizontal layout: list of chart names or inline chart/face definitions. |
22
22
  | `grid` | [GridLayout](#gridlayout) | ✓ | CSS-grid style layout with explicit row/column placement. |
23
23
  | `tabs` | [TabLayout](#tablayout) | ✓ | Tabbed navigation layout where each tab contains its own layout. |
24
24
  | `card_gap` | bool | ✓ | When True, adds gap between cards. Default: cards are edge-to-edge (0 gap). |
@@ -55,7 +55,7 @@ Variable definition from YAML.
55
55
  | `visible` | bool | ✓ | When False, the variable is not rendered in the UI but can still be set via URL params. |
56
56
  | `enabled` | bool \| str \| [SingleRowBoolProbe](#singlerowboolprobe) | ✓ | Enable this control. Accepts: static bool; a variable name or Jinja boolean expression string (no {{ }} required — bare names auto-wrap); or a {query, column} form that reads a single boolean cell from a named query. None = enabled. Absent variable in a string expression raises (use a default). |
57
57
  | `column` | str | ✓ | Column name in the query result to use as option values. |
58
- | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| [LookmlQuery](#lookmlquery) \| [LookmlMergeQuery](#lookmlmergequery) | ✓ | Query name or inline query definition for populating options. |
58
+ | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) | ✓ | Query name or inline query definition for populating options. |
59
59
  | `dimension` | str | ✓ | MetricFlow dimension name for populating options. |
60
60
  | `measure` | str | ✓ | MetricFlow measure name for populating options. |
61
61
  | `model` | str | ✓ | dbt model name for populating options. |
@@ -159,54 +159,6 @@ dbt source schema query.
159
159
  | `table` | str | ✓ | Table name for schema queries. |
160
160
  | `column` | str | ✓ | Column name for schema queries. |
161
161
 
162
- <a id="lookmlquery"></a>
163
- ## LookmlQuery
164
- LookML query rooted at one explore.
165
-
166
- | Field | Type | Optional | Description |
167
- |-------|------|:--------:|-------------|
168
- | `explore` | str | | LookML explore name. Presence of this key infers type: lookml. Use a merge query instead to combine multiple sources. |
169
- | `source` | str \| dict[str, Any] | ✓ | Source name reference, or an inline file path (e.g. `./data/sales.csv`). File paths are detected by `/` or data file extension. An inline connection-bearing dict (`{type: postgres, ...}`) is rejected at compile time — reference a named source instead. |
170
- | `description` | str | ✓ | Human-readable description of the query. Used by AI search and tooling. |
171
- | `ignore` | list[str] | ✓ | Diagnostic codes to suppress for this query (e.g., ['WARN-FANOUT-RISK', 'WARN-REAGGREGATION']). |
172
- | `cache` | [Cache](#cache) | ✓ | Cache policy override for this query, e.g. cache: 5m — refines the policy inherited from the source and project scopes; cache: false opts out of result caching entirely. Queries with cache: false cannot be used as {{ queries.X.cache }} upstream references. |
173
- | `type` | enum: "lookml" | ✓ | Query adapter type. |
174
- | `fields` | list[str] | ✓ | Qualified 'view.field' refs to select. Optional at authoring time: collected from chart channels when absent. |
175
- | `sorts` | list[str] | ✓ | Looker sort clauses, e.g. ['view.field', 'view.other desc']. Lowered to ORDER BY via likeml. |
176
- | `pivots` | list[str] | ✓ | Qualified 'view.field' refs to pivot on. |
177
- | `pivots_unwrapped` | bool | ✓ | Which of Looker's two pivot SQL shapes to emit: False/None = wrapped (5-layer DENSE_RANK), True = plain GROUP BY. |
178
- | `total` | bool | ✓ | Looker grand-totals flag. |
179
- | `subtotals` | list[str] | ✓ | Dimension refs to subtotal via GROUP BY ROLLUP. |
180
- | `filter_expression` | str | ✓ | Looker query-level free-form boolean filter over ${view.field} refs. |
181
- | `dynamic_fields` | list[dict[str, Any]] | ✓ | Looker dynamic fields: custom measures / custom dimensions synthesized into SQL. Table calculations compose as a derived wrapper query, not here. |
182
- | `limit` | int | ✓ | Maximum number of rows returned. |
183
- | `column_limit` | int | ✓ | Looker column_limit — caps wrapped-pivot columns. |
184
- | `filters` | dict[str, Any] | ✓ | RAW Looker filter expressions keyed by 'view.field' (e.g. "13 months", "gold") — translated to SQL predicates by likeml. |
185
-
186
- <a id="lookmlmergequery"></a>
187
- ## LookmlMergeQuery
188
- LookML query that merges multiple sources.
189
-
190
- | Field | Type | Optional | Description |
191
- |-------|------|:--------:|-------------|
192
- | `merge` | list[dict[str, Any]] | | LookML merge sources — a list of source specs. Each is either an explore spec ({explore, fields, filters?, merge_on?}) or a query reference ({query, columns, merge_on?}) for a derived source such as a table-calc wrapper. First is the primary; each secondary's `merge_on` maps its key to the primary's. Presence of this key infers type: lookml. Compiled to a FULL OUTER JOIN via likeml. |
193
- | `source` | str \| dict[str, Any] | ✓ | Source name reference, or an inline file path (e.g. `./data/sales.csv`). File paths are detected by `/` or data file extension. An inline connection-bearing dict (`{type: postgres, ...}`) is rejected at compile time — reference a named source instead. |
194
- | `description` | str | ✓ | Human-readable description of the query. Used by AI search and tooling. |
195
- | `ignore` | list[str] | ✓ | Diagnostic codes to suppress for this query (e.g., ['WARN-FANOUT-RISK', 'WARN-REAGGREGATION']). |
196
- | `cache` | [Cache](#cache) | ✓ | Cache policy override for this query, e.g. cache: 5m — refines the policy inherited from the source and project scopes; cache: false opts out of result caching entirely. Queries with cache: false cannot be used as {{ queries.X.cache }} upstream references. |
197
- | `type` | enum: "lookml" | ✓ | Query adapter type. |
198
- | `fields` | list[str] | ✓ | Qualified 'view.field' refs to select. Optional at authoring time: collected from chart channels when absent. |
199
- | `sorts` | list[str] | ✓ | Looker sort clauses, e.g. ['view.field', 'view.other desc']. Lowered to ORDER BY via likeml. |
200
- | `pivots` | list[str] | ✓ | Qualified 'view.field' refs to pivot on. |
201
- | `pivots_unwrapped` | bool | ✓ | Which of Looker's two pivot SQL shapes to emit: False/None = wrapped (5-layer DENSE_RANK), True = plain GROUP BY. |
202
- | `total` | bool | ✓ | Looker grand-totals flag. |
203
- | `subtotals` | list[str] | ✓ | Dimension refs to subtotal via GROUP BY ROLLUP. |
204
- | `filter_expression` | str | ✓ | Looker query-level free-form boolean filter over ${view.field} refs. |
205
- | `dynamic_fields` | list[dict[str, Any]] | ✓ | Looker dynamic fields: custom measures / custom dimensions synthesized into SQL. Table calculations compose as a derived wrapper query, not here. |
206
- | `limit` | int | ✓ | Maximum number of rows returned. |
207
- | `column_limit` | int | ✓ | Looker column_limit — caps wrapped-pivot columns. |
208
- | `filters` | dict[str, Any] | ✓ | RAW Looker filter expressions keyed by 'view.field' (e.g. "13 months", "gold") — translated to SQL predicates by likeml. |
209
-
210
162
  <a id="barchart"></a>
211
163
  ## BarChart
212
164
  Authored patch for bar and histogram charts.
@@ -217,9 +169,9 @@ Authored patch for bar and histogram charts.
217
169
  | `conditional_formatting` | dict[str, [FieldConditionalFormatting](#fieldconditionalformatting)] | ✓ | Discrete rule-driven style overrides indexed by column name. |
218
170
  | `id` | str | ✓ | Explicit chart ID (auto-generated from the chart's YAML key if omitted). |
219
171
  | `description` | str | ✓ | Human-readable description used by AI search and context tooltips. |
220
- | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| [LookmlQuery](#lookmlquery) \| [LookmlMergeQuery](#lookmlmergequery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
172
+ | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
221
173
  | `link` | str | ✓ | Click-through URL template for drill-down links. |
222
- | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'model.explore' for a LookML source, or 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the LookML catalog / dbt semantic manifest. Mutually exclusive with `query:`. |
174
+ | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the dbt semantic manifest. Mutually exclusive with `query:`. |
223
175
  | `warnings_ignore` | list[str] | ✓ | Codes of render warnings to suppress for this chart. |
224
176
  | `title` | str | ✓ | Chart title displayed above the chart (not used on type: kpi). |
225
177
  | `subtitle` | str | ✓ | Chart subtitle displayed below the title. |
@@ -246,9 +198,9 @@ Authored patch for line charts.
246
198
  | `conditional_formatting` | dict[str, [FieldConditionalFormatting](#fieldconditionalformatting)] | ✓ | Discrete rule-driven style overrides indexed by column name. |
247
199
  | `id` | str | ✓ | Explicit chart ID (auto-generated from the chart's YAML key if omitted). |
248
200
  | `description` | str | ✓ | Human-readable description used by AI search and context tooltips. |
249
- | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| [LookmlQuery](#lookmlquery) \| [LookmlMergeQuery](#lookmlmergequery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
201
+ | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
250
202
  | `link` | str | ✓ | Click-through URL template for drill-down links. |
251
- | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'model.explore' for a LookML source, or 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the LookML catalog / dbt semantic manifest. Mutually exclusive with `query:`. |
203
+ | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the dbt semantic manifest. Mutually exclusive with `query:`. |
252
204
  | `warnings_ignore` | list[str] | ✓ | Codes of render warnings to suppress for this chart. |
253
205
  | `title` | str | ✓ | Chart title displayed above the chart (not used on type: kpi). |
254
206
  | `subtitle` | str | ✓ | Chart subtitle displayed below the title. |
@@ -275,9 +227,9 @@ Authored patch for area charts.
275
227
  | `conditional_formatting` | dict[str, [FieldConditionalFormatting](#fieldconditionalformatting)] | ✓ | Discrete rule-driven style overrides indexed by column name. |
276
228
  | `id` | str | ✓ | Explicit chart ID (auto-generated from the chart's YAML key if omitted). |
277
229
  | `description` | str | ✓ | Human-readable description used by AI search and context tooltips. |
278
- | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| [LookmlQuery](#lookmlquery) \| [LookmlMergeQuery](#lookmlmergequery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
230
+ | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
279
231
  | `link` | str | ✓ | Click-through URL template for drill-down links. |
280
- | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'model.explore' for a LookML source, or 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the LookML catalog / dbt semantic manifest. Mutually exclusive with `query:`. |
232
+ | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the dbt semantic manifest. Mutually exclusive with `query:`. |
281
233
  | `warnings_ignore` | list[str] | ✓ | Codes of render warnings to suppress for this chart. |
282
234
  | `title` | str | ✓ | Chart title displayed above the chart (not used on type: kpi). |
283
235
  | `subtitle` | str | ✓ | Chart subtitle displayed below the title. |
@@ -304,9 +256,9 @@ Authored patch for scatter charts.
304
256
  | `conditional_formatting` | dict[str, [FieldConditionalFormatting](#fieldconditionalformatting)] | ✓ | Discrete rule-driven style overrides indexed by column name. |
305
257
  | `id` | str | ✓ | Explicit chart ID (auto-generated from the chart's YAML key if omitted). |
306
258
  | `description` | str | ✓ | Human-readable description used by AI search and context tooltips. |
307
- | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| [LookmlQuery](#lookmlquery) \| [LookmlMergeQuery](#lookmlmergequery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
259
+ | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
308
260
  | `link` | str | ✓ | Click-through URL template for drill-down links. |
309
- | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'model.explore' for a LookML source, or 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the LookML catalog / dbt semantic manifest. Mutually exclusive with `query:`. |
261
+ | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the dbt semantic manifest. Mutually exclusive with `query:`. |
310
262
  | `warnings_ignore` | list[str] | ✓ | Codes of render warnings to suppress for this chart. |
311
263
  | `title` | str | ✓ | Chart title displayed above the chart (not used on type: kpi). |
312
264
  | `subtitle` | str | ✓ | Chart subtitle displayed below the title. |
@@ -334,9 +286,9 @@ Authored patch for heatmap charts.
334
286
  | `type` | enum: "heatmap" | | Heatmap chart type. |
335
287
  | `id` | str | ✓ | Explicit chart ID (auto-generated from the chart's YAML key if omitted). |
336
288
  | `description` | str | ✓ | Human-readable description used by AI search and context tooltips. |
337
- | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| [LookmlQuery](#lookmlquery) \| [LookmlMergeQuery](#lookmlmergequery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
289
+ | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
338
290
  | `link` | str | ✓ | Click-through URL template for drill-down links. |
339
- | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'model.explore' for a LookML source, or 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the LookML catalog / dbt semantic manifest. Mutually exclusive with `query:`. |
291
+ | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the dbt semantic manifest. Mutually exclusive with `query:`. |
340
292
  | `warnings_ignore` | list[str] | ✓ | Codes of render warnings to suppress for this chart. |
341
293
  | `title` | str | ✓ | Chart title displayed above the chart (not used on type: kpi). |
342
294
  | `subtitle` | str | ✓ | Chart subtitle displayed below the title. |
@@ -363,9 +315,9 @@ Authored patch for pie and donut charts.
363
315
  | `conditional_formatting` | dict[str, [FieldConditionalFormatting](#fieldconditionalformatting)] | ✓ | Discrete rule-driven style overrides indexed by column name. |
364
316
  | `id` | str | ✓ | Explicit chart ID (auto-generated from the chart's YAML key if omitted). |
365
317
  | `description` | str | ✓ | Human-readable description used by AI search and context tooltips. |
366
- | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| [LookmlQuery](#lookmlquery) \| [LookmlMergeQuery](#lookmlmergequery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
318
+ | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
367
319
  | `link` | str | ✓ | Click-through URL template for drill-down links. |
368
- | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'model.explore' for a LookML source, or 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the LookML catalog / dbt semantic manifest. Mutually exclusive with `query:`. |
320
+ | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the dbt semantic manifest. Mutually exclusive with `query:`. |
369
321
  | `warnings_ignore` | list[str] | ✓ | Codes of render warnings to suppress for this chart. |
370
322
  | `title` | str | ✓ | Chart title displayed above the chart (not used on type: kpi). |
371
323
  | `subtitle` | str | ✓ | Chart subtitle displayed below the title. |
@@ -386,9 +338,9 @@ Authored patch for KPI (key performance indicator) charts.
386
338
  | `conditional_formatting` | dict[str, [FieldConditionalFormatting](#fieldconditionalformatting)] | ✓ | Discrete rule-driven style overrides indexed by column name. |
387
339
  | `id` | str | ✓ | Explicit chart ID (auto-generated from the chart's YAML key if omitted). |
388
340
  | `description` | str | ✓ | Human-readable description used by AI search and context tooltips. |
389
- | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| [LookmlQuery](#lookmlquery) \| [LookmlMergeQuery](#lookmlmergequery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
341
+ | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
390
342
  | `link` | str | ✓ | Click-through URL template for drill-down links. |
391
- | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'model.explore' for a LookML source, or 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the LookML catalog / dbt semantic manifest. Mutually exclusive with `query:`. |
343
+ | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the dbt semantic manifest. Mutually exclusive with `query:`. |
392
344
  | `warnings_ignore` | list[str] | ✓ | Codes of render warnings to suppress for this chart. |
393
345
  | `label` | str | ✓ | KPI label rendered above the headline value. |
394
346
  | `variant` | enum: "stacked", "inline", "compact" | ✓ | Layout variant. 'stacked' (default) shows value, label, and support on three vertical lines. 'inline' lays value, label, and support out on a single baseline-aligned row. 'compact' is 2-column — big value on the left, up to two stacked lines on the right with the bottom line sharing baseline with the value; a lone `support` block splits across the two right-column lines. |
@@ -406,9 +358,9 @@ Authored patch for table charts.
406
358
  | `conditional_formatting` | dict[str, [FieldConditionalFormatting](#fieldconditionalformatting)] | ✓ | Discrete rule-driven style overrides indexed by column name. |
407
359
  | `id` | str | ✓ | Explicit chart ID (auto-generated from the chart's YAML key if omitted). |
408
360
  | `description` | str | ✓ | Human-readable description used by AI search and context tooltips. |
409
- | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| [LookmlQuery](#lookmlquery) \| [LookmlMergeQuery](#lookmlmergequery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
361
+ | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
410
362
  | `link` | str | ✓ | Click-through URL template for drill-down links. |
411
- | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'model.explore' for a LookML source, or 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the LookML catalog / dbt semantic manifest. Mutually exclusive with `query:`. |
363
+ | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the dbt semantic manifest. Mutually exclusive with `query:`. |
412
364
  | `warnings_ignore` | list[str] | ✓ | Codes of render warnings to suppress for this chart. |
413
365
  | `title` | str | ✓ | Chart title displayed above the chart (not used on type: kpi). |
414
366
  | `subtitle` | str | ✓ | Chart subtitle displayed below the title. |
@@ -427,9 +379,9 @@ Authored patch for point_map and bubble_map charts.
427
379
  | `conditional_formatting` | dict[str, [FieldConditionalFormatting](#fieldconditionalformatting)] | ✓ | Discrete rule-driven style overrides indexed by column name. |
428
380
  | `id` | str | ✓ | Explicit chart ID (auto-generated from the chart's YAML key if omitted). |
429
381
  | `description` | str | ✓ | Human-readable description used by AI search and context tooltips. |
430
- | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| [LookmlQuery](#lookmlquery) \| [LookmlMergeQuery](#lookmlmergequery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
382
+ | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
431
383
  | `link` | str | ✓ | Click-through URL template for drill-down links. |
432
- | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'model.explore' for a LookML source, or 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the LookML catalog / dbt semantic manifest. Mutually exclusive with `query:`. |
384
+ | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the dbt semantic manifest. Mutually exclusive with `query:`. |
433
385
  | `warnings_ignore` | list[str] | ✓ | Codes of render warnings to suppress for this chart. |
434
386
  | `title` | str | ✓ | Chart title displayed above the chart (not used on type: kpi). |
435
387
  | `subtitle` | str | ✓ | Chart subtitle displayed below the title. |
@@ -457,9 +409,9 @@ Authored patch for map and geoshape charts.
457
409
  | `conditional_formatting` | dict[str, [FieldConditionalFormatting](#fieldconditionalformatting)] | ✓ | Discrete rule-driven style overrides indexed by column name. |
458
410
  | `id` | str | ✓ | Explicit chart ID (auto-generated from the chart's YAML key if omitted). |
459
411
  | `description` | str | ✓ | Human-readable description used by AI search and context tooltips. |
460
- | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| [LookmlQuery](#lookmlquery) \| [LookmlMergeQuery](#lookmlmergequery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
412
+ | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
461
413
  | `link` | str | ✓ | Click-through URL template for drill-down links. |
462
- | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'model.explore' for a LookML source, or 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the LookML catalog / dbt semantic manifest. Mutually exclusive with `query:`. |
414
+ | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the dbt semantic manifest. Mutually exclusive with `query:`. |
463
415
  | `warnings_ignore` | list[str] | ✓ | Codes of render warnings to suppress for this chart. |
464
416
  | `title` | str | ✓ | Chart title displayed above the chart (not used on type: kpi). |
465
417
  | `subtitle` | str | ✓ | Chart subtitle displayed below the title. |
@@ -494,9 +446,9 @@ Authored patch for spark_bar charts (compact horizontal bars).
494
446
  | `type` | enum: "spark_bar" | | SparkBar chart type. |
495
447
  | `id` | str | ✓ | Explicit chart ID (auto-generated from the chart's YAML key if omitted). |
496
448
  | `description` | str | ✓ | Human-readable description used by AI search and context tooltips. |
497
- | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| [LookmlQuery](#lookmlquery) \| [LookmlMergeQuery](#lookmlmergequery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
449
+ | `query` | str \| [SqlQuery](#sqlquery) \| [MetricflowQuery](#metricflowquery) \| [HttpQuery](#httpquery) \| [ValuesQuery](#valuesquery) \| [CompactValuesQuery](#compactvaluesquery) \| [SchemaQuery](#schemaquery) \| QueryRef | ✓ | Named query reference, inline AuthoredQuery, or SQL string shorthand. |
498
450
  | `link` | str | ✓ | Click-through URL template for drill-down links. |
499
- | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'model.explore' for a LookML source, or 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the LookML catalog / dbt semantic manifest. Mutually exclusive with `query:`. |
451
+ | `model` | str | ✓ | Semantic-layer entry point, two dot-joined names: 'source.semantic_model' for a dbt_profile (MetricFlow) source. Channel fields name the model's fields directly; roles are inferred from the dbt semantic manifest. Mutually exclusive with `query:`. |
500
452
  | `warnings_ignore` | list[str] | ✓ | Codes of render warnings to suppress for this chart. |
501
453
  | `title` | str | ✓ | Chart title displayed above the chart (not used on type: kpi). |
502
454
  | `subtitle` | str | ✓ | Chart subtitle displayed below the title. |
@@ -504,14 +456,6 @@ Authored patch for spark_bar charts (compact horizontal bars).
504
456
  | `y` | str \| list[str] | ✓ | Y-axis (value) column name(s). |
505
457
  | `style` | [SparkBarChartStyle](#sparkbarchartstyle) | ✓ | Chart-local style overrides. |
506
458
 
507
- <a id="foreachitem"></a>
508
- ## ForeachItem
509
- Top-level foreach construct in a layout list.
510
-
511
- | Field | Type | Description |
512
- |-------|------|-------------|
513
- | `foreach` | [ForeachConfig](#foreachconfig) | foreach loop configuration with query, as, and items. |
514
-
515
459
  <a id="gridlayout"></a>
516
460
  ## GridLayout
517
461
  Grid layout configuration.
@@ -1050,23 +994,13 @@ Authored overlay for SparkBarChartStyle. Produced by cascade from theme YAML.
1050
994
  | `border` | [BorderStyle](#borderstyle) | ✓ | Spark_bar outer border style. |
1051
995
  | `subtitle` | [SubtitleStyle](#subtitlestyle) | ✓ | Spark_bar subtitle font-sizing constants. |
1052
996
 
1053
- <a id="foreachconfig"></a>
1054
- ## ForeachConfig
1055
- foreach loop configuration.
1056
-
1057
- | Field | Type | Description |
1058
- |-------|------|-------------|
1059
- | `query` | [ForeachQuery](#foreachquery) | Inline data source providing the rows to iterate over. |
1060
- | `as` | str | Variable name bound to each row (accessible as {{ as.field }}). |
1061
- | `items` | list[str \| [Face](#face) \| [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart) \| [ForeachItem](#foreachitem) \| dict[str, [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart)]] | Layout item templates resolved once per data row. |
1062
-
1063
997
  <a id="griditem"></a>
1064
998
  ## GridItem
1065
999
  Grid layout item with position and span.
1066
1000
 
1067
1001
  | Field | Type | Optional | Description |
1068
1002
  |-------|------|:--------:|-------------|
1069
- | `item` | str \| [Face](#face) \| [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart) \| [ForeachItem](#foreachitem) \| dict[str, [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart)] | | Chart name or inline chart/face definition to place in this grid cell. |
1003
+ | `item` | str \| [Face](#face) \| [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart) \| dict[str, [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart)] | | Chart name or inline chart/face definition to place in this grid cell. |
1070
1004
  | `col` | int | ✓ | Column position (0-indexed). Auto-placed if omitted. |
1071
1005
  | `row` | int | ✓ | Row position (0-indexed). Auto-placed if omitted. |
1072
1006
  | `col_span` | int | ✓ | Number of columns to span (width in grid units). |
@@ -1086,8 +1020,8 @@ Tab layout item.
1086
1020
  | `description` | str | ✓ | Optional metadata for AI search and context tooltips. |
1087
1021
  | `text` | str | ✓ | Markdown text content shown in this tab. |
1088
1022
  | `style` | [Style](#style) | ✓ | Style patch for this tab's content area. |
1089
- | `rows` | list[str \| [Face](#face) \| [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart) \| [ForeachItem](#foreachitem) \| dict[str, [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart)]] | ✓ | Vertical stack layout for this tab's content. |
1090
- | `cols` | list[str \| [Face](#face) \| [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart) \| [ForeachItem](#foreachitem) \| dict[str, [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart)]] | ✓ | Horizontal layout for this tab's content. |
1023
+ | `rows` | list[str \| [Face](#face) \| [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart) \| dict[str, [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart)]] | ✓ | Vertical stack layout for this tab's content. |
1024
+ | `cols` | list[str \| [Face](#face) \| [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart) \| dict[str, [BarChart](#barchart) \| [LineChart](#linechart) \| [AreaChart](#areachart) \| [ScatterChart](#scatterchart) \| [HeatmapChart](#heatmapchart) \| [PieChart](#piechart) \| [KpiChart](#kpichart) \| [TableChart](#tablechart) \| [PointMapChart](#pointmapchart) \| [GeoshapeChart](#geoshapechart) \| [CalloutChart](#calloutchart) \| [SparkBarChart](#sparkbarchart)]] | ✓ | Horizontal layout for this tab's content. |
1091
1025
  | `grid` | [GridLayout](#gridlayout) | ✓ | CSS-grid layout for this tab's content. |
1092
1026
  | `tabs` | [TabLayout](#tablayout) | ✓ | Nested tab layout (tabs within tabs). |
1093
1027
 
@@ -1242,7 +1176,6 @@ Authored overlay for VariablesStyle. Variable controls chrome styling.
1242
1176
  | `label` | [VariablesLabelStyle](#variableslabelstyle) | ✓ | Variable label typography. |
1243
1177
  | `value` | [VariablesValueStyle](#variablesvaluestyle) | ✓ | Variable value typography. |
1244
1178
  | `placeholder` | [VariablesPlaceholderStyle](#variablesplaceholderstyle) | ✓ | Style for unselected/hint text in variable inputs. |
1245
- | `line_height` | float | ✓ | Line height for variable control text in pixels. |
1246
1179
  | `padding` | float | ✓ | Outer padding around the variables panel in pixels. |
1247
1180
  | `container_height` | float | ✓ | Height of the variables panel container in pixels. |
1248
1181
  | `container_padding` | float | ✓ | Inner padding of the variables panel container in pixels. |
@@ -1921,16 +1854,6 @@ Authored overlay for SparkBarCountStyle. Count-value sub-block for SparkBarChart
1921
1854
  | `visible` | bool | ✓ | Show count/value text next to bars. |
1922
1855
  | `width` | float | ✓ | Reserved width for bar count text in pixels. |
1923
1856
 
1924
- <a id="foreachquery"></a>
1925
- ## ForeachQuery
1926
- Inline data source for compile-time foreach loops.
1927
-
1928
- | Field | Type | Optional | Description |
1929
- |-------|------|:--------:|-------------|
1930
- | `data` | list[dict[str, Any]] | ✓ | Inline row data for compile-time iteration. |
1931
- | `static_data` | list[dict[str, Any]] | ✓ | Alias for data; inline row data for compile-time iteration. |
1932
- | `palette` | str | ✓ | Palette name to iterate its live stops from the palette YAML source of truth (one row per stop: {n: 1-indexed position, hex: sRGB hex}). Accepts the same 'name:steps' / 'name_r' shorthand as palette(). |
1933
-
1934
1857
  <a id="titlewidthoffsetsstyle"></a>
1935
1858
  ## TitleWidthOffsetsStyle
1936
1859
  Authored overlay for TitleWidthOffsetsStyle. Additive level offsets applied to a face/chart title's heading level, by card pixel width.
@@ -2985,8 +2908,6 @@ Postgres source configuration.
2985
2908
  | `password` | str | | Database password (dbt accepts pass as an input alias). |
2986
2909
  | `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
2987
2910
  | `max_query_duration_seconds` | int | ✓ | Maximum execution time for one query in seconds. Overrides execution.max_query_duration_seconds for this source. |
2988
- | `lookml_path` | str | ✓ | Relative path to the directory of .lkml files backing this source's models. |
2989
- | `models` | dict[str, [LookMLModelConfig](#lookmlmodelconfig)] | ✓ | Named LookML model collections nested under this source. |
2990
2911
  | `attribution` | dict[str, str] | ✓ | Cost-attribution pairs sent with every query against this source, e.g. attribution: {team: analytics}. Emitted as BigQuery job labels and as a query comment elsewhere. Keys and values must match BigQuery's label rules ([a-z][a-z0-9_-]{0,62} / [a-z0-9_-]{0,63}). The dft_ prefix and the app key are reserved for the engine's own identity. |
2991
2912
  | `port` | int | ✓ | Database port number. |
2992
2913
  | `schema` | str | ✓ | Default schema for queries. |
@@ -3012,8 +2933,6 @@ Snowflake source configuration.
3012
2933
  | `database` | str | | Snowflake database name. |
3013
2934
  | `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
3014
2935
  | `max_query_duration_seconds` | int | ✓ | Maximum execution time for one query in seconds. Overrides execution.max_query_duration_seconds for this source. |
3015
- | `lookml_path` | str | ✓ | Relative path to the directory of .lkml files backing this source's models. |
3016
- | `models` | dict[str, [LookMLModelConfig](#lookmlmodelconfig)] | ✓ | Named LookML model collections nested under this source. |
3017
2936
  | `attribution` | dict[str, str] | ✓ | Cost-attribution pairs sent with every query against this source, e.g. attribution: {team: analytics}. Emitted as BigQuery job labels and as a query comment elsewhere. Keys and values must match BigQuery's label rules ([a-z][a-z0-9_-]{0,62} / [a-z0-9_-]{0,63}). The dft_ prefix and the app key are reserved for the engine's own identity. |
3018
2937
  | `user` | str | ✓ | Snowflake user name. Omit for token-based authentication when supported. |
3019
2938
  | `password` | str | ✓ | Snowflake password. Omit when using OAuth or key-pair auth. |
@@ -3054,8 +2973,6 @@ BigQuery source configuration.
3054
2973
  | `dataset` | str | | BigQuery dataset name (equivalent to schema). |
3055
2974
  | `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
3056
2975
  | `max_query_duration_seconds` | int | ✓ | Maximum execution time for one query in seconds. Overrides execution.max_query_duration_seconds for this source. |
3057
- | `lookml_path` | str | ✓ | Relative path to the directory of .lkml files backing this source's models. |
3058
- | `models` | dict[str, [LookMLModelConfig](#lookmlmodelconfig)] | ✓ | Named LookML model collections nested under this source. |
3059
2976
  | `attribution` | dict[str, str] | ✓ | Cost-attribution pairs sent with every query against this source, e.g. attribution: {team: analytics}. Emitted as BigQuery job labels and as a query comment elsewhere. Keys and values must match BigQuery's label rules ([a-z][a-z0-9_-]{0,62} / [a-z0-9_-]{0,63}). The dft_ prefix and the app key are reserved for the engine's own identity. |
3060
2977
  | `keyfile` | str | ✓ | Path to service account JSON key file. |
3061
2978
  | `keyfile_json` | dict[str, str \| int \| float \| bool] | ✓ | Inline service account JSON dict. |
@@ -3097,8 +3014,6 @@ Redshift source configuration.
3097
3014
  | `dbname` | str | | Redshift database name (dbt accepts database as an input alias). |
3098
3015
  | `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
3099
3016
  | `max_query_duration_seconds` | int | ✓ | Maximum execution time for one query in seconds. Overrides execution.max_query_duration_seconds for this source. |
3100
- | `lookml_path` | str | ✓ | Relative path to the directory of .lkml files backing this source's models. |
3101
- | `models` | dict[str, [LookMLModelConfig](#lookmlmodelconfig)] | ✓ | Named LookML model collections nested under this source. |
3102
3017
  | `attribution` | dict[str, str] | ✓ | Cost-attribution pairs sent with every query against this source, e.g. attribution: {team: analytics}. Emitted as BigQuery job labels and as a query comment elsewhere. Keys and values must match BigQuery's label rules ([a-z][a-z0-9_-]{0,62} / [a-z0-9_-]{0,63}). The dft_ prefix and the app key are reserved for the engine's own identity. |
3103
3018
  | `port` | int | ✓ | Redshift port number. |
3104
3019
  | `schema` | str | ✓ | Default schema for queries. |
@@ -3145,8 +3060,6 @@ MySQL source configuration.
3145
3060
  | `password` | str | | MySQL password. |
3146
3061
  | `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
3147
3062
  | `max_query_duration_seconds` | int | ✓ | Maximum execution time for one query in seconds. Overrides execution.max_query_duration_seconds for this source. |
3148
- | `lookml_path` | str | ✓ | Relative path to the directory of .lkml files backing this source's models. |
3149
- | `models` | dict[str, [LookMLModelConfig](#lookmlmodelconfig)] | ✓ | Named LookML model collections nested under this source. |
3150
3063
  | `attribution` | dict[str, str] | ✓ | Cost-attribution pairs sent with every query against this source, e.g. attribution: {team: analytics}. Emitted as BigQuery job labels and as a query comment elsewhere. Keys and values must match BigQuery's label rules ([a-z][a-z0-9_-]{0,62} / [a-z0-9_-]{0,63}). The dft_ prefix and the app key are reserved for the engine's own identity. |
3151
3064
  | `port` | int | ✓ | MySQL port number. |
3152
3065
  | `schema` | str | ✓ | Default schema for queries. |
@@ -3160,8 +3073,6 @@ DuckDB source configuration.
3160
3073
  | `type` | enum: "duckdb" | | Source type identifier. |
3161
3074
  | `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
3162
3075
  | `max_query_duration_seconds` | int | ✓ | Maximum execution time for one query in seconds. Overrides execution.max_query_duration_seconds for this source. |
3163
- | `lookml_path` | str | ✓ | Relative path to the directory of .lkml files backing this source's models. |
3164
- | `models` | dict[str, [LookMLModelConfig](#lookmlmodelconfig)] | ✓ | Named LookML model collections nested under this source. |
3165
3076
  | `path` | str | ✓ | DuckDB file path or ':memory:' for an in-memory database. |
3166
3077
  | `schema` | str | ✓ | Default schema for unqualified table names (sets search_path). |
3167
3078
  | `duckdb_config` | dict[str, str \| int \| float \| bool] | ✓ | DuckDB connection configuration values, such as enable_external_access. |
@@ -3188,8 +3099,6 @@ SQLite source configuration.
3188
3099
  |-------|------|:--------:|-------------|
3189
3100
  | `type` | enum: "sqlite" | | Source type identifier. |
3190
3101
  | `path` | str | | Path to the SQLite database file. |
3191
- | `lookml_path` | str | ✓ | Relative path to the directory of .lkml files backing this source's models. |
3192
- | `models` | dict[str, [LookMLModelConfig](#lookmlmodelconfig)] | ✓ | Named LookML model collections nested under this source. |
3193
3102
  | `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
3194
3103
 
3195
3104
  <a id="csvsourceconfig"></a>
@@ -3199,7 +3108,7 @@ CSV file source configuration.
3199
3108
  | Field | Type | Optional | Description |
3200
3109
  |-------|------|:--------:|-------------|
3201
3110
  | `type` | enum: "csv" | | Source type identifier. |
3202
- | `files` | dict[str, str] | | Mapping of table_name → file path. Each key is the SQL table name; the value is the path relative to the project root. Required and must not be empty. |
3111
+ | `files` | dict[str, str] | | Mapping of table_name → relative path or glob pattern. Each key is the SQL table name. The value is a path relative to the project root, or a glob pattern using ``*`` (matches within a directory) and ``?`` (matches one character). A glob must match at least one file; all matched files must share the same column schema and are concatenated into one table. The fan-out limit is ``execution.max_glob_file_count`` in ``dataface.yml`` (default 1000). Required and must not be empty. |
3203
3112
  | `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
3204
3113
  | `delimiter` | str | ✓ | Field delimiter character. |
3205
3114
  | `encoding` | str | ✓ | File encoding. |
@@ -3211,7 +3120,7 @@ Parquet file source configuration.
3211
3120
  | Field | Type | Optional | Description |
3212
3121
  |-------|------|:--------:|-------------|
3213
3122
  | `type` | enum: "parquet" | | Source type identifier. |
3214
- | `files` | dict[str, str] | | Mapping of table_name → file path. Each key is the SQL table name; the value is the path relative to the project root. Required and must not be empty. |
3123
+ | `files` | dict[str, str] | | Mapping of table_name → relative path or glob pattern. Each key is the SQL table name. The value is a path relative to the project root, or a glob pattern using ``*`` (matches within a directory) and ``?`` (matches one character). A glob must match at least one file; all matched files must share the same column schema and are concatenated into one table. The fan-out limit is ``execution.max_glob_file_count`` in ``dataface.yml`` (default 1000). Required and must not be empty. |
3215
3124
  | `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
3216
3125
 
3217
3126
  <a id="jsonsourceconfig"></a>
@@ -3221,8 +3130,9 @@ JSON file source configuration.
3221
3130
  | Field | Type | Optional | Description |
3222
3131
  |-------|------|:--------:|-------------|
3223
3132
  | `type` | enum: "json" | | Source type identifier. |
3224
- | `files` | dict[str, str] | | Mapping of table_name → file path. Each key is the SQL table name; the value is the path relative to the project root. Required and must not be empty. |
3133
+ | `files` | dict[str, str] | | Mapping of table_name → relative path or glob pattern. Each key is the SQL table name. The value is a path relative to the project root, or a glob pattern using ``*`` (matches within a directory) and ``?`` (matches one character). A glob must match at least one file and all matched files are concatenated into one table. The fan-out limit is ``execution.max_glob_file_count`` in ``dataface.yml`` (default 1000). Required and must not be empty. |
3225
3134
  | `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
3135
+ | `union_by_name` | bool | ✓ | When True, rows from different files in a glob set are unified by column name: columns absent in a particular file are filled with NULL. When False (default), all files in a glob set must share the same column schema — a mismatch raises an error. |
3226
3136
 
3227
3137
  <a id="httpsourceconfig"></a>
3228
3138
  ## HttpSourceConfig
@@ -3271,13 +3181,3 @@ Cross-file chart reference. Bare string is coerced automatically.
3271
3181
  | Field | Type | Description |
3272
3182
  |-------|------|-------------|
3273
3183
  | `ref` | str | Reference path: '&lt;file&gt;.charts.&lt;name&gt;'. May start with one or more '../' segments to reach a sibling directory. A bare string value is coerced automatically. |
3274
-
3275
- <a id="lookmlmodelconfig"></a>
3276
- ## LookMLModelConfig
3277
- One LookML model: a named collection of explores under a warehouse source.
3278
-
3279
- | Field | Type | Optional | Description |
3280
- |-------|------|:--------:|-------------|
3281
- | `lkml` | str | ✓ | Path to a specific .lkml model file, relative to the project root. |
3282
- | `group_label` | str | ✓ | LookML group_label selecting this model's explores. Not yet enforced at compile time. |
3283
- | `explores` | list[str] | ✓ | Explicit list of explore names in this model. |
@@ -43,7 +43,6 @@ def prepare_serve(
43
43
  max_workers: int | None,
44
44
  no_cache: bool,
45
45
  cache_path: Path | None,
46
- allow_external_access: bool,
47
46
  ) -> ServeSetup | Diagnostic:
48
47
  """Validate startup config, resolve port/dialect, and build the ASGI app.
49
48
 
@@ -97,7 +96,6 @@ def prepare_serve(
97
96
  max_workers=max_workers,
98
97
  no_cache=no_cache,
99
98
  cache_path=cache_path,
100
- allow_external_access_in_readonly=allow_external_access,
101
99
  )
102
100
 
103
101
  return ServeSetup(
@@ -227,6 +227,8 @@ def _validate_resolved(resolved: ProjectPath) -> ValidateResult:
227
227
  if resolved.is_meta:
228
228
  return _validate_meta_file(resolved)
229
229
 
230
+ from dataface.core.compile.errors import CompilationError
231
+
230
232
  try:
231
233
  result = compile_file(resolved.read_face())
232
234
  except OSError as exc:
@@ -239,6 +241,12 @@ def _validate_resolved(resolved: ProjectPath) -> ValidateResult:
239
241
  )
240
242
  ],
241
243
  )
244
+ except CompilationError as exc:
245
+ return ValidateResult(
246
+ success=False,
247
+ path=Path(resolved.relpath),
248
+ errors=[exc.to_diagnostic(file=resolved.relpath)],
249
+ )
242
250
 
243
251
  errors = list(result.errors)
244
252
  return ValidateResult(
@@ -172,6 +172,7 @@ def render_command(
172
172
  fail_on_chart_errors: bool = True,
173
173
  max_workers: int | None = None,
174
174
  print0: bool = False,
175
+ chart: str | None = None,
175
176
  *,
176
177
  project: FilesystemProject,
177
178
  ) -> str | None:
@@ -237,6 +238,7 @@ def render_command(
237
238
  raise RenderFailed([resolved])
238
239
  result = project_session.render_dashboard(
239
240
  face=resolved,
241
+ chart=chart,
240
242
  format=format,
241
243
  variables=variables,
242
244
  use_cache=use_cache,
@@ -273,6 +275,7 @@ def render_command_from_yaml(
273
275
  fail_on_chart_errors: bool = True,
274
276
  max_workers: int | None = None,
275
277
  print0: bool = False,
278
+ chart: str | None = None,
276
279
  *,
277
280
  project: FilesystemProject,
278
281
  ) -> str | None:
@@ -329,6 +332,7 @@ def render_command_from_yaml(
329
332
  face = InMemoryFace(yaml_content, path=None)
330
333
  result = project_session.render_dashboard(
331
334
  face=face,
335
+ chart=chart,
332
336
  format=format,
333
337
  variables=variables,
334
338
  use_cache=use_cache,
@@ -439,6 +443,7 @@ def render_commands(
439
443
  max_workers: int | None = None,
440
444
  print0: bool = False,
441
445
  fail_fast: bool = False,
446
+ chart: str | None = None,
442
447
  ) -> None:
443
448
  """Render one or more dashboards, printing output paths to stdout.
444
449
 
@@ -485,6 +490,7 @@ def render_commands(
485
490
  fail_on_chart_errors=fail_on_chart_errors,
486
491
  max_workers=max_workers,
487
492
  print0=print0,
493
+ chart=chart,
488
494
  )
489
495
  except RenderFailed as exc:
490
496
  print_diagnostics(exc.errors, json_output=json_errors)
@@ -28,7 +28,6 @@ def serve_command(
28
28
  max_workers: int | None = None,
29
29
  no_cache: bool = False,
30
30
  cache_path: Path | None = None,
31
- allow_external_access: bool = False,
32
31
  ) -> None:
33
32
  """Start unified Dataface server.
34
33
 
@@ -49,10 +48,6 @@ def serve_command(
49
48
  project: The resolved Dataface project (injected by @with_project)
50
49
  dialect: SQL dialect (auto-detected from dbt profile, or duckdb)
51
50
  target: dbt target name (defaults to DBT_TARGET env var, then profile default)
52
- allow_external_access: Allow author SQL to reach the filesystem/network via
53
- DuckDB (read_csv, read_json_auto, httpfs). Off by default — serve is
54
- strict read-only. Opt in only for local dashboards that must read files
55
- directly in SQL (e.g. glob-based analytics that cannot be file sources).
56
51
  no_cache: Skip the query-result cache entirely.
57
52
  cache_path: Persist the query-result cache to this DuckDB file (created
58
53
  if absent). None (the default) opens an in-memory cache — ephemeral,
@@ -84,7 +79,6 @@ def serve_command(
84
79
  max_workers=max_workers,
85
80
  no_cache=no_cache,
86
81
  cache_path=cache_path,
87
- allow_external_access=allow_external_access,
88
82
  )
89
83
  except _PydanticError as e:
90
84
  typer.echo(f"dataface.yml validation error: {e}", err=True)