@bonnard/cli 0.2.14 → 0.2.15
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.
package/dist/bin/bon.mjs
CHANGED
|
@@ -1908,6 +1908,30 @@ async function annotateCommand(id, options = {}) {
|
|
|
1908
1908
|
}
|
|
1909
1909
|
}
|
|
1910
1910
|
|
|
1911
|
+
//#endregion
|
|
1912
|
+
//#region src/commands/pull.ts
|
|
1913
|
+
async function pullCommand() {
|
|
1914
|
+
const paths = getProjectPaths(process.cwd());
|
|
1915
|
+
console.log(pc.dim("Downloading deployed models..."));
|
|
1916
|
+
try {
|
|
1917
|
+
const files = (await get("/api/deploy/files")).files;
|
|
1918
|
+
const fileKeys = Object.keys(files);
|
|
1919
|
+
if (fileKeys.length === 0) {
|
|
1920
|
+
console.log(pc.yellow("No deployed files found. Have you run `bon deploy` yet?"));
|
|
1921
|
+
return;
|
|
1922
|
+
}
|
|
1923
|
+
for (const [relativePath, content] of Object.entries(files)) {
|
|
1924
|
+
const fullPath = path.join(paths.root, relativePath);
|
|
1925
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
1926
|
+
fs.writeFileSync(fullPath, content, "utf-8");
|
|
1927
|
+
}
|
|
1928
|
+
console.log(pc.green(`Pulled ${fileKeys.length} file(s) to bonnard/`));
|
|
1929
|
+
} catch (err) {
|
|
1930
|
+
console.log(pc.red(`Pull failed: ${err instanceof Error ? err.message : err}`));
|
|
1931
|
+
process.exit(1);
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1911
1935
|
//#endregion
|
|
1912
1936
|
//#region src/commands/diff.ts
|
|
1913
1937
|
async function diffCommand(id, options = {}) {
|
|
@@ -3860,6 +3884,7 @@ datasource.command("list").description("List data sources (shows both local and
|
|
|
3860
3884
|
datasource.command("remove").description("Remove a data source from .bon/datasources.yaml (local by default)").argument("<name>", "Data source name").option("--remote", "Remove from Bonnard server instead of local (requires login)").action(datasourceRemoveCommand);
|
|
3861
3885
|
program.command("validate").description("Validate YAML syntax in bonnard/cubes/ and bonnard/views/").action(validateCommand);
|
|
3862
3886
|
program.command("deploy").description("Deploy cubes and views to Bonnard. Requires login, validates, syncs datasources").option("--ci", "Non-interactive mode").requiredOption("-m, --message <text>", "Deploy message describing your changes").action(deployCommand);
|
|
3887
|
+
program.command("pull").description("Download deployed cubes and views from Bonnard").action(pullCommand);
|
|
3863
3888
|
program.command("deployments").description("List deployment history").option("--all", "Show all deployments (default: last 10)").option("--format <format>", "Output format: table or json", "table").action(deploymentsCommand);
|
|
3864
3889
|
program.command("diff").description("Show changes in a deployment").argument("<id>", "Deployment ID").option("--format <format>", "Output format: table or json", "table").option("--breaking", "Show only breaking changes").action(diffCommand);
|
|
3865
3890
|
program.command("annotate").description("Annotate deployment changes with reasoning").argument("<id>", "Deployment ID").option("--data <json>", "Annotations JSON").action(annotateCommand);
|
|
@@ -172,6 +172,25 @@ Wrap components in a `<Grid>` tag to arrange them in columns:
|
|
|
172
172
|
|------|------|---------|-------------|
|
|
173
173
|
| `cols` | string | `"2"` | Number of columns in the grid |
|
|
174
174
|
|
|
175
|
+
### Layout Best Practices
|
|
176
|
+
|
|
177
|
+
**Use `##` for sections, not `#`.** The `#` heading renders very large and wastes vertical space. Use `##` for section titles and `###` for subsections. Reserve `#` for the dashboard title only (which is set in frontmatter, not in the body).
|
|
178
|
+
|
|
179
|
+
**Group related charts side by side.** Wrap pairs of charts in `<Grid cols="2">` to avoid long vertical scrolling:
|
|
180
|
+
|
|
181
|
+
```markdown
|
|
182
|
+
<Grid cols="2">
|
|
183
|
+
<BarChart data={by_channel} x="orders.channel" y="orders.total_revenue" title="By Channel" />
|
|
184
|
+
<BarChart data={by_city} x="orders.city" y="orders.total_revenue" title="By City" horizontal />
|
|
185
|
+
</Grid>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Start each section with KPIs.** Place `<BigValue>` cards at the top of a section for at-a-glance metrics, then follow with charts for detail.
|
|
189
|
+
|
|
190
|
+
**Only Grid together components of similar height.** Don't mix a `<BigValue>` with a chart in the same `<Grid>` row — the grid stretches both cells to the tallest item, leaving the BigValue card with a large empty area. Instead, place KPIs in their own row (consecutive BigValues auto-group) and pair charts with other charts of similar size.
|
|
191
|
+
|
|
192
|
+
**Keep it compact.** A good dashboard fits key information in 2-3 screens of scrolling. Use Grids, concise titles, and avoid unnecessary headings between every chart.
|
|
193
|
+
|
|
175
194
|
## Formatting
|
|
176
195
|
|
|
177
196
|
Values are auto-formatted by default — numbers get locale grouping (1,234.56), dates display as "13 Jan 2025", and nulls show as "—". Override with named presets for common currencies and percentages, or use raw Excel format codes for full control.
|
|
@@ -252,16 +252,89 @@ limit: 10
|
|
|
252
252
|
|
|
253
253
|
The `<DateRange>` automatically applies to all queries with a `timeDimension` (here: `trend`). The `<Dropdown>` filters `trend` and `by_city` by channel. The `channels` query populates the dropdown and is never filtered by it.
|
|
254
254
|
|
|
255
|
+
## Compact Multi-Section Dashboard
|
|
256
|
+
|
|
257
|
+
A dashboard with multiple sections, side-by-side charts, and compact layout. Uses `##` headings (not `#`), `<Grid>` for horizontal grouping, and keeps all queries near the components that use them.
|
|
258
|
+
|
|
259
|
+
```markdown
|
|
260
|
+
---
|
|
261
|
+
title: Operations Overview
|
|
262
|
+
description: KPIs, trends, and breakdowns across channels and cities
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
<DateRange name="period" default="last-30-days" label="Period" />
|
|
266
|
+
|
|
267
|
+
` ``query channels
|
|
268
|
+
dimensions: [orders.channel]
|
|
269
|
+
` ``
|
|
270
|
+
|
|
271
|
+
<Dropdown name="channel" dimension="orders.channel" data={channels} queries="kpis,trend,by_city" label="Channel" />
|
|
272
|
+
|
|
273
|
+
## Key Metrics
|
|
274
|
+
|
|
275
|
+
` ``query kpis
|
|
276
|
+
measures: [orders.total_revenue, orders.count, orders.avg_order_value]
|
|
277
|
+
` ``
|
|
278
|
+
|
|
279
|
+
<BigValue data={kpis} value="orders.total_revenue" title="Revenue" fmt="eur" />
|
|
280
|
+
<BigValue data={kpis} value="orders.count" title="Orders" fmt="num0" />
|
|
281
|
+
<BigValue data={kpis} value="orders.avg_order_value" title="Avg Order" fmt="eur2" />
|
|
282
|
+
|
|
283
|
+
## Trends & Breakdown
|
|
284
|
+
|
|
285
|
+
` ``query trend
|
|
286
|
+
measures: [orders.total_revenue]
|
|
287
|
+
timeDimension:
|
|
288
|
+
dimension: orders.created_at
|
|
289
|
+
granularity: week
|
|
290
|
+
` ``
|
|
291
|
+
|
|
292
|
+
` ``query by_channel
|
|
293
|
+
measures: [orders.total_revenue]
|
|
294
|
+
dimensions: [orders.channel]
|
|
295
|
+
orderBy:
|
|
296
|
+
orders.total_revenue: desc
|
|
297
|
+
` ``
|
|
298
|
+
|
|
299
|
+
<Grid cols="2">
|
|
300
|
+
<LineChart data={trend} x="orders.created_at" y="orders.total_revenue" title="Weekly Revenue" yFmt="eur" />
|
|
301
|
+
<BarChart data={by_channel} x="orders.channel" y="orders.total_revenue" title="By Channel" yFmt="eur" />
|
|
302
|
+
</Grid>
|
|
303
|
+
|
|
304
|
+
## Top Cities
|
|
305
|
+
|
|
306
|
+
` ``query by_city
|
|
307
|
+
measures: [orders.total_revenue, orders.count]
|
|
308
|
+
dimensions: [orders.city]
|
|
309
|
+
orderBy:
|
|
310
|
+
orders.total_revenue: desc
|
|
311
|
+
limit: 10
|
|
312
|
+
` ``
|
|
313
|
+
|
|
314
|
+
<Grid cols="2">
|
|
315
|
+
<BarChart data={by_city} x="orders.city" y="orders.total_revenue" title="Revenue by City" horizontal yFmt="eur" />
|
|
316
|
+
<DataTable data={by_city} fmt="orders.total_revenue:eur,orders.count:num0" />
|
|
317
|
+
</Grid>
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Key patterns:
|
|
321
|
+
- **`##` headings** for sections — compact, no oversized H1s
|
|
322
|
+
- **Consecutive `<BigValue>`** auto-groups into a row (no Grid needed)
|
|
323
|
+
- **`<Grid cols="2">`** pairs a chart with a table or two charts side by side
|
|
324
|
+
- **Queries defined before their Grid** — keeps the layout clean and components grouped
|
|
325
|
+
|
|
255
326
|
## Tips
|
|
256
327
|
|
|
257
|
-
- **Start with KPIs**: Use `BigValue`
|
|
328
|
+
- **Start with KPIs**: Use `BigValue` at the top for key metrics — consecutive BigValues auto-group into a row
|
|
258
329
|
- **One query per chart**: Each component gets its own query — keep them focused
|
|
330
|
+
- **Use `##` headings**: Reserve `#` for the dashboard title (in frontmatter). Use `##` for sections
|
|
259
331
|
- **Use views**: Prefer view names over cube names when available
|
|
260
332
|
- **Name queries descriptively**: `monthly_revenue` is better than `q1`
|
|
261
333
|
- **Limit large datasets**: Add `limit` to dimension queries to avoid oversized charts
|
|
262
334
|
- **Time series**: Always use `timeDimension` with `granularity` for time-based charts
|
|
263
335
|
- **Multi-series**: Use `series="cube.column"` to split data by a dimension. For bars, default is stacked; use `type="grouped"` for side-by-side
|
|
264
336
|
- **Multiple y columns**: Use comma-separated values like `y="orders.revenue,orders.cases"` to show multiple measures on one chart
|
|
337
|
+
- **Side-by-side charts**: Wrap pairs in `<Grid cols="2">` to reduce vertical scrolling
|
|
265
338
|
|
|
266
339
|
## See Also
|
|
267
340
|
|