@bonnard/cli 0.1.7 → 0.1.8
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 +29 -29
- package/dist/bin/{models-CzOWi3fU.mjs → cubes-De1_2_YJ.mjs} +7 -7
- package/dist/bin/{validate-BUHevw7F.mjs → validate-DiN3DaTl.mjs} +2 -2
- package/dist/docs/_index.md +3 -3
- package/dist/docs/topics/cubes.dimensions.primary-key.md +1 -1
- package/dist/docs/topics/cubes.dimensions.sub-query.md +1 -1
- package/dist/docs/topics/cubes.joins.md +1 -1
- package/dist/docs/topics/cubes.md +3 -3
- package/dist/docs/topics/cubes.measures.types.md +1 -1
- package/dist/docs/topics/cubes.refresh-key.md +1 -1
- package/dist/docs/topics/syntax.md +2 -2
- package/dist/docs/topics/syntax.references.md +1 -1
- package/dist/docs/topics/views.folders.md +1 -1
- package/dist/docs/topics/workflow.deploy.md +16 -17
- package/dist/docs/topics/workflow.mcp.md +98 -25
- package/dist/docs/topics/workflow.md +13 -13
- package/dist/docs/topics/workflow.query.md +20 -20
- package/dist/docs/topics/workflow.validate.md +7 -7
- package/dist/templates/claude/skills/bonnard-cli/SKILL.md +6 -6
- package/dist/templates/claude/skills/bonnard-queries/SKILL.md +3 -3
- package/dist/templates/cursor/rules/bonnard-cli.mdc +6 -6
- package/dist/templates/cursor/rules/bonnard-queries.mdc +3 -3
- package/dist/templates/shared/bonnard.md +8 -8
- package/package.json +1 -1
package/dist/bin/bon.mjs
CHANGED
|
@@ -33,20 +33,20 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
33
33
|
//#endregion
|
|
34
34
|
//#region src/lib/project.ts
|
|
35
35
|
/**
|
|
36
|
-
* The subdirectory name used for Bonnard
|
|
36
|
+
* The subdirectory name used for Bonnard cube/view files.
|
|
37
37
|
* Keeps Bonnard files namespaced to avoid conflicts with existing
|
|
38
38
|
* project directories (e.g. dbt's models/).
|
|
39
39
|
*/
|
|
40
40
|
const BONNARD_DIR = "bonnard";
|
|
41
41
|
/**
|
|
42
42
|
* Resolve Bonnard project paths relative to the working directory.
|
|
43
|
-
* All
|
|
43
|
+
* All cube/view operations should use these paths.
|
|
44
44
|
*/
|
|
45
45
|
function getProjectPaths(cwd) {
|
|
46
46
|
const bonnardRoot = path.join(cwd, BONNARD_DIR);
|
|
47
47
|
return {
|
|
48
48
|
root: bonnardRoot,
|
|
49
|
-
|
|
49
|
+
cubes: path.join(bonnardRoot, "cubes"),
|
|
50
50
|
views: path.join(bonnardRoot, "views"),
|
|
51
51
|
config: path.join(cwd, "bon.yaml"),
|
|
52
52
|
localState: path.join(cwd, ".bon")
|
|
@@ -475,8 +475,8 @@ function generateProjectContext(env) {
|
|
|
475
475
|
else roleLines.push("New project — no existing data tools detected. Help them connect a warehouse (`bon datasource add`), then create their first cube.");
|
|
476
476
|
roleLines.push("");
|
|
477
477
|
roleLines.push("**Important:**");
|
|
478
|
-
roleLines.push("- Bonnard
|
|
479
|
-
roleLines.push("- Use `bon docs` to look up
|
|
478
|
+
roleLines.push("- Bonnard cubes go in `bonnard/cubes/` and views in `bonnard/views/` — do NOT modify files outside these directories");
|
|
479
|
+
roleLines.push("- Use `bon docs` to look up YAML syntax before writing cube/view definitions");
|
|
480
480
|
if (hasDbt && dbtTool) {
|
|
481
481
|
const dbtDir = dbtTool.configPath.includes("/") ? dbtTool.configPath.split("/").slice(0, -1).join("/") + "/" : "";
|
|
482
482
|
const modelsPath = dbtDir ? `${dbtDir}models/` : "models/";
|
|
@@ -591,7 +591,7 @@ async function initCommand() {
|
|
|
591
591
|
console.log(pc.red("A bon.yaml already exists in this directory."));
|
|
592
592
|
process.exit(1);
|
|
593
593
|
}
|
|
594
|
-
fs.mkdirSync(paths.
|
|
594
|
+
fs.mkdirSync(paths.cubes, { recursive: true });
|
|
595
595
|
fs.mkdirSync(paths.views, { recursive: true });
|
|
596
596
|
fs.mkdirSync(paths.localState, { recursive: true });
|
|
597
597
|
fs.writeFileSync(paths.config, BON_YAML_TEMPLATE(projectName));
|
|
@@ -602,7 +602,7 @@ async function initCommand() {
|
|
|
602
602
|
console.log();
|
|
603
603
|
console.log(pc.bold("Core files:"));
|
|
604
604
|
console.log(` ${pc.dim("bon.yaml")} project config`);
|
|
605
|
-
console.log(` ${pc.dim(`${BONNARD_DIR}/
|
|
605
|
+
console.log(` ${pc.dim(`${BONNARD_DIR}/cubes/`)} cube definitions`);
|
|
606
606
|
console.log(` ${pc.dim(`${BONNARD_DIR}/views/`)} view definitions`);
|
|
607
607
|
console.log(` ${pc.dim(".bon/")} local state (gitignored)`);
|
|
608
608
|
console.log(` ${pc.dim(".gitignore")} git ignore rules`);
|
|
@@ -2246,10 +2246,10 @@ async function validateCommand(options = {}) {
|
|
|
2246
2246
|
console.log(pc.red("No bon.yaml found. Are you in a Bonnard project?"));
|
|
2247
2247
|
process.exit(1);
|
|
2248
2248
|
}
|
|
2249
|
-
const { validate } = await import("./validate-
|
|
2249
|
+
const { validate } = await import("./validate-DiN3DaTl.mjs");
|
|
2250
2250
|
const result = await validate(cwd);
|
|
2251
2251
|
if (result.cubes.length === 0 && result.views.length === 0 && result.valid) {
|
|
2252
|
-
console.log(pc.yellow(`No
|
|
2252
|
+
console.log(pc.yellow(`No cube or view files found in ${BONNARD_DIR}/cubes/ or ${BONNARD_DIR}/views/.`));
|
|
2253
2253
|
return;
|
|
2254
2254
|
}
|
|
2255
2255
|
if (!result.valid) {
|
|
@@ -2280,16 +2280,16 @@ async function validateCommand(options = {}) {
|
|
|
2280
2280
|
}
|
|
2281
2281
|
}
|
|
2282
2282
|
/**
|
|
2283
|
-
* Test connections for datasources referenced by
|
|
2283
|
+
* Test connections for datasources referenced by cubes and views
|
|
2284
2284
|
* Lenient: warns but doesn't fail validation
|
|
2285
2285
|
*/
|
|
2286
2286
|
async function testReferencedConnections(cwd) {
|
|
2287
|
-
const {
|
|
2287
|
+
const { extractDatasourcesFromCubes } = await import("./cubes-De1_2_YJ.mjs");
|
|
2288
2288
|
const { loadLocalDatasources, resolveEnvVarsInCredentials } = await Promise.resolve().then(() => local_exports);
|
|
2289
2289
|
const { testConnection } = await Promise.resolve().then(() => connection_exports);
|
|
2290
|
-
const references =
|
|
2290
|
+
const references = extractDatasourcesFromCubes(cwd);
|
|
2291
2291
|
if (references.length === 0) {
|
|
2292
|
-
console.log(pc.dim("No datasource references found in
|
|
2292
|
+
console.log(pc.dim("No datasource references found in cubes."));
|
|
2293
2293
|
return;
|
|
2294
2294
|
}
|
|
2295
2295
|
console.log(pc.bold("Testing connections..."));
|
|
@@ -2357,8 +2357,8 @@ async function deployCommand(options = {}) {
|
|
|
2357
2357
|
console.log(pc.red("No bon.yaml found. Are you in a Bonnard project?"));
|
|
2358
2358
|
process.exit(1);
|
|
2359
2359
|
}
|
|
2360
|
-
console.log(pc.dim("Validating
|
|
2361
|
-
const { validate } = await import("./validate-
|
|
2360
|
+
console.log(pc.dim("Validating cubes and views..."));
|
|
2361
|
+
const { validate } = await import("./validate-DiN3DaTl.mjs");
|
|
2362
2362
|
const result = await validate(cwd);
|
|
2363
2363
|
if (!result.valid) {
|
|
2364
2364
|
console.log(pc.red("Validation failed:\n"));
|
|
@@ -2366,13 +2366,13 @@ async function deployCommand(options = {}) {
|
|
|
2366
2366
|
process.exit(1);
|
|
2367
2367
|
}
|
|
2368
2368
|
if (result.cubes.length === 0 && result.views.length === 0) {
|
|
2369
|
-
console.log(pc.yellow(`No
|
|
2369
|
+
console.log(pc.yellow(`No cube or view files found in ${BONNARD_DIR}/cubes/ or ${BONNARD_DIR}/views/. Nothing to deploy.`));
|
|
2370
2370
|
process.exit(1);
|
|
2371
2371
|
}
|
|
2372
2372
|
console.log(pc.dim(` Found ${result.cubes.length} cube(s) and ${result.views.length} view(s)`));
|
|
2373
2373
|
if (await testAndSyncDatasources(cwd, options)) process.exit(1);
|
|
2374
2374
|
const files = {
|
|
2375
|
-
...collectFiles(paths.
|
|
2375
|
+
...collectFiles(paths.cubes, cwd),
|
|
2376
2376
|
...collectFiles(paths.views, cwd)
|
|
2377
2377
|
};
|
|
2378
2378
|
const fileCount = Object.keys(files).length;
|
|
@@ -2382,7 +2382,7 @@ async function deployCommand(options = {}) {
|
|
|
2382
2382
|
const response = await post("/api/deploy", { files });
|
|
2383
2383
|
console.log(pc.green("Deploy successful!"));
|
|
2384
2384
|
console.log(`Deployment ID: ${pc.cyan(response.deployment.id)}`);
|
|
2385
|
-
console.log(`
|
|
2385
|
+
console.log(`API: ${pc.cyan(response.deployment.cubeApiUrl)}`);
|
|
2386
2386
|
console.log();
|
|
2387
2387
|
console.log(pc.bold("Connect AI agents via MCP:"));
|
|
2388
2388
|
console.log(` MCP URL: ${pc.cyan("https://mcp.bonnard.dev/mcp")}`);
|
|
@@ -2397,11 +2397,11 @@ async function deployCommand(options = {}) {
|
|
|
2397
2397
|
* Returns true if any connection failed (strict mode)
|
|
2398
2398
|
*/
|
|
2399
2399
|
async function testAndSyncDatasources(cwd, options = {}) {
|
|
2400
|
-
const {
|
|
2400
|
+
const { extractDatasourcesFromCubes } = await import("./cubes-De1_2_YJ.mjs");
|
|
2401
2401
|
const { loadLocalDatasources, resolveEnvVarsInCredentials } = await Promise.resolve().then(() => local_exports);
|
|
2402
2402
|
const { testConnection } = await Promise.resolve().then(() => connection_exports);
|
|
2403
2403
|
const { pushDatasource } = await Promise.resolve().then(() => push_exports);
|
|
2404
|
-
const references =
|
|
2404
|
+
const references = extractDatasourcesFromCubes(cwd);
|
|
2405
2405
|
if (references.length === 0) return false;
|
|
2406
2406
|
console.log();
|
|
2407
2407
|
console.log(pc.dim("Testing datasource connections..."));
|
|
@@ -2744,11 +2744,11 @@ async function docsSchemaCommand(schemaName) {
|
|
|
2744
2744
|
//#endregion
|
|
2745
2745
|
//#region src/commands/cube/query.ts
|
|
2746
2746
|
/**
|
|
2747
|
-
* Query the deployed
|
|
2747
|
+
* Query the deployed semantic layer
|
|
2748
2748
|
*
|
|
2749
2749
|
* Supports two formats:
|
|
2750
|
-
* - JSON (default): bon
|
|
2751
|
-
* - SQL: bon
|
|
2750
|
+
* - JSON (default): bon query '{"measures": ["orders.count"]}'
|
|
2751
|
+
* - SQL: bon query --sql "SELECT MEASURE(count) FROM orders"
|
|
2752
2752
|
*/
|
|
2753
2753
|
async function cubeQueryCommand(queryInput, options = {}) {
|
|
2754
2754
|
if (!loadCredentials()) {
|
|
@@ -2766,7 +2766,7 @@ async function cubeQueryCommand(queryInput, options = {}) {
|
|
|
2766
2766
|
query = JSON.parse(queryInput);
|
|
2767
2767
|
} catch {
|
|
2768
2768
|
console.error(pc.red("Invalid JSON query. Use --sql for SQL queries."));
|
|
2769
|
-
console.log(pc.dim("Example: bon
|
|
2769
|
+
console.log(pc.dim("Example: bon query '{\"measures\": [\"orders.count\"]}'"));
|
|
2770
2770
|
process.exit(1);
|
|
2771
2771
|
}
|
|
2772
2772
|
if (limit && !query.limit) query.limit = limit;
|
|
@@ -2803,7 +2803,7 @@ async function cubeQueryCommand(queryInput, options = {}) {
|
|
|
2803
2803
|
//#region src/bin/bon.ts
|
|
2804
2804
|
const { version } = createRequire(import.meta.url)("../../package.json");
|
|
2805
2805
|
program.name("bon").description("Bonnard semantic layer CLI").version(version);
|
|
2806
|
-
program.command("init").description("Create bon.yaml, bonnard/
|
|
2806
|
+
program.command("init").description("Create bon.yaml, bonnard/cubes/, bonnard/views/, .bon/, and agent templates (.claude/, .cursor/)").action(initCommand);
|
|
2807
2807
|
program.command("login").description("Authenticate with Bonnard via your browser").action(loginCommand);
|
|
2808
2808
|
program.command("logout").description("Remove stored credentials").action(logoutCommand);
|
|
2809
2809
|
program.command("whoami").description("Show current login status").option("--verify", "Verify session is still valid with the server").action(whoamiCommand);
|
|
@@ -2814,11 +2814,11 @@ datasource.command("test").description("Test data source connectivity by connect
|
|
|
2814
2814
|
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);
|
|
2815
2815
|
datasource.command("push").description("Push a local data source to Bonnard server (requires login)").argument("<name>", "Data source name from .bon/datasources.yaml").option("--force", "Overwrite if already exists on remote").action(datasourcePushCommand);
|
|
2816
2816
|
program.command("preview").description("Preview data from a local warehouse using raw SQL (for development/exploration)").argument("<datasource>", "Data source name from .bon/datasources.yaml").argument("<sql>", "SQL query to execute").option("--schema <schema>", "Override schema").option("--database <database>", "Override database").option("--limit <limit>", "Max rows to return", "1000").option("--format <format>", "Output format: toon or json", "toon").action(previewCommand);
|
|
2817
|
-
program.command("validate").description("Validate YAML syntax in bonnard/
|
|
2818
|
-
program.command("deploy").description("Deploy
|
|
2817
|
+
program.command("validate").description("Validate YAML syntax in bonnard/cubes/ and bonnard/views/").option("--test-connection", "Also test datasource connections (warns on failure, doesn't block)").action(validateCommand);
|
|
2818
|
+
program.command("deploy").description("Deploy cubes and views to Bonnard. Requires login, validates, tests connections (fails on error)").option("--ci", "Non-interactive mode (fail if missing datasources)").option("--push-datasources", "Auto-push missing datasources without prompting").action(deployCommand);
|
|
2819
2819
|
program.command("mcp").description("MCP connection info and setup instructions").action(mcpCommand).command("test").description("Test MCP server connectivity").action(mcpTestCommand);
|
|
2820
|
-
program.command("
|
|
2821
|
-
program.command("docs").description("Browse
|
|
2820
|
+
program.command("query").description("Execute a query against the deployed semantic layer").argument("<query>", "JSON query or SQL (with --sql flag)").option("--sql", "Use SQL API instead of JSON format").option("--limit <limit>", "Max rows to return").option("--format <format>", "Output format: toon or json", "toon").action(cubeQueryCommand);
|
|
2821
|
+
program.command("docs").description("Browse documentation for building cubes and views").argument("[topic]", "Topic to display (e.g., cubes, cubes.measures)").option("-r, --recursive", "Show topic and all child topics").option("-s, --search <query>", "Search topics for a keyword").option("-f, --format <format>", "Output format: markdown or json", "markdown").action(docsCommand).command("schema").description("Show JSON schema for a type (cube, view, measure, etc.)").argument("<type>", "Schema type to display").action(docsSchemaCommand);
|
|
2822
2822
|
program.parse();
|
|
2823
2823
|
|
|
2824
2824
|
//#endregion
|
|
@@ -3,9 +3,9 @@ import fs from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import YAML from "yaml";
|
|
5
5
|
|
|
6
|
-
//#region src/lib/
|
|
6
|
+
//#region src/lib/cubes/datasources.ts
|
|
7
7
|
/**
|
|
8
|
-
* Extract datasource references from
|
|
8
|
+
* Extract datasource references from cube and view files
|
|
9
9
|
*/
|
|
10
10
|
/**
|
|
11
11
|
* Collect all YAML files from a directory recursively
|
|
@@ -49,14 +49,14 @@ function extractFromFile(filePath) {
|
|
|
49
49
|
return datasourceToCubes;
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
|
-
* Extract all unique datasource references from bonnard/
|
|
52
|
+
* Extract all unique datasource references from bonnard/cubes/ and bonnard/views/ directories
|
|
53
53
|
* Returns datasource names mapped to the cubes that use them
|
|
54
54
|
*/
|
|
55
|
-
function
|
|
55
|
+
function extractDatasourcesFromCubes(projectPath) {
|
|
56
56
|
const paths = getProjectPaths(projectPath);
|
|
57
|
-
const
|
|
57
|
+
const cubesDir = paths.cubes;
|
|
58
58
|
const viewsDir = paths.views;
|
|
59
|
-
const allFiles = [...collectYamlFiles(
|
|
59
|
+
const allFiles = [...collectYamlFiles(cubesDir), ...collectYamlFiles(viewsDir)];
|
|
60
60
|
const aggregated = /* @__PURE__ */ new Map();
|
|
61
61
|
for (const file of allFiles) {
|
|
62
62
|
const fileRefs = extractFromFile(file);
|
|
@@ -75,4 +75,4 @@ function extractDatasourcesFromModels(projectPath) {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
//#endregion
|
|
78
|
-
export {
|
|
78
|
+
export { extractDatasourcesFromCubes };
|
|
@@ -61,12 +61,12 @@ function checkMissingDescriptions(files) {
|
|
|
61
61
|
}
|
|
62
62
|
function createModelRepository(projectPath) {
|
|
63
63
|
const paths = getProjectPaths(projectPath);
|
|
64
|
-
const
|
|
64
|
+
const cubesDir = paths.cubes;
|
|
65
65
|
const viewsDir = paths.views;
|
|
66
66
|
return {
|
|
67
67
|
localPath: () => projectPath,
|
|
68
68
|
dataSchemaFiles: () => {
|
|
69
|
-
const files = [...collectYamlFiles(
|
|
69
|
+
const files = [...collectYamlFiles(cubesDir, projectPath), ...collectYamlFiles(viewsDir, projectPath)];
|
|
70
70
|
return Promise.resolve(files);
|
|
71
71
|
}
|
|
72
72
|
};
|
package/dist/docs/_index.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Bonnard Documentation
|
|
2
2
|
|
|
3
|
-
> Build semantic layers with
|
|
3
|
+
> Build semantic layers with cubes and views.
|
|
4
4
|
|
|
5
5
|
## Cubes
|
|
6
6
|
|
|
7
7
|
### Core
|
|
8
|
-
- [cubes](cubes) - Define
|
|
8
|
+
- [cubes](cubes) - Define cubes with measures and dimensions
|
|
9
9
|
- [cubes.sql](cubes.sql) - Base SQL table or query
|
|
10
10
|
- [cubes.extends](cubes.extends) - Reuse members from other cubes
|
|
11
11
|
- [cubes.public](cubes.public) - Control API visibility
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
## Workflow
|
|
56
56
|
|
|
57
57
|
- [workflow](workflow) - End-to-end development workflow
|
|
58
|
-
- [workflow.validate](workflow.validate) - Validate
|
|
58
|
+
- [workflow.validate](workflow.validate) - Validate cubes and views locally
|
|
59
59
|
- [workflow.deploy](workflow.deploy) - Deploy to Bonnard
|
|
60
60
|
- [workflow.query](workflow.query) - Query the deployed semantic layer
|
|
61
61
|
- [workflow.mcp](workflow.mcp) - Connect AI agents via MCP
|
|
@@ -86,7 +86,7 @@ When `propagate_filters_to_sub_query: true`, filters applied in the main query a
|
|
|
86
86
|
|
|
87
87
|
## How It Works
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
Bonnard generates an optimized LEFT JOIN with an aggregation subquery:
|
|
90
90
|
|
|
91
91
|
```sql
|
|
92
92
|
SELECT
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
Joins define relationships between cubes, allowing queries to combine measures and dimensions from multiple cubes.
|
|
7
|
+
Joins define relationships between cubes, allowing queries to combine measures and dimensions from multiple cubes. Bonnard automatically generates the appropriate SQL JOINs.
|
|
8
8
|
|
|
9
9
|
## Example
|
|
10
10
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# cubes
|
|
2
2
|
|
|
3
|
-
> Define
|
|
3
|
+
> Define cubes that map to your database tables.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
@@ -90,10 +90,10 @@ cubes:
|
|
|
90
90
|
|
|
91
91
|
## File Organization
|
|
92
92
|
|
|
93
|
-
One cube per file in the `bonnard/
|
|
93
|
+
One cube per file in the `bonnard/cubes/` directory:
|
|
94
94
|
|
|
95
95
|
```
|
|
96
|
-
bonnard/
|
|
96
|
+
bonnard/cubes/
|
|
97
97
|
├── orders.yaml
|
|
98
98
|
├── users.yaml
|
|
99
99
|
├── products.yaml
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
There are 12 measure types that determine how values are aggregated. Choose the right type based on your analytical needs.
|
|
8
8
|
|
|
9
9
|
## Measure Types
|
|
10
10
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
The `refresh_key` property determines when
|
|
7
|
+
The `refresh_key` property determines when the cache should be invalidated. Use it to ensure queries return fresh data while optimizing performance.
|
|
8
8
|
|
|
9
9
|
## Example
|
|
10
10
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# syntax
|
|
2
2
|
|
|
3
|
-
> YAML syntax and conventions for
|
|
3
|
+
> YAML syntax and conventions for cubes and views.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Cubes and views are defined in YAML files. Understanding the syntax conventions helps you write correct and maintainable definitions.
|
|
8
8
|
|
|
9
9
|
## File Structure
|
|
10
10
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Bonnard provides special syntax for referencing columns, measures, dimensions, and other cubes within SQL expressions. This enables dynamic, maintainable cube definitions.
|
|
8
8
|
|
|
9
9
|
## Reference Types
|
|
10
10
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
Folders organize view members into logical categories, making large views easier to navigate. They appear as hierarchical groupings in BI tools and
|
|
7
|
+
Folders organize view members into logical categories, making large views easier to navigate. They appear as hierarchical groupings in BI tools and dashboards.
|
|
8
8
|
|
|
9
9
|
## Example
|
|
10
10
|
|
|
@@ -1,39 +1,38 @@
|
|
|
1
1
|
# workflow.deploy
|
|
2
2
|
|
|
3
|
-
> Push
|
|
3
|
+
> Push cubes and views to Bonnard for querying.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
The `bon deploy` command uploads your cubes and views to Bonnard, making them available for querying via the API. It validates
|
|
7
|
+
The `bon deploy` command uploads your cubes and views to Bonnard, making them available for querying via the API. It validates and tests connections before deploying.
|
|
8
8
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
# Deploy all models
|
|
13
12
|
bon deploy
|
|
14
13
|
```
|
|
15
14
|
|
|
16
15
|
## Prerequisites
|
|
17
16
|
|
|
18
17
|
1. **Logged in** — run `bon login` first
|
|
19
|
-
2. **Valid
|
|
18
|
+
2. **Valid cubes and views** — must pass `bon validate`
|
|
20
19
|
3. **Working connections** — data sources must be accessible
|
|
21
20
|
|
|
22
21
|
## What Happens
|
|
23
22
|
|
|
24
|
-
1. **Validates
|
|
23
|
+
1. **Validates** — checks cubes and views for errors
|
|
25
24
|
2. **Tests connections** — verifies data source access
|
|
26
|
-
3. **Uploads
|
|
27
|
-
4. **Activates** — makes
|
|
25
|
+
3. **Uploads** — sends cubes and views to Bonnard
|
|
26
|
+
4. **Activates** — makes cubes and views available for queries
|
|
28
27
|
|
|
29
28
|
## Example Output
|
|
30
29
|
|
|
31
30
|
```
|
|
32
31
|
bon deploy
|
|
33
32
|
|
|
34
|
-
✓ Validating
|
|
35
|
-
✓ bonnard/
|
|
36
|
-
✓ bonnard/
|
|
33
|
+
✓ Validating...
|
|
34
|
+
✓ bonnard/cubes/orders.yaml
|
|
35
|
+
✓ bonnard/cubes/users.yaml
|
|
37
36
|
✓ bonnard/views/orders_overview.yaml
|
|
38
37
|
|
|
39
38
|
✓ Testing connections...
|
|
@@ -44,8 +43,8 @@ bon deploy
|
|
|
44
43
|
|
|
45
44
|
✓ Deploy complete!
|
|
46
45
|
|
|
47
|
-
Your
|
|
48
|
-
https://api.bonnard.dev/v1/your-org
|
|
46
|
+
Your semantic layer is now available at:
|
|
47
|
+
https://api.bonnard.dev/v1/your-org
|
|
49
48
|
```
|
|
50
49
|
|
|
51
50
|
## Deploy Flow
|
|
@@ -58,7 +57,7 @@ bon deploy
|
|
|
58
57
|
├── 2. Test all datasource connections (must succeed)
|
|
59
58
|
│
|
|
60
59
|
├── 3. Upload to Bonnard API
|
|
61
|
-
│ - cubes from bonnard/
|
|
60
|
+
│ - cubes from bonnard/cubes/
|
|
62
61
|
│ - views from bonnard/views/
|
|
63
62
|
│ - datasource configs
|
|
64
63
|
│
|
|
@@ -70,9 +69,9 @@ bon deploy
|
|
|
70
69
|
### Validation Errors
|
|
71
70
|
|
|
72
71
|
```
|
|
73
|
-
✗ Validating
|
|
72
|
+
✗ Validating...
|
|
74
73
|
|
|
75
|
-
bonnard/
|
|
74
|
+
bonnard/cubes/orders.yaml:15:5
|
|
76
75
|
error: Unknown measure type "counts"
|
|
77
76
|
|
|
78
77
|
Deploy aborted. Fix validation errors first.
|
|
@@ -102,7 +101,7 @@ Run: bon login
|
|
|
102
101
|
|
|
103
102
|
| Source | Deployed |
|
|
104
103
|
|--------|----------|
|
|
105
|
-
| `bonnard/
|
|
104
|
+
| `bonnard/cubes/*.yaml` | All cube definitions |
|
|
106
105
|
| `bonnard/views/*.yaml` | All view definitions |
|
|
107
106
|
| `.bon/datasources.yaml` | Connection configs (credentials encrypted) |
|
|
108
107
|
| `bon.yaml` | Project settings |
|
|
@@ -117,7 +116,7 @@ Run: bon login
|
|
|
117
116
|
|
|
118
117
|
1. **Validate first** — run `bon validate` before deploy
|
|
119
118
|
2. **Test locally** — verify queries work before deploying
|
|
120
|
-
3. **Use version control** — commit
|
|
119
|
+
3. **Use version control** — commit cubes and views before deploying
|
|
121
120
|
4. **Monitor after deploy** — check for query errors
|
|
122
121
|
|
|
123
122
|
## See Also
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
After deploying
|
|
7
|
+
After deploying with `bon deploy`, AI agents can query your semantic layer through the Model Context Protocol (MCP). Bonnard's MCP server provides tools for exploring your data model and running queries.
|
|
8
|
+
|
|
9
|
+
MCP is supported by Claude, ChatGPT, Cursor, Windsurf, VS Code, Gemini, and more.
|
|
8
10
|
|
|
9
11
|
## MCP URL
|
|
10
12
|
|
|
@@ -16,7 +18,45 @@ https://mcp.bonnard.dev/mcp
|
|
|
16
18
|
|
|
17
19
|
### Claude Desktop
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
1. Open **Settings > Connectors**
|
|
22
|
+
2. Click **Add custom connector**
|
|
23
|
+
3. Enter a name (e.g. "Bonnard MCP") and the MCP URL: `https://mcp.bonnard.dev/mcp`
|
|
24
|
+
4. Click **Add**
|
|
25
|
+
|
|
26
|
+

|
|
27
|
+
|
|
28
|
+

|
|
29
|
+
|
|
30
|
+
Once added, enable the Bonnard connector in any chat via the **Connectors** menu:
|
|
31
|
+
|
|
32
|
+

|
|
33
|
+
|
|
34
|
+
Remote MCP servers in Claude Desktop must be added through the Connectors UI, not the JSON config file.
|
|
35
|
+
|
|
36
|
+
### ChatGPT
|
|
37
|
+
|
|
38
|
+
1. Open **Settings > Apps**
|
|
39
|
+
2. Click **Advanced settings** and enable **Developer mode**
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+

|
|
44
|
+
|
|
45
|
+
3. Click **Create app**
|
|
46
|
+
4. Enter a name (e.g. "Bonnard MCP"), the MCP URL `https://mcp.bonnard.dev/mcp`, and select **OAuth** for authentication
|
|
47
|
+
5. Check the acknowledgement box and click **Create**
|
|
48
|
+
|
|
49
|
+

|
|
50
|
+
|
|
51
|
+
Once created, the Bonnard connector appears in the **More** menu in any chat:
|
|
52
|
+
|
|
53
|
+

|
|
54
|
+
|
|
55
|
+
Available on Pro and Plus plans.
|
|
56
|
+
|
|
57
|
+
### Cursor
|
|
58
|
+
|
|
59
|
+
Open **Settings > MCP** and add the server URL, or add to `.cursor/mcp.json` in your project:
|
|
20
60
|
|
|
21
61
|
```json
|
|
22
62
|
{
|
|
@@ -28,14 +68,15 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
|
28
68
|
}
|
|
29
69
|
```
|
|
30
70
|
|
|
31
|
-
###
|
|
71
|
+
### VS Code / GitHub Copilot
|
|
32
72
|
|
|
33
|
-
Add to `.
|
|
73
|
+
Open the Command Palette and run **MCP: Add Server**, or add to `.vscode/mcp.json` in your project:
|
|
34
74
|
|
|
35
75
|
```json
|
|
36
76
|
{
|
|
37
|
-
"
|
|
77
|
+
"servers": {
|
|
38
78
|
"bonnard": {
|
|
79
|
+
"type": "http",
|
|
39
80
|
"url": "https://mcp.bonnard.dev/mcp"
|
|
40
81
|
}
|
|
41
82
|
}
|
|
@@ -44,13 +85,47 @@ Add to `.cursor/mcp.json` in your project:
|
|
|
44
85
|
|
|
45
86
|
### Claude Code
|
|
46
87
|
|
|
47
|
-
|
|
88
|
+
Run in your terminal:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
claude mcp add --transport http bonnard https://mcp.bonnard.dev/mcp
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Or add to `.mcp.json` in your project:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"mcpServers": {
|
|
99
|
+
"bonnard": {
|
|
100
|
+
"type": "http",
|
|
101
|
+
"url": "https://mcp.bonnard.dev/mcp"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Windsurf
|
|
108
|
+
|
|
109
|
+
Open **Settings > Plugins > Manage plugins > View raw config**, or edit `~/.codeium/windsurf/mcp_config.json`:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"mcpServers": {
|
|
114
|
+
"bonnard": {
|
|
115
|
+
"serverUrl": "https://mcp.bonnard.dev/mcp"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Gemini CLI
|
|
122
|
+
|
|
123
|
+
Add to `.gemini/settings.json` in your project or `~/.gemini/settings.json` globally:
|
|
48
124
|
|
|
49
125
|
```json
|
|
50
126
|
{
|
|
51
127
|
"mcpServers": {
|
|
52
128
|
"bonnard": {
|
|
53
|
-
"type": "url",
|
|
54
129
|
"url": "https://mcp.bonnard.dev/mcp"
|
|
55
130
|
}
|
|
56
131
|
}
|
|
@@ -61,38 +136,36 @@ Add to `.mcp.json` in your project:
|
|
|
61
136
|
|
|
62
137
|
MCP uses OAuth 2.0 with PKCE. When an agent first connects:
|
|
63
138
|
|
|
64
|
-
1. Agent discovers OAuth endpoints
|
|
65
|
-
2.
|
|
66
|
-
3.
|
|
67
|
-
4. Agent receives an access token (valid for 7 days)
|
|
68
|
-
5. Token persists across server restarts
|
|
139
|
+
1. Agent discovers OAuth endpoints automatically
|
|
140
|
+
2. You are redirected to Bonnard to sign in and authorize
|
|
141
|
+
3. Agent receives an access token (valid for 30 days)
|
|
69
142
|
|
|
70
143
|
No API keys or manual token management needed.
|
|
71
144
|
|
|
145
|
+
## Available Tools
|
|
146
|
+
|
|
147
|
+
Once connected, AI agents can use these MCP tools:
|
|
148
|
+
|
|
149
|
+
| Tool | Description |
|
|
150
|
+
|------|-------------|
|
|
151
|
+
| `explore_schema` | Discover views and cubes, list their measures, dimensions, and segments. Supports browsing a specific source by name or searching across all fields by keyword. |
|
|
152
|
+
| `query` | Query the semantic layer with measures, dimensions, time dimensions, filters, segments, and pagination. |
|
|
153
|
+
| `sql_query` | Execute raw SQL against the semantic layer using Cube SQL syntax with `MEASURE()` for aggregations. Use for CTEs, UNIONs, and custom calculations. |
|
|
154
|
+
| `describe_field` | Get detailed metadata for a field — SQL expression, type, format, origin cube, and referenced fields. |
|
|
155
|
+
|
|
72
156
|
## Testing
|
|
73
157
|
|
|
74
158
|
```bash
|
|
75
159
|
# Verify the MCP server is reachable
|
|
76
160
|
bon mcp test
|
|
77
161
|
|
|
78
|
-
# View connection info
|
|
162
|
+
# View connection info
|
|
79
163
|
bon mcp
|
|
80
164
|
```
|
|
81
165
|
|
|
82
|
-
## Available Tools
|
|
83
|
-
|
|
84
|
-
Once connected, AI agents can use these MCP tools:
|
|
85
|
-
|
|
86
|
-
| Tool | Description |
|
|
87
|
-
|------|-------------|
|
|
88
|
-
| `query` | Execute a Cube query (measures, dimensions, filters) |
|
|
89
|
-
| `sql_query` | Execute a SQL query via Cube SQL API |
|
|
90
|
-
| `list_cubes` | List available cubes and their members |
|
|
91
|
-
| `list_views` | List available views and their members |
|
|
92
|
-
|
|
93
166
|
## Managing Connections
|
|
94
167
|
|
|
95
|
-
Active MCP connections can be viewed and revoked in the Bonnard dashboard
|
|
168
|
+
Active MCP connections can be viewed and revoked in the Bonnard dashboard under **MCP**.
|
|
96
169
|
|
|
97
170
|
## See Also
|
|
98
171
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# workflow
|
|
2
2
|
|
|
3
|
-
> Development workflow for building and deploying
|
|
3
|
+
> Development workflow for building and deploying cubes and views.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
Building semantic
|
|
7
|
+
Building a semantic layer with Bonnard follows a development workflow: initialize a project, connect data sources, define cubes and views, validate, and deploy.
|
|
8
8
|
|
|
9
9
|
## Quick Start
|
|
10
10
|
|
|
@@ -15,9 +15,9 @@ bon init
|
|
|
15
15
|
# 2. Add a data source
|
|
16
16
|
bon datasource add
|
|
17
17
|
|
|
18
|
-
# 3. Create
|
|
18
|
+
# 3. Create cubes in bonnard/cubes/ and views in bonnard/views/
|
|
19
19
|
|
|
20
|
-
# 4. Validate
|
|
20
|
+
# 4. Validate
|
|
21
21
|
bon validate
|
|
22
22
|
|
|
23
23
|
# 5. Deploy to Bonnard
|
|
@@ -32,7 +32,7 @@ After `bon init`, your project has:
|
|
|
32
32
|
my-project/
|
|
33
33
|
├── bon.yaml # Project configuration
|
|
34
34
|
├── bonnard/ # Semantic layer definitions
|
|
35
|
-
│ ├──
|
|
35
|
+
│ ├── cubes/ # Cube definitions
|
|
36
36
|
│ │ └── orders.yaml
|
|
37
37
|
│ └── views/ # View definitions
|
|
38
38
|
│ └── orders_overview.yaml
|
|
@@ -42,12 +42,12 @@ my-project/
|
|
|
42
42
|
|
|
43
43
|
## Development Cycle
|
|
44
44
|
|
|
45
|
-
### 1. Define
|
|
45
|
+
### 1. Define Cubes
|
|
46
46
|
|
|
47
47
|
Create cubes that map to your database tables:
|
|
48
48
|
|
|
49
49
|
```yaml
|
|
50
|
-
# bonnard/
|
|
50
|
+
# bonnard/cubes/orders.yaml
|
|
51
51
|
cubes:
|
|
52
52
|
- name: orders
|
|
53
53
|
sql_table: public.orders
|
|
@@ -88,7 +88,7 @@ bon validate --test-connection
|
|
|
88
88
|
|
|
89
89
|
### 4. Deploy
|
|
90
90
|
|
|
91
|
-
Push
|
|
91
|
+
Push cubes and views to Bonnard:
|
|
92
92
|
|
|
93
93
|
```bash
|
|
94
94
|
bon deploy
|
|
@@ -99,7 +99,7 @@ bon deploy
|
|
|
99
99
|
### One Cube Per File
|
|
100
100
|
|
|
101
101
|
```
|
|
102
|
-
bonnard/
|
|
102
|
+
bonnard/cubes/
|
|
103
103
|
├── orders.yaml
|
|
104
104
|
├── users.yaml
|
|
105
105
|
├── products.yaml
|
|
@@ -109,7 +109,7 @@ bonnard/models/
|
|
|
109
109
|
### Related Cubes Together
|
|
110
110
|
|
|
111
111
|
```
|
|
112
|
-
bonnard/
|
|
112
|
+
bonnard/cubes/
|
|
113
113
|
├── sales/
|
|
114
114
|
│ ├── orders.yaml
|
|
115
115
|
│ └── line_items.yaml
|
|
@@ -124,7 +124,7 @@ bonnard/models/
|
|
|
124
124
|
|
|
125
125
|
1. **Start simple** — begin with one cube, add complexity gradually
|
|
126
126
|
2. **Validate often** — run `bon validate` after each change
|
|
127
|
-
3. **Use version control** — commit
|
|
127
|
+
3. **Use version control** — commit cubes and views to git
|
|
128
128
|
4. **Document with descriptions** — add `description` to measures/dimensions
|
|
129
129
|
5. **Test with queries** — verify models produce expected results
|
|
130
130
|
|
|
@@ -136,9 +136,9 @@ bonnard/models/
|
|
|
136
136
|
| `bon datasource add` | Add a data source |
|
|
137
137
|
| `bon datasource list` | List configured sources |
|
|
138
138
|
| `bon datasource test <name>` | Test connection |
|
|
139
|
-
| `bon validate` | Check
|
|
139
|
+
| `bon validate` | Check cube and view syntax |
|
|
140
140
|
| `bon deploy` | Deploy to Bonnard |
|
|
141
|
-
| `bon docs` | Browse
|
|
141
|
+
| `bon docs` | Browse documentation |
|
|
142
142
|
|
|
143
143
|
## See Also
|
|
144
144
|
|
|
@@ -4,20 +4,20 @@
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
After deploying
|
|
7
|
+
After deploying with `bon deploy`, you can query the semantic layer using `bon query`. This tests that your cubes and views work correctly and returns data from your warehouse through Bonnard.
|
|
8
8
|
|
|
9
9
|
## Query Formats
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Bonnard supports two query formats:
|
|
12
12
|
|
|
13
13
|
### JSON Format (Default)
|
|
14
14
|
|
|
15
|
-
The JSON format uses
|
|
15
|
+
The JSON format uses the REST API structure:
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
bon
|
|
18
|
+
bon query '{"measures": ["orders.count"]}'
|
|
19
19
|
|
|
20
|
-
bon
|
|
20
|
+
bon query '{
|
|
21
21
|
"measures": ["orders.total_revenue"],
|
|
22
22
|
"dimensions": ["orders.status"],
|
|
23
23
|
"filters": [{
|
|
@@ -36,7 +36,7 @@ bon cube query '{
|
|
|
36
36
|
| `dimensions` | Array of dimensions to group by (e.g., `["orders.status"]`) |
|
|
37
37
|
| `filters` | Array of filter objects |
|
|
38
38
|
| `timeDimensions` | Time-based grouping with granularity |
|
|
39
|
-
| `segments` | Named filters defined in
|
|
39
|
+
| `segments` | Named filters defined in cubes |
|
|
40
40
|
| `limit` | Max rows to return |
|
|
41
41
|
| `offset` | Skip rows (pagination) |
|
|
42
42
|
| `order` | Sort specification |
|
|
@@ -54,12 +54,12 @@ bon cube query '{
|
|
|
54
54
|
|
|
55
55
|
### SQL Format
|
|
56
56
|
|
|
57
|
-
The SQL format uses
|
|
57
|
+
The SQL format uses the SQL API, where cubes are tables:
|
|
58
58
|
|
|
59
59
|
```bash
|
|
60
|
-
bon
|
|
60
|
+
bon query --sql "SELECT status, MEASURE(count) FROM orders GROUP BY 1"
|
|
61
61
|
|
|
62
|
-
bon
|
|
62
|
+
bon query --sql "SELECT
|
|
63
63
|
city,
|
|
64
64
|
MEASURE(total_revenue),
|
|
65
65
|
MEASURE(avg_order_value)
|
|
@@ -97,16 +97,16 @@ ORDER BY 1
|
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
99
|
# JSON format (default)
|
|
100
|
-
bon
|
|
100
|
+
bon query '{"measures": ["orders.count"]}'
|
|
101
101
|
|
|
102
102
|
# SQL format
|
|
103
|
-
bon
|
|
103
|
+
bon query --sql "SELECT MEASURE(count) FROM orders"
|
|
104
104
|
|
|
105
105
|
# Limit rows
|
|
106
|
-
bon
|
|
106
|
+
bon query '{"measures": ["orders.count"], "dimensions": ["orders.city"]}' --limit 10
|
|
107
107
|
|
|
108
108
|
# JSON output (instead of table)
|
|
109
|
-
bon
|
|
109
|
+
bon query '{"measures": ["orders.count"]}' --format json
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
## Output Formats
|
|
@@ -126,7 +126,7 @@ bon cube query '{"measures": ["orders.count"]}' --format json
|
|
|
126
126
|
### JSON Format
|
|
127
127
|
|
|
128
128
|
```bash
|
|
129
|
-
bon
|
|
129
|
+
bon query '{"measures": ["orders.count"]}' --format json
|
|
130
130
|
```
|
|
131
131
|
|
|
132
132
|
```json
|
|
@@ -142,7 +142,7 @@ bon cube query '{"measures": ["orders.count"]}' --format json
|
|
|
142
142
|
### Time Series Analysis
|
|
143
143
|
|
|
144
144
|
```bash
|
|
145
|
-
bon
|
|
145
|
+
bon query '{
|
|
146
146
|
"measures": ["orders.total_revenue"],
|
|
147
147
|
"timeDimensions": [{
|
|
148
148
|
"dimension": "orders.created_at",
|
|
@@ -155,7 +155,7 @@ bon cube query '{
|
|
|
155
155
|
### Filtering by Dimension
|
|
156
156
|
|
|
157
157
|
```bash
|
|
158
|
-
bon
|
|
158
|
+
bon query '{
|
|
159
159
|
"measures": ["orders.count"],
|
|
160
160
|
"dimensions": ["orders.city"],
|
|
161
161
|
"filters": [{
|
|
@@ -169,7 +169,7 @@ bon cube query '{
|
|
|
169
169
|
### Multiple Measures
|
|
170
170
|
|
|
171
171
|
```bash
|
|
172
|
-
bon
|
|
172
|
+
bon query '{
|
|
173
173
|
"measures": ["orders.count", "orders.total_revenue", "orders.avg_order_value"],
|
|
174
174
|
"dimensions": ["orders.category"]
|
|
175
175
|
}'
|
|
@@ -184,15 +184,15 @@ bon cube query '{
|
|
|
184
184
|
- All measures must use `MEASURE()` or matching aggregate
|
|
185
185
|
|
|
186
186
|
**"Cube not found"**
|
|
187
|
-
- Check cube name matches deployed
|
|
188
|
-
- Run `bon deploy` if
|
|
187
|
+
- Check cube name matches deployed cube
|
|
188
|
+
- Run `bon deploy` if cubes changed
|
|
189
189
|
|
|
190
190
|
**"Not logged in"**
|
|
191
191
|
- Run `bon login` first
|
|
192
192
|
|
|
193
193
|
## See Also
|
|
194
194
|
|
|
195
|
-
- [workflow.deploy](workflow.deploy) - Deploy
|
|
195
|
+
- [workflow.deploy](workflow.deploy) - Deploy before querying
|
|
196
196
|
- [cubes.measures](cubes.measures) - Define measures
|
|
197
197
|
- [cubes.dimensions](cubes.dimensions) - Define dimensions
|
|
198
198
|
- [views](views) - Create focused query interfaces
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# workflow.validate
|
|
2
2
|
|
|
3
|
-
> Check
|
|
3
|
+
> Check cubes and views for errors before deploying.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
The `bon validate` command checks your YAML
|
|
7
|
+
The `bon validate` command checks your YAML cubes and views for syntax errors, schema violations, and optionally tests data source connections. Run this before deploying to catch issues early.
|
|
8
8
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
@@ -48,11 +48,11 @@ bon validate --test-connection
|
|
|
48
48
|
|
|
49
49
|
```
|
|
50
50
|
✓ Validating YAML syntax...
|
|
51
|
-
✓ Checking bonnard/
|
|
52
|
-
✓ Checking bonnard/
|
|
51
|
+
✓ Checking bonnard/cubes/orders.yaml
|
|
52
|
+
✓ Checking bonnard/cubes/users.yaml
|
|
53
53
|
✓ Checking bonnard/views/orders_overview.yaml
|
|
54
54
|
|
|
55
|
-
All
|
|
55
|
+
All cubes and views valid.
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
### Errors
|
|
@@ -60,7 +60,7 @@ All models valid.
|
|
|
60
60
|
```
|
|
61
61
|
✗ Validating YAML syntax...
|
|
62
62
|
|
|
63
|
-
bonnard/
|
|
63
|
+
bonnard/cubes/orders.yaml:15:5
|
|
64
64
|
error: Unknown measure type "counts"
|
|
65
65
|
|
|
66
66
|
Did you mean "count"?
|
|
@@ -77,7 +77,7 @@ bonnard/models/orders.yaml:15:5
|
|
|
77
77
|
|
|
78
78
|
```
|
|
79
79
|
✓ Validating YAML syntax...
|
|
80
|
-
✓ All
|
|
80
|
+
✓ All cubes and views valid.
|
|
81
81
|
|
|
82
82
|
⚠ Testing connections...
|
|
83
83
|
⚠ datasource "analytics": Connection timed out
|
|
@@ -25,8 +25,8 @@ bon datasource remove <name> # Remove data source
|
|
|
25
25
|
|
|
26
26
|
### Development
|
|
27
27
|
```bash
|
|
28
|
-
bon validate # Validate
|
|
29
|
-
bon deploy # Deploy to Bonnard
|
|
28
|
+
bon validate # Validate cubes and views
|
|
29
|
+
bon deploy # Deploy to Bonnard
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
### Data Exploration (Local)
|
|
@@ -39,12 +39,12 @@ bon preview <datasource> "<sql>" --limit 100 # Limit rows
|
|
|
39
39
|
### Semantic Layer Queries (Deployed)
|
|
40
40
|
```bash
|
|
41
41
|
# JSON format (default)
|
|
42
|
-
bon
|
|
43
|
-
bon
|
|
42
|
+
bon query '{"measures": ["orders.count"]}'
|
|
43
|
+
bon query '{"measures": ["orders.total_revenue"], "dimensions": ["orders.status"]}'
|
|
44
44
|
|
|
45
45
|
# SQL format
|
|
46
|
-
bon
|
|
47
|
-
bon
|
|
46
|
+
bon query --sql "SELECT status, MEASURE(count) FROM orders GROUP BY 1"
|
|
47
|
+
bon query --sql "SELECT city, SUM(amount) FROM orders GROUP BY 1" --limit 10
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
### Documentation
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bonnard-queries
|
|
3
|
-
description: How to write
|
|
3
|
+
description: How to write queries and work with cubes and views. Use when user asks about metrics, dimensions, or data modeling.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Bonnard Query Patterns
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## Cube Structure (YAML)
|
|
9
9
|
|
|
10
10
|
```yaml
|
|
11
11
|
cubes:
|
|
@@ -49,7 +49,7 @@ views:
|
|
|
49
49
|
|
|
50
50
|
## Workflow
|
|
51
51
|
|
|
52
|
-
1. Define
|
|
52
|
+
1. Define cubes in `bonnard/cubes/*.yaml`
|
|
53
53
|
2. Define views in `bonnard/views/*.yaml`
|
|
54
54
|
3. Run `bon validate` to check syntax
|
|
55
55
|
4. Run `bon deploy` to publish
|
|
@@ -24,8 +24,8 @@ bon datasource remove <name> # Remove data source
|
|
|
24
24
|
|
|
25
25
|
### Development
|
|
26
26
|
```bash
|
|
27
|
-
bon validate # Validate
|
|
28
|
-
bon deploy # Deploy to Bonnard
|
|
27
|
+
bon validate # Validate cubes and views
|
|
28
|
+
bon deploy # Deploy to Bonnard
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
### Data Exploration (Local)
|
|
@@ -38,10 +38,10 @@ bon preview <datasource> "<sql>" --limit 100 # Limit rows
|
|
|
38
38
|
### Semantic Layer Queries (Deployed)
|
|
39
39
|
```bash
|
|
40
40
|
# JSON format (default)
|
|
41
|
-
bon
|
|
42
|
-
bon
|
|
41
|
+
bon query '{"measures": ["orders.count"]}'
|
|
42
|
+
bon query '{"measures": ["orders.total_revenue"], "dimensions": ["orders.status"]}'
|
|
43
43
|
|
|
44
44
|
# SQL format
|
|
45
|
-
bon
|
|
46
|
-
bon
|
|
45
|
+
bon query --sql "SELECT status, MEASURE(count) FROM orders GROUP BY 1"
|
|
46
|
+
bon query --sql "SELECT city, SUM(amount) FROM orders GROUP BY 1" --limit 10
|
|
47
47
|
```
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "How to write
|
|
2
|
+
description: "How to write queries and work with cubes and views. Use when user asks about metrics, dimensions, or data modeling."
|
|
3
3
|
alwaysApply: false
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Bonnard Query Patterns
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## Cube Structure (YAML)
|
|
9
9
|
|
|
10
10
|
```yaml
|
|
11
11
|
cubes:
|
|
@@ -43,7 +43,7 @@ views:
|
|
|
43
43
|
|
|
44
44
|
## Workflow
|
|
45
45
|
|
|
46
|
-
1. Define
|
|
46
|
+
1. Define cubes in `bonnard/cubes/*.yaml`
|
|
47
47
|
2. Define views in `bonnard/views/*.yaml`
|
|
48
48
|
3. Run `bon validate` to check syntax
|
|
49
49
|
4. Run `bon deploy` to publish
|
|
@@ -7,11 +7,11 @@ Bonnard is a semantic layer platform that sits between your data warehouse and e
|
|
|
7
7
|
```
|
|
8
8
|
Data Warehouse (Snowflake, Postgres, BigQuery, Databricks)
|
|
9
9
|
↓
|
|
10
|
-
|
|
10
|
+
Cubes (measures, dimensions, joins)
|
|
11
11
|
↓
|
|
12
|
-
|
|
12
|
+
Views (curated subsets for specific use cases)
|
|
13
13
|
↓
|
|
14
|
-
Bonnard API
|
|
14
|
+
Bonnard API
|
|
15
15
|
↓
|
|
16
16
|
Consumers (MCP tools, dashboards, analysts)
|
|
17
17
|
```
|
|
@@ -30,7 +30,7 @@ Data Warehouse (Snowflake, Postgres, BigQuery, Databricks)
|
|
|
30
30
|
my-project/
|
|
31
31
|
├── bon.yaml # Project config
|
|
32
32
|
├── bonnard/ # Semantic layer definitions
|
|
33
|
-
│ ├──
|
|
33
|
+
│ ├── cubes/ # Cube definitions
|
|
34
34
|
│ │ ├── orders.yaml
|
|
35
35
|
│ │ └── customers.yaml
|
|
36
36
|
│ └── views/ # View definitions
|
|
@@ -50,11 +50,11 @@ my-project/
|
|
|
50
50
|
| `bon validate` | Validate YAML syntax |
|
|
51
51
|
| `bon validate --test-connection` | Validate + test connections |
|
|
52
52
|
| `bon deploy` | Deploy to Bonnard (requires login) |
|
|
53
|
-
| `bon docs` | Browse
|
|
53
|
+
| `bon docs` | Browse documentation |
|
|
54
54
|
|
|
55
|
-
## Learning
|
|
55
|
+
## Learning YAML Syntax
|
|
56
56
|
|
|
57
|
-
Use `bon docs` to explore
|
|
57
|
+
Use `bon docs` to explore data modeling concepts:
|
|
58
58
|
|
|
59
59
|
```bash
|
|
60
60
|
bon docs # Show all topics
|
|
@@ -73,7 +73,7 @@ Topics follow dot notation (e.g., `cubes.dimensions.time`). Use `--recursive` to
|
|
|
73
73
|
## Workflow
|
|
74
74
|
|
|
75
75
|
1. **Setup datasource** — `bon datasource add --from-dbt` or manual
|
|
76
|
-
2. **Create cubes** — Define measures/dimensions in `bonnard/
|
|
76
|
+
2. **Create cubes** — Define measures/dimensions in `bonnard/cubes/*.yaml`
|
|
77
77
|
3. **Create views** — Compose cubes in `bonnard/views/*.yaml`
|
|
78
78
|
4. **Validate** — `bon validate --test-connection`
|
|
79
79
|
5. **Deploy** — `bon login` then `bon deploy`
|