@lightdash/cli 1.39.2 → 1.40.0

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.
@@ -56,7 +56,7 @@ The available data models are defined in dbt YAML files at **`/tmp/dbt-repo/mode
56
56
  Projects range from a handful of models to well over a thousand, so the directory is indexed rather than inlined:
57
57
 
58
58
  1. **Read `/tmp/dbt-repo/models/_index.md` first.** It lists every model, most-queried first, with its file name, dimension/metric counts, joined tables, and description.
59
- 2. **Read only the model files the app actually needs**, e.g. `Read /tmp/dbt-repo/models/orders.yml`. Each file holds that model's complete dimensions, metrics, joins, and parameters.
59
+ 2. **Read only the model files the app actually needs**, e.g. `Read /tmp/dbt-repo/models/orders.yml`. Each file holds that model's complete dimensions, metrics, joins, parameters, and model-level filters.
60
60
  3. **Grep when the index isn't enough.** If you know a field name but not its model, `Grep` the directory for it. A wide model may be split across `<name>.yml`, `<name>.part2.yml`, … — the last line of each part points at the next.
61
61
 
62
62
  **Never read every model file, and never page through a file with `offset`/`limit`** — pick the model from the index and read that one file whole.
@@ -141,6 +141,16 @@ query('orders')
141
141
 
142
142
  Each entry under `meta.joins` may carry a `relationship` (`one-to-many`, `many-to-one`, `one-to-one`, `many-to-many`) and a `sql_on` condition — either can be absent. When a `relationship` is present, use it to reason about grain and fan-out: joining a `one-to-many` table multiplies base rows, so aggregating a base metric across that join can double-count — prefer a metric defined on the "many" side, or aggregate before joining.
143
143
 
144
+ ### Model-level filters — check before querying
145
+
146
+ Some models declare filters in their `meta:` block (the index marks them with `filters=…`). They change what every query against that model returns, so account for them when writing queries:
147
+
148
+ - **`required_filters`** — the backend force-ANDs each of these onto every query against the model, **unless your query has its own filter on the same field** (another time interval of the same date field also counts: filtering `order_date_month` overrides a required filter on `order_date`). If the user asks for a range that conflicts with a required filter (e.g. "last 90 days" but the model requires the last 4 weeks), you MUST add your own filter on that field — without one, the backend's filter silently caps your results.
149
+ - **`default_filters`** — NOT enforced by the backend, but Lightdash's own Explore UI pre-applies them. Apply them in your queries by default so the app's numbers match what users see in Lightdash; drop or replace one only when the user's request conflicts with it.
150
+ - **`sql_filter`** — a raw SQL condition ANDed onto every query against the model. It cannot be overridden or removed. Factor it into naming and copy — a model filtered to `status = 'completed'` must not be labelled "all orders" — and consider it when results look narrower than expected.
151
+
152
+ Entries under `required_filters` / `default_filters` use the SDK `Filter` shape (`field`, `operator`, `value`, `unit`) — pass them to `.filters([...])` as-is.
153
+
144
154
  ### Understanding data grain
145
155
 
146
156
  When designing queries, consider the model's grain — what combination of dimensions produces one unique row. If the grain includes dimensions you aren't selecting, you may need filters to avoid duplicates. Estimate row counts from the grain to set appropriate `.limit()` values.
@@ -228,6 +238,8 @@ const bySegment = base.label('Revenue by Segment').dimensions(['customer_segment
228
238
  const byRegion = base.label('Revenue by Region').dimensions(['region']);
229
239
  ```
230
240
 
241
+ **Sharing the explore-name constant:** define it in the component that uses it, or in its own module (e.g. `src/lib/constants.js`). Never export it from a component file that imports its consumers — that circular import evaluates the consumer first, the constant is `undefined` when a module-scope `query(...)` runs, and the app crashes on load.
242
+
231
243
  KPI cards — metrics without dimensions gives a single aggregated row:
232
244
  ```ts
233
245
  query('orders').label('KPI Summary').metrics(['total_revenue', 'order_count']).limit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/cli",
3
- "version": "1.39.2",
3
+ "version": "1.40.0",
4
4
  "description": "Lightdash CLI tool",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -41,8 +41,8 @@
41
41
  "unique-names-generator": "4.7.1",
42
42
  "uuid": "11.1.1",
43
43
  "yaml": "2.8.3",
44
- "@lightdash/common": "1.39.2",
45
- "@lightdash/warehouses": "1.39.2"
44
+ "@lightdash/common": "1.40.0",
45
+ "@lightdash/warehouses": "1.40.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/inquirer": "8.2.4",