@bonnard/cli 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/bin/bon.mjs +1919 -100
  2. package/dist/bin/models-IsV2sX74.mjs +76 -0
  3. package/dist/bin/{validate-Bd1D39Bj.mjs → validate-C4EHvJzJ.mjs} +47 -4
  4. package/dist/docs/README.md +78 -0
  5. package/dist/docs/_index.md +70 -0
  6. package/dist/docs/topics/cubes.data-source.md +92 -0
  7. package/dist/docs/topics/cubes.dimensions.format.md +195 -0
  8. package/dist/docs/topics/cubes.dimensions.md +184 -0
  9. package/dist/docs/topics/cubes.dimensions.primary-key.md +106 -0
  10. package/dist/docs/topics/cubes.dimensions.sub-query.md +174 -0
  11. package/dist/docs/topics/cubes.dimensions.time.md +111 -0
  12. package/dist/docs/topics/cubes.dimensions.types.md +107 -0
  13. package/dist/docs/topics/cubes.extends.md +149 -0
  14. package/dist/docs/topics/cubes.hierarchies.md +174 -0
  15. package/dist/docs/topics/cubes.joins.md +115 -0
  16. package/dist/docs/topics/cubes.md +117 -0
  17. package/dist/docs/topics/cubes.measures.calculated.md +99 -0
  18. package/dist/docs/topics/cubes.measures.drill-members.md +158 -0
  19. package/dist/docs/topics/cubes.measures.filters.md +86 -0
  20. package/dist/docs/topics/cubes.measures.format.md +153 -0
  21. package/dist/docs/topics/cubes.measures.md +162 -0
  22. package/dist/docs/topics/cubes.measures.rolling.md +119 -0
  23. package/dist/docs/topics/cubes.measures.types.md +122 -0
  24. package/dist/docs/topics/cubes.public.md +172 -0
  25. package/dist/docs/topics/cubes.refresh-key.md +153 -0
  26. package/dist/docs/topics/cubes.segments.md +121 -0
  27. package/dist/docs/topics/cubes.sql.md +61 -0
  28. package/dist/docs/topics/pre-aggregations.md +126 -0
  29. package/dist/docs/topics/pre-aggregations.rollup.md +162 -0
  30. package/dist/docs/topics/syntax.context-variables.md +153 -0
  31. package/dist/docs/topics/syntax.md +133 -0
  32. package/dist/docs/topics/syntax.references.md +174 -0
  33. package/dist/docs/topics/views.cubes.md +162 -0
  34. package/dist/docs/topics/views.folders.md +154 -0
  35. package/dist/docs/topics/views.includes.md +139 -0
  36. package/dist/docs/topics/views.md +138 -0
  37. package/dist/docs/topics/workflow.deploy.md +128 -0
  38. package/dist/docs/topics/workflow.mcp.md +100 -0
  39. package/dist/docs/topics/workflow.md +147 -0
  40. package/dist/docs/topics/workflow.query.md +198 -0
  41. package/dist/docs/topics/workflow.validate.md +152 -0
  42. package/dist/templates/claude/rules/bonnard.md +15 -0
  43. package/dist/templates/claude/settings.json +7 -0
  44. package/dist/templates/claude/skills/bonnard-cli/SKILL.md +59 -0
  45. package/dist/templates/claude/skills/bonnard-queries/SKILL.md +68 -0
  46. package/dist/templates/cursor/rules/bonnard-cli.mdc +47 -0
  47. package/dist/templates/cursor/rules/bonnard-queries.mdc +49 -0
  48. package/dist/templates/cursor/rules/bonnard.mdc +20 -0
  49. package/dist/templates/shared/bonnard.md +81 -0
  50. package/package.json +13 -8
