model2data-studio 0.1.0__tar.gz → 0.3.0__tar.gz
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.
- {model2data_studio-0.1.0 → model2data_studio-0.3.0}/PKG-INFO +137 -14
- {model2data_studio-0.1.0 → model2data_studio-0.3.0}/README.md +136 -13
- {model2data_studio-0.1.0 → model2data_studio-0.3.0}/model2data_studio/__init__.py +1 -1
- model2data_studio-0.3.0/model2data_studio/cli.py +1188 -0
- model2data_studio-0.3.0/model2data_studio/client.py +442 -0
- model2data_studio-0.3.0/model2data_studio/export.py +537 -0
- {model2data_studio-0.1.0 → model2data_studio-0.3.0}/model2data_studio/mcp_server.py +274 -17
- {model2data_studio-0.1.0 → model2data_studio-0.3.0}/pyproject.toml +1 -1
- {model2data_studio-0.1.0 → model2data_studio-0.3.0}/server.json +2 -2
- model2data_studio-0.3.0/tests/test_cli.py +2022 -0
- model2data_studio-0.3.0/tests/test_export.py +434 -0
- model2data_studio-0.3.0/tests/test_mcp_server.py +649 -0
- {model2data_studio-0.1.0 → model2data_studio-0.3.0}/uv.lock +1 -1
- model2data_studio-0.1.0/model2data_studio/cli.py +0 -452
- model2data_studio-0.1.0/model2data_studio/client.py +0 -197
- model2data_studio-0.1.0/model2data_studio/export.py +0 -191
- model2data_studio-0.1.0/tests/test_cli.py +0 -928
- model2data_studio-0.1.0/tests/test_export.py +0 -137
- model2data_studio-0.1.0/tests/test_mcp_server.py +0 -301
- {model2data_studio-0.1.0 → model2data_studio-0.3.0}/.gitignore +0 -0
- {model2data_studio-0.1.0 → model2data_studio-0.3.0}/LICENSE +0 -0
- {model2data_studio-0.1.0 → model2data_studio-0.3.0}/model2data_studio/archive.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: model2data-studio
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Generate a model2data studio project's data from the command line, so CI can rebuild fixtures instead of committing them.
|
|
5
5
|
Project-URL: Homepage, https://www.jbanalytica.com/model2data/
|
|
6
6
|
Project-URL: Studio, https://studio.jbanalytica.com
|
|
@@ -69,11 +69,11 @@ the account, so put it in your CI provider's secrets rather than in a file.
|
|
|
69
69
|
|
|
70
70
|
Leave the key's access on **Generate and export**, which is the default and
|
|
71
71
|
covers everything below: reading a project, generating, exporting. A key with
|
|
72
|
-
**Read only** access is refused by `generate` with a 403 saying so.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
**Read only** access is refused by `generate` with a 403 saying so. **Generate
|
|
73
|
+
and save** adds writing the project back, which `push` and `dashboard push` need — for a
|
|
74
|
+
pipeline that pushes a model up rather than pulling data down — and **Full access** adds
|
|
75
|
+
deleting a project and managing its share links, which the CLI never does. A
|
|
76
|
+
key that leaks out of a CI log can only do what it was given.
|
|
77
77
|
|
|
78
78
|
## Commands
|
|
79
79
|
|
|
@@ -83,6 +83,17 @@ model2data-studio whoami # the plan behind the key, and what it h
|
|
|
83
83
|
|
|
84
84
|
model2data-studio generate --project <id> --out seeds/
|
|
85
85
|
model2data-studio generate --project <id> --out . --format dbt --adapter duckdb
|
|
86
|
+
|
|
87
|
+
model2data-studio push --project <id> shop.model2data.yml # save a model as the project's
|
|
88
|
+
|
|
89
|
+
model2data-studio metrics list --project ID # what each metric computes
|
|
90
|
+
model2data-studio metrics check --project shop.metrics.yml # exits 1 on an error, for CI
|
|
91
|
+
model2data-studio metrics values --project ID --seed 42 --as-of 2026-10-01
|
|
92
|
+
model2data-studio metrics suggest --project shop.model2data.yml -o shop.metrics.yml
|
|
93
|
+
|
|
94
|
+
model2data-studio dashboard pull <id> --out dashboards/ # one <name>.dashboard.yml each
|
|
95
|
+
model2data-studio dashboard push <id> dashboards/*.dashboard.yml
|
|
96
|
+
model2data-studio dashboard check dashboards/*.dashboard.yml --project <id> # for CI
|
|
86
97
|
```
|
|
87
98
|
|
|
88
99
|
`generate` takes every setting from the saved project — row counts, per-table
|
|
@@ -102,6 +113,8 @@ overrides, seed, locale, name — and each flag overrides one of them:
|
|
|
102
113
|
| `--skew N` | how unevenly child rows spread over their parents, `0.0`-`1.0`. Pro. |
|
|
103
114
|
| `--name NAME` | the dbt project's name |
|
|
104
115
|
| `--adapter duckdb\|postgres` | the warehouse the dbt project targets |
|
|
116
|
+
| `--metrics FILE` / `--no-metrics` | the metrics file to send instead of the project's own, or none (the metrics are then the ones the model implies). A dbt export holds `<project>.metrics.yml`, `metric_values.json` and a test per metric under `data-tests/metrics/`. |
|
|
117
|
+
| `--defects PRESET` | break the data on purpose: `clean`, `messy`, `training` or `none`; the archive then holds `defects_report.json` (and, for dbt, `EXPECTED_FAILURES.md`), and the log lists the tests `dbt build` should fail. Defaults to the project's. Pro, bar `training` on a bundled example. |
|
|
105
118
|
| `--force` | replace files already in `--out` |
|
|
106
119
|
| `--check` | compare against `--out` instead of writing to it |
|
|
107
120
|
|
|
@@ -132,10 +145,34 @@ committed fixtures, or that needs a failing build to be reproducible on a
|
|
|
132
145
|
laptop next week, wants the day pinned one way or the other; with `--seed`, the
|
|
133
146
|
two together name one dataset for good.
|
|
134
147
|
|
|
135
|
-
**
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
148
|
+
**A project written as a model is generated from the model.** A project whose
|
|
149
|
+
text is a model2data model — a `.model2data.yml` document, spec 0.2.0, with a
|
|
150
|
+
top-level `model2data:` version key — is sent to the studio as that text, and
|
|
151
|
+
the studio reads it with the engine's own loader, exactly as `model2data --file`
|
|
152
|
+
would. A model the studio refuses fails the run with every issue at its path in
|
|
153
|
+
the document (`tables.orders.columns.status.generate.weights: ...`). The
|
|
154
|
+
project's settings, and every flag above, still win over the model's own `run:`
|
|
155
|
+
section.
|
|
156
|
+
|
|
157
|
+
**A DBML project must have been opened in the studio at least once** since the
|
|
158
|
+
studio started saving its parse. Nothing on the server reads DBML into what the
|
|
159
|
+
editor showed — the browser does, and saves the result beside the project — so
|
|
160
|
+
a DBML project with no stored parse has nothing to generate from, and the CLI
|
|
161
|
+
says so rather than failing later.
|
|
162
|
+
|
|
163
|
+
**`push` saves a model file as the project's text.** The studio checks the model
|
|
164
|
+
first and nothing is saved if it has an error (warnings are printed and do not
|
|
165
|
+
stop it). The project's name, settings and canvas positions are kept; the
|
|
166
|
+
browser's saved parse of the old text is cleared, since the model is read
|
|
167
|
+
as-is from then on. It needs a key with **Generate and save** access. It takes
|
|
168
|
+
a model, not DBML: convert a DBML file with the engine's
|
|
169
|
+
`model2data convert schema.dbml` first.
|
|
170
|
+
|
|
171
|
+
**`push` saves the metrics file beside the model too.** `shop.metrics.yml` next
|
|
172
|
+
to `shop.model2data.yml` is checked by the studio and saved as the project's
|
|
173
|
+
metrics file, or the file `--metrics` names. Without either — or with
|
|
174
|
+
`--no-metrics` — the project keeps the metrics file it already has. A metrics
|
|
175
|
+
file with an error saves nothing.
|
|
139
176
|
|
|
140
177
|
**`--check` never writes into `--out`.** It regenerates into a scratch
|
|
141
178
|
directory and diffs it against what is already there, printing what changed,
|
|
@@ -144,6 +181,79 @@ job can fail a build whose committed fixtures nobody regenerated after a schema
|
|
|
144
181
|
change, instead of shipping them stale. Exits 0 and prints `Up to date: N
|
|
145
182
|
files` when they match.
|
|
146
183
|
|
|
184
|
+
## Metrics
|
|
185
|
+
|
|
186
|
+
A project's metrics file — `<stem>.metrics.yml` beside `<stem>.model2data.yml`,
|
|
187
|
+
metrics spec 0.1.0 — says what its numbers mean: `revenue` is the sum of
|
|
188
|
+
`orders.total_amount` where the order was paid, shipped or delivered. The studio
|
|
189
|
+
saves one per project (the Metrics tab); in a repository it is the file next to
|
|
190
|
+
the model. Without one, the metrics are the ones the model implies: a sum per
|
|
191
|
+
`measure` column and a row count per fact.
|
|
192
|
+
|
|
193
|
+
Every `metrics` command takes `--project`: a saved project's id **or** a local file (the id also still works as a plain argument, as it did before 0.2.1): the
|
|
194
|
+
model (`shop.model2data.yml`, or `shop.dbml`), or its metrics file, in which case
|
|
195
|
+
the model beside it is used. A local model's metrics are the `shop.metrics.yml`
|
|
196
|
+
beside it, unless `--metrics FILE` or `--no-metrics` says otherwise. **A local
|
|
197
|
+
file needs no API key**: checking metrics is free, and without a key `values`
|
|
198
|
+
runs on the free plan.
|
|
199
|
+
|
|
200
|
+
| | |
|
|
201
|
+
| --- | --- |
|
|
202
|
+
| `metrics list --project TARGET` | each metric's name, label, kind, what it computes, its filter and its date column; a metric the model implies rather than the file writes is marked `*` |
|
|
203
|
+
| `metrics check --project TARGET` | every issue as `file:line: error: path: message`, the shape a CI log viewer links; exits 1 on an error, 0 on warnings alone |
|
|
204
|
+
| `metrics values --project TARGET` | generates the data (the same run `generate` makes with the same arguments) and prints each metric's known value. `--seed`, `--rows` and `--as-of` as for `generate`; `--by-month` adds each month; `--json` prints the values shaped like the export's `metric_values.json` (its `run` and `metrics`; the spec version and rounding note are the export's own) |
|
|
205
|
+
| `metrics suggest --project TARGET` | a metrics file of the metrics the model implies, to start one from: stdout, or `-o FILE` (`--force` to replace one) |
|
|
206
|
+
|
|
207
|
+
```console
|
|
208
|
+
$ model2data-studio metrics values examples/ecommerce.model2data.yml --seed 42 --as-of 2026-10-01
|
|
209
|
+
ecommerce: seed 42, dates anchored on 2026-10-01, 100 rows a table
|
|
210
|
+
metric label value
|
|
211
|
+
------------------- ------------------------ -----------------------
|
|
212
|
+
revenue Revenue 4,012.30
|
|
213
|
+
orders Orders 100
|
|
214
|
+
average_order_value Average order value 40.12 (exact 40.123)
|
|
215
|
+
cancelled_orders Cancelled orders 4
|
|
216
|
+
cancellation_rate Cancellation rate 4.00%
|
|
217
|
+
...
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
The values are **known answers**: what a correct query over the generated seeds
|
|
221
|
+
returns. A rounded value is followed by its exact one, since that is what the
|
|
222
|
+
query will return. Metric values are Pro, except on a bundled example; on a
|
|
223
|
+
plan without them `values` says so and exits 1.
|
|
224
|
+
|
|
225
|
+
## Dashboards
|
|
226
|
+
|
|
227
|
+
A project's dashboards are files, `<name>.dashboard.yml`: the file name is the
|
|
228
|
+
dashboard's name. They name the project's metrics and columns, never a value;
|
|
229
|
+
the studio draws them from the project's generated data. The format is
|
|
230
|
+
model2data's open [dashboard spec](https://github.com/JB-Analytica/model2data/blob/main/model2data/spec/dashboards/README.md) (0.1.0),
|
|
231
|
+
with a JSON Schema at
|
|
232
|
+
`https://www.jbanalytica.com/model2data/spec/dashboards/0.1.0/dashboard.schema.json`
|
|
233
|
+
for editor completion: a file starts with
|
|
234
|
+
|
|
235
|
+
```yaml
|
|
236
|
+
# yaml-language-server: $schema=https://www.jbanalytica.com/model2data/spec/dashboards/0.1.0/dashboard.schema.json
|
|
237
|
+
model2data-dashboard: 0.1.0
|
|
238
|
+
model: coffee_webshop
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
This client does not read the files: it moves them to and from the studio, which
|
|
242
|
+
checks them and says what is wrong, by line and column. `dashboard guide` and
|
|
243
|
+
`dashboard check` without `--project` need no key. Since 0.3.0.
|
|
244
|
+
|
|
245
|
+
| | |
|
|
246
|
+
| --- | --- |
|
|
247
|
+
| `dashboard list PROJECT_ID` | the project's dashboards |
|
|
248
|
+
| `dashboard pull PROJECT_ID` | writes each one into `--out DIR` (the current folder by default); `--name NAME` for just that one. A file there that differs from the studio's is left alone, and nothing is written, unless `--force` |
|
|
249
|
+
| `dashboard push PROJECT_ID FILE...` | creates or replaces each dashboard by file name. Every file is checked first and nothing is saved if one has an error. Needs a key with **Generate and save** access |
|
|
250
|
+
| `dashboard check FILE... [--project ID]` | every error and warning as `file:line:column: error: message`; exits 1 on an error, 0 on warnings alone. With `--project`, names the project lacks are warnings |
|
|
251
|
+
| `dashboard guide [--project ID]` | the guide to writing one, as markdown: the dashboard spec, then what the studio adds; with a project, it ends with the metrics and columns that project offers |
|
|
252
|
+
|
|
253
|
+
A dashboard file that names something the project does not have is still saved:
|
|
254
|
+
that is a warning, not an error, so a dashboard can be sketched before the
|
|
255
|
+
metric it needs exists.
|
|
256
|
+
|
|
147
257
|
## Regenerating dbt seeds in CI
|
|
148
258
|
|
|
149
259
|
```yaml
|
|
@@ -241,15 +351,22 @@ and for anything that reads a JSON config (Claude Desktop, Cursor, Zed):
|
|
|
241
351
|
|
|
242
352
|
`MODEL2DATA_STUDIO_URL` works here too, for a self-hosted studio.
|
|
243
353
|
|
|
244
|
-
|
|
354
|
+
Twelve tools:
|
|
245
355
|
|
|
246
356
|
| | |
|
|
247
357
|
| --- | --- |
|
|
248
358
|
| `account` | the plan and its caps, worth reading before asking for a lot of rows |
|
|
249
359
|
| `list_projects` | the ids to pass to everything else |
|
|
250
|
-
| `describe_project` | one project's tables, columns, refs and enums as text, generation hints included |
|
|
360
|
+
| `describe_project` | one project's tables, columns, refs and enums as text, generation hints included, and its metrics |
|
|
251
361
|
| `preview_data` | generate and return the rows themselves, capped at fifty a table |
|
|
252
362
|
| `write_data` | generate and write the files, as `generate --out` does |
|
|
363
|
+
| `list_metrics` | the project's metrics, a line each: what it computes, its filter, its date column |
|
|
364
|
+
| `metric_values` | each metric's known value over a generated run, overall and by month (`seed`, `rows`, `as_of` as for `preview_data`). Pro, bar a bundled example. |
|
|
365
|
+
| `list_dashboards` | the project's dashboards, by name |
|
|
366
|
+
| `get_dashboard` | one dashboard file's text, to edit and save back |
|
|
367
|
+
| `get_dashboard_guide` | how to write a dashboard file: the open dashboard spec, then what the studio adds (no key needed); with `project_id`, ending with that project's metrics and columns |
|
|
368
|
+
| `check_dashboard` | a dashboard file's errors and warnings, each with its line and column, without saving (no key needed without `project_id`) |
|
|
369
|
+
| `save_dashboard` | checks a dashboard file, then creates or replaces it by name; a file with errors is not saved and the errors come back. Answers with the link to the project |
|
|
253
370
|
|
|
254
371
|
`preview_data` is the one worth having. An agent that can *read* generated rows
|
|
255
372
|
can act on them — write an assertion against them, notice that `shipped_at`
|
|
@@ -257,7 +374,13 @@ precedes `ordered_at`, spot a column coming out as placeholder sentences. It
|
|
|
257
374
|
answers with the rows inline and says how many there really are; `write_data` is
|
|
258
375
|
for when it has decided and wants the fixtures on disk.
|
|
259
376
|
|
|
260
|
-
|
|
377
|
+
`metric_values` is its other half: the numbers a correct query over those rows
|
|
378
|
+
returns, one quotable line per metric —
|
|
379
|
+
`revenue (Revenue): 4,012.30 — sum of orders.total_amount where orders.status in
|
|
380
|
+
paid, shipped, delivered; by month (orders.order_date): 2025-10 472.39, …` — so an
|
|
381
|
+
agent writing SQL against the seeds can check its own answer.
|
|
382
|
+
|
|
383
|
+
All of them go through the same `export.resolve` the CLI's `generate` does, so an agent
|
|
261
384
|
and a pipeline asking for the same project with the same arguments get the same
|
|
262
385
|
rows — including the part where an unpinned project has a seed picked for it and
|
|
263
386
|
is told which one, so the answer can be reproduced afterwards.
|
|
@@ -288,7 +411,7 @@ workflow refuses a tag that disagrees with any of them), merge, then tag the
|
|
|
288
411
|
merge commit on `main` and push the tag:
|
|
289
412
|
|
|
290
413
|
```bash
|
|
291
|
-
git tag cli-v0.
|
|
414
|
+
git tag cli-v0.3.0 && git push origin cli-v0.3.0
|
|
292
415
|
```
|
|
293
416
|
|
|
294
417
|
`.github/workflows/release-cli.yml` runs the tests, builds, publishes to PyPI
|
|
@@ -40,11 +40,11 @@ the account, so put it in your CI provider's secrets rather than in a file.
|
|
|
40
40
|
|
|
41
41
|
Leave the key's access on **Generate and export**, which is the default and
|
|
42
42
|
covers everything below: reading a project, generating, exporting. A key with
|
|
43
|
-
**Read only** access is refused by `generate` with a 403 saying so.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
**Read only** access is refused by `generate` with a 403 saying so. **Generate
|
|
44
|
+
and save** adds writing the project back, which `push` and `dashboard push` need — for a
|
|
45
|
+
pipeline that pushes a model up rather than pulling data down — and **Full access** adds
|
|
46
|
+
deleting a project and managing its share links, which the CLI never does. A
|
|
47
|
+
key that leaks out of a CI log can only do what it was given.
|
|
48
48
|
|
|
49
49
|
## Commands
|
|
50
50
|
|
|
@@ -54,6 +54,17 @@ model2data-studio whoami # the plan behind the key, and what it h
|
|
|
54
54
|
|
|
55
55
|
model2data-studio generate --project <id> --out seeds/
|
|
56
56
|
model2data-studio generate --project <id> --out . --format dbt --adapter duckdb
|
|
57
|
+
|
|
58
|
+
model2data-studio push --project <id> shop.model2data.yml # save a model as the project's
|
|
59
|
+
|
|
60
|
+
model2data-studio metrics list --project ID # what each metric computes
|
|
61
|
+
model2data-studio metrics check --project shop.metrics.yml # exits 1 on an error, for CI
|
|
62
|
+
model2data-studio metrics values --project ID --seed 42 --as-of 2026-10-01
|
|
63
|
+
model2data-studio metrics suggest --project shop.model2data.yml -o shop.metrics.yml
|
|
64
|
+
|
|
65
|
+
model2data-studio dashboard pull <id> --out dashboards/ # one <name>.dashboard.yml each
|
|
66
|
+
model2data-studio dashboard push <id> dashboards/*.dashboard.yml
|
|
67
|
+
model2data-studio dashboard check dashboards/*.dashboard.yml --project <id> # for CI
|
|
57
68
|
```
|
|
58
69
|
|
|
59
70
|
`generate` takes every setting from the saved project — row counts, per-table
|
|
@@ -73,6 +84,8 @@ overrides, seed, locale, name — and each flag overrides one of them:
|
|
|
73
84
|
| `--skew N` | how unevenly child rows spread over their parents, `0.0`-`1.0`. Pro. |
|
|
74
85
|
| `--name NAME` | the dbt project's name |
|
|
75
86
|
| `--adapter duckdb\|postgres` | the warehouse the dbt project targets |
|
|
87
|
+
| `--metrics FILE` / `--no-metrics` | the metrics file to send instead of the project's own, or none (the metrics are then the ones the model implies). A dbt export holds `<project>.metrics.yml`, `metric_values.json` and a test per metric under `data-tests/metrics/`. |
|
|
88
|
+
| `--defects PRESET` | break the data on purpose: `clean`, `messy`, `training` or `none`; the archive then holds `defects_report.json` (and, for dbt, `EXPECTED_FAILURES.md`), and the log lists the tests `dbt build` should fail. Defaults to the project's. Pro, bar `training` on a bundled example. |
|
|
76
89
|
| `--force` | replace files already in `--out` |
|
|
77
90
|
| `--check` | compare against `--out` instead of writing to it |
|
|
78
91
|
|
|
@@ -103,10 +116,34 @@ committed fixtures, or that needs a failing build to be reproducible on a
|
|
|
103
116
|
laptop next week, wants the day pinned one way or the other; with `--seed`, the
|
|
104
117
|
two together name one dataset for good.
|
|
105
118
|
|
|
106
|
-
**
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
119
|
+
**A project written as a model is generated from the model.** A project whose
|
|
120
|
+
text is a model2data model — a `.model2data.yml` document, spec 0.2.0, with a
|
|
121
|
+
top-level `model2data:` version key — is sent to the studio as that text, and
|
|
122
|
+
the studio reads it with the engine's own loader, exactly as `model2data --file`
|
|
123
|
+
would. A model the studio refuses fails the run with every issue at its path in
|
|
124
|
+
the document (`tables.orders.columns.status.generate.weights: ...`). The
|
|
125
|
+
project's settings, and every flag above, still win over the model's own `run:`
|
|
126
|
+
section.
|
|
127
|
+
|
|
128
|
+
**A DBML project must have been opened in the studio at least once** since the
|
|
129
|
+
studio started saving its parse. Nothing on the server reads DBML into what the
|
|
130
|
+
editor showed — the browser does, and saves the result beside the project — so
|
|
131
|
+
a DBML project with no stored parse has nothing to generate from, and the CLI
|
|
132
|
+
says so rather than failing later.
|
|
133
|
+
|
|
134
|
+
**`push` saves a model file as the project's text.** The studio checks the model
|
|
135
|
+
first and nothing is saved if it has an error (warnings are printed and do not
|
|
136
|
+
stop it). The project's name, settings and canvas positions are kept; the
|
|
137
|
+
browser's saved parse of the old text is cleared, since the model is read
|
|
138
|
+
as-is from then on. It needs a key with **Generate and save** access. It takes
|
|
139
|
+
a model, not DBML: convert a DBML file with the engine's
|
|
140
|
+
`model2data convert schema.dbml` first.
|
|
141
|
+
|
|
142
|
+
**`push` saves the metrics file beside the model too.** `shop.metrics.yml` next
|
|
143
|
+
to `shop.model2data.yml` is checked by the studio and saved as the project's
|
|
144
|
+
metrics file, or the file `--metrics` names. Without either — or with
|
|
145
|
+
`--no-metrics` — the project keeps the metrics file it already has. A metrics
|
|
146
|
+
file with an error saves nothing.
|
|
110
147
|
|
|
111
148
|
**`--check` never writes into `--out`.** It regenerates into a scratch
|
|
112
149
|
directory and diffs it against what is already there, printing what changed,
|
|
@@ -115,6 +152,79 @@ job can fail a build whose committed fixtures nobody regenerated after a schema
|
|
|
115
152
|
change, instead of shipping them stale. Exits 0 and prints `Up to date: N
|
|
116
153
|
files` when they match.
|
|
117
154
|
|
|
155
|
+
## Metrics
|
|
156
|
+
|
|
157
|
+
A project's metrics file — `<stem>.metrics.yml` beside `<stem>.model2data.yml`,
|
|
158
|
+
metrics spec 0.1.0 — says what its numbers mean: `revenue` is the sum of
|
|
159
|
+
`orders.total_amount` where the order was paid, shipped or delivered. The studio
|
|
160
|
+
saves one per project (the Metrics tab); in a repository it is the file next to
|
|
161
|
+
the model. Without one, the metrics are the ones the model implies: a sum per
|
|
162
|
+
`measure` column and a row count per fact.
|
|
163
|
+
|
|
164
|
+
Every `metrics` command takes `--project`: a saved project's id **or** a local file (the id also still works as a plain argument, as it did before 0.2.1): the
|
|
165
|
+
model (`shop.model2data.yml`, or `shop.dbml`), or its metrics file, in which case
|
|
166
|
+
the model beside it is used. A local model's metrics are the `shop.metrics.yml`
|
|
167
|
+
beside it, unless `--metrics FILE` or `--no-metrics` says otherwise. **A local
|
|
168
|
+
file needs no API key**: checking metrics is free, and without a key `values`
|
|
169
|
+
runs on the free plan.
|
|
170
|
+
|
|
171
|
+
| | |
|
|
172
|
+
| --- | --- |
|
|
173
|
+
| `metrics list --project TARGET` | each metric's name, label, kind, what it computes, its filter and its date column; a metric the model implies rather than the file writes is marked `*` |
|
|
174
|
+
| `metrics check --project TARGET` | every issue as `file:line: error: path: message`, the shape a CI log viewer links; exits 1 on an error, 0 on warnings alone |
|
|
175
|
+
| `metrics values --project TARGET` | generates the data (the same run `generate` makes with the same arguments) and prints each metric's known value. `--seed`, `--rows` and `--as-of` as for `generate`; `--by-month` adds each month; `--json` prints the values shaped like the export's `metric_values.json` (its `run` and `metrics`; the spec version and rounding note are the export's own) |
|
|
176
|
+
| `metrics suggest --project TARGET` | a metrics file of the metrics the model implies, to start one from: stdout, or `-o FILE` (`--force` to replace one) |
|
|
177
|
+
|
|
178
|
+
```console
|
|
179
|
+
$ model2data-studio metrics values examples/ecommerce.model2data.yml --seed 42 --as-of 2026-10-01
|
|
180
|
+
ecommerce: seed 42, dates anchored on 2026-10-01, 100 rows a table
|
|
181
|
+
metric label value
|
|
182
|
+
------------------- ------------------------ -----------------------
|
|
183
|
+
revenue Revenue 4,012.30
|
|
184
|
+
orders Orders 100
|
|
185
|
+
average_order_value Average order value 40.12 (exact 40.123)
|
|
186
|
+
cancelled_orders Cancelled orders 4
|
|
187
|
+
cancellation_rate Cancellation rate 4.00%
|
|
188
|
+
...
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The values are **known answers**: what a correct query over the generated seeds
|
|
192
|
+
returns. A rounded value is followed by its exact one, since that is what the
|
|
193
|
+
query will return. Metric values are Pro, except on a bundled example; on a
|
|
194
|
+
plan without them `values` says so and exits 1.
|
|
195
|
+
|
|
196
|
+
## Dashboards
|
|
197
|
+
|
|
198
|
+
A project's dashboards are files, `<name>.dashboard.yml`: the file name is the
|
|
199
|
+
dashboard's name. They name the project's metrics and columns, never a value;
|
|
200
|
+
the studio draws them from the project's generated data. The format is
|
|
201
|
+
model2data's open [dashboard spec](https://github.com/JB-Analytica/model2data/blob/main/model2data/spec/dashboards/README.md) (0.1.0),
|
|
202
|
+
with a JSON Schema at
|
|
203
|
+
`https://www.jbanalytica.com/model2data/spec/dashboards/0.1.0/dashboard.schema.json`
|
|
204
|
+
for editor completion: a file starts with
|
|
205
|
+
|
|
206
|
+
```yaml
|
|
207
|
+
# yaml-language-server: $schema=https://www.jbanalytica.com/model2data/spec/dashboards/0.1.0/dashboard.schema.json
|
|
208
|
+
model2data-dashboard: 0.1.0
|
|
209
|
+
model: coffee_webshop
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
This client does not read the files: it moves them to and from the studio, which
|
|
213
|
+
checks them and says what is wrong, by line and column. `dashboard guide` and
|
|
214
|
+
`dashboard check` without `--project` need no key. Since 0.3.0.
|
|
215
|
+
|
|
216
|
+
| | |
|
|
217
|
+
| --- | --- |
|
|
218
|
+
| `dashboard list PROJECT_ID` | the project's dashboards |
|
|
219
|
+
| `dashboard pull PROJECT_ID` | writes each one into `--out DIR` (the current folder by default); `--name NAME` for just that one. A file there that differs from the studio's is left alone, and nothing is written, unless `--force` |
|
|
220
|
+
| `dashboard push PROJECT_ID FILE...` | creates or replaces each dashboard by file name. Every file is checked first and nothing is saved if one has an error. Needs a key with **Generate and save** access |
|
|
221
|
+
| `dashboard check FILE... [--project ID]` | every error and warning as `file:line:column: error: message`; exits 1 on an error, 0 on warnings alone. With `--project`, names the project lacks are warnings |
|
|
222
|
+
| `dashboard guide [--project ID]` | the guide to writing one, as markdown: the dashboard spec, then what the studio adds; with a project, it ends with the metrics and columns that project offers |
|
|
223
|
+
|
|
224
|
+
A dashboard file that names something the project does not have is still saved:
|
|
225
|
+
that is a warning, not an error, so a dashboard can be sketched before the
|
|
226
|
+
metric it needs exists.
|
|
227
|
+
|
|
118
228
|
## Regenerating dbt seeds in CI
|
|
119
229
|
|
|
120
230
|
```yaml
|
|
@@ -212,15 +322,22 @@ and for anything that reads a JSON config (Claude Desktop, Cursor, Zed):
|
|
|
212
322
|
|
|
213
323
|
`MODEL2DATA_STUDIO_URL` works here too, for a self-hosted studio.
|
|
214
324
|
|
|
215
|
-
|
|
325
|
+
Twelve tools:
|
|
216
326
|
|
|
217
327
|
| | |
|
|
218
328
|
| --- | --- |
|
|
219
329
|
| `account` | the plan and its caps, worth reading before asking for a lot of rows |
|
|
220
330
|
| `list_projects` | the ids to pass to everything else |
|
|
221
|
-
| `describe_project` | one project's tables, columns, refs and enums as text, generation hints included |
|
|
331
|
+
| `describe_project` | one project's tables, columns, refs and enums as text, generation hints included, and its metrics |
|
|
222
332
|
| `preview_data` | generate and return the rows themselves, capped at fifty a table |
|
|
223
333
|
| `write_data` | generate and write the files, as `generate --out` does |
|
|
334
|
+
| `list_metrics` | the project's metrics, a line each: what it computes, its filter, its date column |
|
|
335
|
+
| `metric_values` | each metric's known value over a generated run, overall and by month (`seed`, `rows`, `as_of` as for `preview_data`). Pro, bar a bundled example. |
|
|
336
|
+
| `list_dashboards` | the project's dashboards, by name |
|
|
337
|
+
| `get_dashboard` | one dashboard file's text, to edit and save back |
|
|
338
|
+
| `get_dashboard_guide` | how to write a dashboard file: the open dashboard spec, then what the studio adds (no key needed); with `project_id`, ending with that project's metrics and columns |
|
|
339
|
+
| `check_dashboard` | a dashboard file's errors and warnings, each with its line and column, without saving (no key needed without `project_id`) |
|
|
340
|
+
| `save_dashboard` | checks a dashboard file, then creates or replaces it by name; a file with errors is not saved and the errors come back. Answers with the link to the project |
|
|
224
341
|
|
|
225
342
|
`preview_data` is the one worth having. An agent that can *read* generated rows
|
|
226
343
|
can act on them — write an assertion against them, notice that `shipped_at`
|
|
@@ -228,7 +345,13 @@ precedes `ordered_at`, spot a column coming out as placeholder sentences. It
|
|
|
228
345
|
answers with the rows inline and says how many there really are; `write_data` is
|
|
229
346
|
for when it has decided and wants the fixtures on disk.
|
|
230
347
|
|
|
231
|
-
|
|
348
|
+
`metric_values` is its other half: the numbers a correct query over those rows
|
|
349
|
+
returns, one quotable line per metric —
|
|
350
|
+
`revenue (Revenue): 4,012.30 — sum of orders.total_amount where orders.status in
|
|
351
|
+
paid, shipped, delivered; by month (orders.order_date): 2025-10 472.39, …` — so an
|
|
352
|
+
agent writing SQL against the seeds can check its own answer.
|
|
353
|
+
|
|
354
|
+
All of them go through the same `export.resolve` the CLI's `generate` does, so an agent
|
|
232
355
|
and a pipeline asking for the same project with the same arguments get the same
|
|
233
356
|
rows — including the part where an unpinned project has a seed picked for it and
|
|
234
357
|
is told which one, so the answer can be reproduced afterwards.
|
|
@@ -259,7 +382,7 @@ workflow refuses a tag that disagrees with any of them), merge, then tag the
|
|
|
259
382
|
merge commit on `main` and push the tag:
|
|
260
383
|
|
|
261
384
|
```bash
|
|
262
|
-
git tag cli-v0.
|
|
385
|
+
git tag cli-v0.3.0 && git push origin cli-v0.3.0
|
|
263
386
|
```
|
|
264
387
|
|
|
265
388
|
`.github/workflows/release-cli.yml` runs the tests, builds, publishes to PyPI
|