@@ -0,0 +1,158 @@
1
+ # cubes.measures.drill-members
2
+
3
+ > Define which dimensions to show when drilling into a measure.
4
+
5
+ ## Overview
6
+
7
+ The `drill_members` property specifies which dimensions should be displayed when a user "drills down" into a measure to see the underlying detail records.
8
+
9
+ ## Example
10
+
11
+ ```yaml
12
+ cubes:
13
+ - name: orders
14
+ sql_table: orders
15
+
16
+ measures:
17
+ - name: count
18
+ type: count
19
+ drill_members:
20
+ - id
21
+ - status
22
+ - created_at
23
+ - customer_name
24
+
25
+ - name: total_revenue
26
+ type: sum
27
+ sql: amount
28
+ drill_members:
29
+ - id
30
+ - amount
31
+ - status
32
+ - created_at
33
+
34
+ dimensions:
35
+ - name: id
36
+ type: number
37
+ sql: id
38
+ primary_key: true
39
+
40
+ - name: status
41
+ type: string
42
+ sql: status
43
+
44
+ - name: amount
45
+ type: number
46
+ sql: amount
47
+
48
+ - name: customer_name
49
+ type: string
50
+ sql: customer_name
51
+
52
+ - name: created_at
53
+ type: time
54
+ sql: created_at
55
+ ```
56
+
57
+ ## Syntax
58
+
59
+ List dimensions by name:
60
+
61
+ ```yaml
62
+ measures:
63
+ - name: count
64
+ type: count
65
+ drill_members:
66
+ - id
67
+ - name
68
+ - email
69
+ - created_at
70
+ ```
71
+
72
+ ## How Drill-Down Works
73
+
74
+ 1. User sees aggregated measure (e.g., "Orders: 1,234")
75
+ 2. User clicks to drill down
76
+ 3. BI tool queries the specified `drill_members` dimensions
77
+ 4. User sees detail records that make up that aggregate
78
+
79
+ ## Cross-Cube Drill Members
80
+
81
+ Reference dimensions from joined cubes:
82
+
83
+ ```yaml
84
+ cubes:
85
+ - name: orders
86
+ joins:
87
+ - name: users
88
+ relationship: many_to_one
89
+ sql: "{CUBE}.user_id = {users.id}"
90
+
91
+ measures:
92
+ - name: count
93
+ type: count
94
+ drill_members:
95
+ - id
96
+ - status
97
+ - users.name # From joined cube
98
+ - users.email # From joined cube
99
+ - created_at
100
+ ```
101
+
102
+ ## Best Practices
103
+
104
+ ### Include Identifying Information
105
+
106
+ ```yaml
107
+ drill_members:
108
+ - id # Primary identifier
109
+ - name # Human-readable name
110
+ - created_at # When it happened
111
+ ```
112
+
113
+ ### Include Relevant Context
114
+
115
+ ```yaml
116
+ # For a revenue measure
117
+ drill_members:
118
+ - order_id
119
+ - product_name
120
+ - amount # The value being summed
121
+ - customer_name
122
+ - order_date
123
+ ```
124
+
125
+ ### Keep Lists Focused
126
+
127
+ Don't include every dimension—focus on what's useful for understanding that specific measure:
128
+
129
+ ```yaml
130
+ # Good - focused on revenue context
131
+ - name: total_revenue
132
+ drill_members:
133
+ - id
134
+ - amount
135
+ - product
136
+ - customer
137
+
138
+ # Bad - too many unrelated fields
139
+ - name: total_revenue
140
+ drill_members:
141
+ - id
142
+ - amount
143
+ - product
144
+ - customer
145
+ - internal_code
146
+ - debug_flag
147
+ - sync_status
148
+ ```
149
+
150
+ ## BI Tool Support
151
+
152
+ Drill-down support varies by visualization tool. Check your specific tool's documentation for how it handles `drill_members`.
153
+
154
+ ## See Also
155
+
156
+ - cubes.measures
157
+ - cubes.dimensions
158
+ - cubes.joins
@@ -0,0 +1,86 @@
1
+ # cubes.measures.filters
2
+
3
+ > Apply permanent filters to measures for conditional aggregations.
4
+
5
+ ## Overview
6
+
7
+ The `filters` property lets you define measures that only count or aggregate rows matching specific conditions. This creates reusable filtered metrics without requiring query-time filters.
8
+
9
+ ## Example
10
+
11
+ ```yaml
12
+ measures:
13
+ - name: completed_orders
14
+ type: count
15
+ filters:
16
+ - sql: "{CUBE}.status = 'completed'"
17
+
18
+ - name: revenue_this_year
19
+ type: sum
20
+ sql: amount
21
+ filters:
22
+ - sql: "YEAR({CUBE}.created_at) = YEAR(CURRENT_DATE)"
23
+ ```
24
+
25
+ ## Syntax
26
+
27
+ ### Single Filter
28
+
29
+ ```yaml
30
+ - name: active_users
31
+ type: count_distinct
32
+ sql: user_id
33
+ filters:
34
+ - sql: "{CUBE}.is_active = true"
35
+ ```
36
+
37
+ ### Multiple Filters (AND logic)
38
+
39
+ ```yaml
40
+ - name: completed_paid_orders
41
+ type: count
42
+ filters:
43
+ - sql: "{CUBE}.status = 'completed'"
44
+ - sql: "{CUBE}.payment_status = 'paid'"
45
+ ```
46
+
47
+ ## Use Cases
48
+
49
+ ### Percentage Calculations
50
+
51
+ ```yaml
52
+ measures:
53
+ - name: total_orders
54
+ type: count
55
+
56
+ - name: completed_orders
57
+ type: count
58
+ filters:
59
+ - sql: "{CUBE}.status = 'completed'"
60
+
61
+ - name: completion_rate
62
+ type: number
63
+ sql: "100.0 * {completed_orders} / NULLIF({total_orders}, 0)"
64
+ format: percent
65
+ ```
66
+
67
+ ### Time-Based Metrics
68
+
69
+ ```yaml
70
+ - name: orders_last_30_days
71
+ type: count
72
+ filters:
73
+ - sql: "{CUBE}.created_at >= CURRENT_DATE - INTERVAL '30 days'"
74
+ ```
75
+
76
+ ## Best Practices
77
+
78
+ 1. **Use {CUBE}** to reference the current cube's columns
79
+ 2. **Combine with number type** for calculated ratios
80
+ 3. **Keep filters simple** — complex logic belongs in the base SQL
81
+
82
+ ## See Also
83
+
84
+ - cubes.measures
85
+ - cubes.measures.calculated
86
+ - cubes.segments
@@ -0,0 +1,153 @@
1
+ # cubes.measures.format
2
+
3
+ > Specify how measure values should be displayed.
4
+
5
+ ## Overview
6
+
7
+ The `format` property hints to BI tools how to display measure values. This affects rendering in dashboards and reports.
8
+
9
+ ## Example
10
+
11
+ ```yaml
12
+ measures:
13
+ - name: total_revenue
14
+ type: sum
15
+ sql: amount
16
+ format: currency
17
+
18
+ - name: conversion_rate
19
+ type: number
20
+ sql: "{conversions} / NULLIF({visits}, 0)"
21
+ format: percent
22
+
23
+ - name: order_count
24
+ type: count
25
+ # No format - displays as plain number
26
+ ```
27
+
28
+ ## Supported Formats
29
+
30
+ ### percent
31
+
32
+ Displays value as a percentage:
33
+
34
+ ```yaml
35
+ - name: completion_rate
36
+ type: number
37
+ sql: "{completed} / NULLIF({total}, 0)"
38
+ format: percent
39
+ ```
40
+
41
+ Output: `75%` instead of `0.75`
42
+
43
+ ### currency
44
+
45
+ Displays value as monetary amount:
46
+
47
+ ```yaml
48
+ - name: total_revenue
49
+ type: sum
50
+ sql: amount
51
+ format: currency
52
+ ```
53
+
54
+ Output: `$1,234.56` (formatting depends on BI tool locale)
55
+
56
+ ## Usage Notes
57
+
58
+ ### Format vs Calculation
59
+
60
+ Format is for display only—it doesn't change the underlying value:
61
+
62
+ ```yaml
63
+ # Value is 0.75, displayed as 75%
64
+ - name: rate
65
+ type: number
66
+ sql: "{part} / NULLIF({whole}, 0)"
67
+ format: percent
68
+
69
+ # If you want the value to be 75, multiply in SQL
70
+ - name: rate_as_whole_number
71
+ type: number
72
+ sql: "100.0 * {part} / NULLIF({whole}, 0)"
73
+ format: percent # Displays as 7500% - probably not what you want!
74
+ ```
75
+
76
+ ### Percentages
77
+
78
+ For percentages, your SQL should return a decimal (0.75 for 75%):
79
+
80
+ ```yaml
81
+ # Correct - returns 0.75, displays as 75%
82
+ - name: conversion_rate
83
+ type: number
84
+ sql: "{conversions} / NULLIF({visits}, 0)"
85
+ format: percent
86
+
87
+ # Also correct - explicit multiplication for clarity
88
+ - name: conversion_rate
89
+ type: number
90
+ sql: "1.0 * {conversions} / NULLIF({visits}, 0)"
91
+ format: percent
92
+ ```
93
+
94
+ ### Currency
95
+
96
+ For currency, return the raw numeric value:
97
+
98
+ ```yaml
99
+ # Correct - returns 1234.56, displays as $1,234.56
100
+ - name: revenue
101
+ type: sum
102
+ sql: amount
103
+ format: currency
104
+ ```
105
+
106
+ ## Common Patterns
107
+
108
+ ### Financial Measures
109
+
110
+ ```yaml
111
+ measures:
112
+ - name: revenue
113
+ type: sum
114
+ sql: amount
115
+ format: currency
116
+
117
+ - name: cost
118
+ type: sum
119
+ sql: cost
120
+ format: currency
121
+
122
+ - name: profit_margin
123
+ type: number
124
+ sql: "({revenue} - {cost}) / NULLIF({revenue}, 0)"
125
+ format: percent
126
+ ```
127
+
128
+ ### Conversion Metrics
129
+
130
+ ```yaml
131
+ measures:
132
+ - name: visits
133
+ type: count_distinct
134
+ sql: session_id
135
+
136
+ - name: signups
137
+ type: count
138
+
139
+ - name: signup_rate
140
+ type: number
141
+ sql: "{signups} / NULLIF({visits}, 0)"
142
+ format: percent
143
+ ```
144
+
145
+ ## BI Tool Support
146
+
147
+ Format support varies by visualization tool. Most tools recognize `percent` and `currency`, but rendering specifics (decimal places, currency symbol) depend on the tool's configuration.
148
+
149
+ ## See Also
150
+
151
+ - cubes.measures
152
+ - cubes.measures.types
153
+ - cubes.dimensions.format
@@ -0,0 +1,162 @@
1
+ # cubes.measures
2
+
3
+ > Define metrics and aggregations for analytical queries.
4
+
5
+ ## Overview
6
+
7
+ Measures are the quantitative values in your data model — counts, sums, averages, and other aggregations. They answer questions like "how many?", "how much?", and "what's the average?".
8
+
9
+ ## Example
10
+
11
+ ```yaml
12
+ measures:
13
+ - name: count
14
+ type: count
15
+ description: Total number of orders
16
+
17
+ - name: total_revenue
18
+ type: sum
19
+ sql: amount
20
+ description: Sum of order amounts in dollars
21
+
22
+ - name: average_order_value
23
+ type: number
24
+ sql: "{total_revenue} / NULLIF({count}, 0)"
25
+ description: Average revenue per order
26
+
27
+ - name: completed_orders
28
+ type: count
29
+ filters:
30
+ - sql: "{CUBE}.status = 'completed'"
31
+ description: Orders with status completed
32
+ ```
33
+
34
+ ## Required Properties
35
+
36
+ | Property | Description |
37
+ |----------|-------------|
38
+ | `name` | Unique identifier in snake_case |
39
+ | `type` | Aggregation type (count, sum, avg, etc.) |
40
+
41
+ ## Optional Properties
42
+
43
+ | Property | Description |
44
+ |----------|-------------|
45
+ | `sql` | SQL expression (required for most types) |
46
+ | `filters` | Conditions for filtered aggregations |
47
+ | `title` | Human-readable display name |
48
+ | `description` | Documentation for consumers |
49
+ | `format` | Output format (percent, currency, etc.) |
50
+ | `public` | Whether exposed in API (default: true) |
51
+ | `rolling_window` | Rolling aggregation settings |
52
+
53
+ ## Measure Types
54
+
55
+ ### Aggregation Types
56
+
57
+ ```yaml
58
+ # Count rows
59
+ - name: count
60
+ type: count
61
+
62
+ # Count distinct values
63
+ - name: unique_users
64
+ type: count_distinct
65
+ sql: user_id
66
+
67
+ # Sum values
68
+ - name: total_revenue
69
+ type: sum
70
+ sql: amount
71
+
72
+ # Average values
73
+ - name: average_price
74
+ type: avg
75
+ sql: price
76
+
77
+ # Min/Max values
78
+ - name: first_order
79
+ type: min
80
+ sql: created_at
81
+
82
+ - name: last_order
83
+ type: max
84
+ sql: created_at
85
+ ```
86
+
87
+ ### Calculated Types
88
+
89
+ ```yaml
90
+ # Calculated number (from other measures)
91
+ - name: average_order_value
92
+ type: number
93
+ sql: "{total_revenue} / NULLIF({count}, 0)"
94
+
95
+ # Boolean result
96
+ - name: has_orders
97
+ type: boolean
98
+ sql: "{count} > 0"
99
+ ```
100
+
101
+ ## Filtered Measures
102
+
103
+ Add conditions to only count/sum matching rows:
104
+
105
+ ```yaml
106
+ - name: completed_orders
107
+ type: count
108
+ filters:
109
+ - sql: "{CUBE}.status = 'completed'"
110
+
111
+ - name: revenue_this_year
112
+ type: sum
113
+ sql: amount
114
+ filters:
115
+ - sql: "YEAR({CUBE}.created_at) = YEAR(CURRENT_DATE)"
116
+ ```
117
+
118
+ ## Calculated Measures
119
+
120
+ Reference other measures to build derived metrics:
121
+
122
+ ```yaml
123
+ - name: total_orders
124
+ type: count
125
+
126
+ - name: completed_orders
127
+ type: count
128
+ filters:
129
+ - sql: "{CUBE}.status = 'completed'"
130
+
131
+ - name: completion_rate
132
+ type: number
133
+ sql: "100.0 * {completed_orders} / NULLIF({total_orders}, 0)"
134
+ format: percent
135
+ ```
136
+
137
+ ## Rolling Windows
138
+
139
+ Calculate metrics over time windows:
140
+
141
+ ```yaml
142
+ - name: rolling_7_day_revenue
143
+ type: sum
144
+ sql: amount
145
+ rolling_window:
146
+ trailing: 7 day
147
+ ```
148
+
149
+ ## Best Practices
150
+
151
+ 1. **Start with count** — every cube should have a basic count
152
+ 2. **Use descriptive names** — `total_revenue` not `sum1`
153
+ 3. **Handle division by zero** — always use `NULLIF(x, 0)`
154
+ 4. **Add formats** — help consumers interpret values
155
+ 5. **Document complex measures** — explain business logic
156
+
157
+ ## See Also
158
+
159
+ - cubes.measures.types
160
+ - cubes.measures.filters
161
+ - cubes.measures.calculated
162
+ - cubes.measures.rolling
@@ -0,0 +1,119 @@
1
+ # cubes.measures.rolling
2
+
3
+ > Calculate rolling window aggregations (7-day average, 30-day sum, etc).
4
+
5
+ ## Overview
6
+
7
+ Rolling window measures aggregate data over a sliding time period. Use `rolling_window` to define moving averages, cumulative totals, and time-based comparisons.
8
+
9
+ ## Example
10
+
11
+ ```yaml
12
+ measures:
13
+ - name: rolling_7_day_orders
14
+ type: count
15
+ rolling_window:
16
+ trailing: 7 day
17
+ offset: start
18
+
19
+ - name: rolling_30_day_revenue
20
+ type: sum
21
+ sql: amount
22
+ rolling_window:
23
+ trailing: 30 day
24
+ ```
25
+
26
+ ## Syntax
27
+
28
+ ### rolling_window Properties
29
+
30
+ | Property | Description |
31
+ |----------|-------------|
32
+ | `trailing` | Time period to look back (e.g., `7 day`, `1 month`) |
33
+ | `leading` | Time period to look forward (rare) |
34
+ | `offset` | `start` or `end` — which end of the window to align |
35
+
36
+ ### Trailing Window
37
+
38
+ ```yaml
39
+ - name: rolling_7_day_avg
40
+ type: avg
41
+ sql: amount
42
+ rolling_window:
43
+ trailing: 7 day
44
+ ```
45
+
46
+ ### Cumulative (Running Total)
47
+
48
+ Use `unbounded` for cumulative calculations:
49
+
50
+ ```yaml
51
+ - name: cumulative_revenue
52
+ type: sum
53
+ sql: amount
54
+ rolling_window:
55
+ trailing: unbounded
56
+ ```
57
+
58
+ ### Offset Options
59
+
60
+ ```yaml
61
+ # Window ends at current row (default)
62
+ rolling_window:
63
+ trailing: 7 day
64
+ offset: end
65
+
66
+ # Window starts at current row
67
+ rolling_window:
68
+ trailing: 7 day
69
+ offset: start
70
+ ```
71
+
72
+ ## Common Patterns
73
+
74
+ ### 7-Day Moving Average
75
+
76
+ ```yaml
77
+ - name: daily_orders
78
+ type: count
79
+
80
+ - name: rolling_7_day_avg_orders
81
+ type: avg
82
+ sql: "{daily_orders}"
83
+ rolling_window:
84
+ trailing: 7 day
85
+ ```
86
+
87
+ ### Month-to-Date
88
+
89
+ ```yaml
90
+ - name: mtd_revenue
91
+ type: sum
92
+ sql: amount
93
+ rolling_window:
94
+ trailing: 1 month
95
+ offset: start
96
+ ```
97
+
98
+ ### Year-to-Date
99
+
100
+ ```yaml
101
+ - name: ytd_revenue
102
+ type: sum
103
+ sql: amount
104
+ rolling_window:
105
+ trailing: 1 year
106
+ offset: start
107
+ ```
108
+
109
+ ## Requirements
110
+
111
+ - Rolling window measures require a time dimension in the query
112
+ - Works best with pre-aggregations for performance
113
+
114
+ ## See Also
115
+
116
+ - cubes.measures
117
+ - cubes.measures.calculated
118
+ - cubes.dimensions.time
119
+ - pre-aggregations