@bonnard/cli 0.1.2 → 0.1.4

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 (49) hide show
  1. package/dist/bin/bon.mjs +1892 -97
  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 +82 -0
  5. package/dist/docs/_index.md +69 -0
  6. package/dist/docs/topics/cubes.data-source.md +96 -0
  7. package/dist/docs/topics/cubes.dimensions.format.md +199 -0
  8. package/dist/docs/topics/cubes.dimensions.md +188 -0
  9. package/dist/docs/topics/cubes.dimensions.primary-key.md +110 -0
  10. package/dist/docs/topics/cubes.dimensions.sub-query.md +178 -0
  11. package/dist/docs/topics/cubes.dimensions.time.md +115 -0
  12. package/dist/docs/topics/cubes.dimensions.types.md +111 -0
  13. package/dist/docs/topics/cubes.extends.md +153 -0
  14. package/dist/docs/topics/cubes.hierarchies.md +178 -0
  15. package/dist/docs/topics/cubes.joins.md +119 -0
  16. package/dist/docs/topics/cubes.md +121 -0
  17. package/dist/docs/topics/cubes.measures.calculated.md +103 -0
  18. package/dist/docs/topics/cubes.measures.drill-members.md +162 -0
  19. package/dist/docs/topics/cubes.measures.filters.md +90 -0
  20. package/dist/docs/topics/cubes.measures.format.md +157 -0
  21. package/dist/docs/topics/cubes.measures.md +166 -0
  22. package/dist/docs/topics/cubes.measures.rolling.md +123 -0
  23. package/dist/docs/topics/cubes.measures.types.md +126 -0
  24. package/dist/docs/topics/cubes.public.md +176 -0
  25. package/dist/docs/topics/cubes.refresh-key.md +157 -0
  26. package/dist/docs/topics/cubes.segments.md +125 -0
  27. package/dist/docs/topics/cubes.sql.md +65 -0
  28. package/dist/docs/topics/pre-aggregations.md +130 -0
  29. package/dist/docs/topics/pre-aggregations.rollup.md +166 -0
  30. package/dist/docs/topics/syntax.context-variables.md +157 -0
  31. package/dist/docs/topics/syntax.md +137 -0
  32. package/dist/docs/topics/syntax.references.md +178 -0
  33. package/dist/docs/topics/views.cubes.md +166 -0
  34. package/dist/docs/topics/views.folders.md +158 -0
  35. package/dist/docs/topics/views.includes.md +143 -0
  36. package/dist/docs/topics/views.md +142 -0
  37. package/dist/docs/topics/workflow.deploy.md +132 -0
  38. package/dist/docs/topics/workflow.md +151 -0
  39. package/dist/docs/topics/workflow.query.md +203 -0
  40. package/dist/docs/topics/workflow.validate.md +156 -0
  41. package/dist/templates/claude/rules/bonnard.md +15 -0
  42. package/dist/templates/claude/settings.json +7 -0
  43. package/dist/templates/claude/skills/bonnard-cli/SKILL.md +59 -0
  44. package/dist/templates/claude/skills/bonnard-queries/SKILL.md +68 -0
  45. package/dist/templates/cursor/rules/bonnard-cli.mdc +47 -0
  46. package/dist/templates/cursor/rules/bonnard-queries.mdc +49 -0
  47. package/dist/templates/cursor/rules/bonnard.mdc +20 -0
  48. package/dist/templates/shared/bonnard.md +81 -0
  49. package/package.json +8 -3
@@ -0,0 +1,188 @@
1
+ # cubes.dimensions
2
+
3
+ > Define attributes for grouping and filtering data.
4
+
5
+ ## Overview
6
+
7
+ Dimensions are the attributes used to slice and filter your data. They answer questions like "by what?", "which ones?", and "when?". Dimensions enable grouping measures and applying filters.
8
+
9
+ ## Example
10
+
11
+ ```yaml
12
+ dimensions:
13
+ - name: id
14
+ type: number
15
+ sql: id
16
+ primary_key: true
17
+ description: Unique order identifier
18
+
19
+ - name: status
20
+ type: string
21
+ sql: status
22
+ description: Order status (pending, completed, cancelled)
23
+
24
+ - name: amount
25
+ type: number
26
+ sql: amount
27
+ description: Order amount in dollars
28
+
29
+ - name: is_active
30
+ type: boolean
31
+ sql: is_active
32
+ description: Whether the order is currently active
33
+
34
+ - name: created_at
35
+ type: time
36
+ sql: created_at
37
+ description: When the order was created
38
+ ```
39
+
40
+ ## Required Properties
41
+
42
+ | Property | Description |
43
+ |----------|-------------|
44
+ | `name` | Unique identifier in snake_case |
45
+ | `type` | Data type (string, number, time, etc.) |
46
+ | `sql` | SQL expression for the value |
47
+
48
+ ## Optional Properties
49
+
50
+ | Property | Description |
51
+ |----------|-------------|
52
+ | `primary_key` | Marks as unique identifier (required for joins) |
53
+ | `title` | Human-readable display name |
54
+ | `description` | Documentation for consumers |
55
+ | `format` | Output format hints |
56
+ | `public` | Whether exposed in API (default: true) |
57
+
58
+ ## Dimension Types
59
+
60
+ ### string
61
+
62
+ Text values for categorization:
63
+
64
+ ```yaml
65
+ - name: status
66
+ type: string
67
+ sql: status
68
+
69
+ - name: full_name
70
+ type: string
71
+ sql: "CONCAT(first_name, ' ', last_name)"
72
+ ```
73
+
74
+ ### number
75
+
76
+ Numeric values (not aggregated):
77
+
78
+ ```yaml
79
+ - name: quantity
80
+ type: number
81
+ sql: quantity
82
+
83
+ - name: unit_price
84
+ type: number
85
+ sql: price
86
+ ```
87
+
88
+ ### boolean
89
+
90
+ True/false values:
91
+
92
+ ```yaml
93
+ - name: is_active
94
+ type: boolean
95
+ sql: is_active
96
+
97
+ - name: has_subscription
98
+ type: boolean
99
+ sql: "subscription_id IS NOT NULL"
100
+ ```
101
+
102
+ ### time
103
+
104
+ Dates and timestamps (enables time-based analysis):
105
+
106
+ ```yaml
107
+ - name: created_at
108
+ type: time
109
+ sql: created_at
110
+
111
+ - name: order_date
112
+ type: time
113
+ sql: DATE(ordered_at)
114
+ ```
115
+
116
+ ### geo
117
+
118
+ Geographic coordinates:
119
+
120
+ ```yaml
121
+ - name: location
122
+ type: geo
123
+ latitude:
124
+ sql: lat
125
+ longitude:
126
+ sql: lng
127
+ ```
128
+
129
+ ### switch
130
+
131
+ Enumerated values with labels:
132
+
133
+ ```yaml
134
+ - name: status_label
135
+ type: switch
136
+ case:
137
+ when:
138
+ - sql: "{CUBE}.status = 'active'"
139
+ label: Active
140
+ - sql: "{CUBE}.status = 'inactive'"
141
+ label: Inactive
142
+ else:
143
+ label: Unknown
144
+ ```
145
+
146
+ ## Primary Key
147
+
148
+ Mark the unique identifier — required for joins and count_distinct:
149
+
150
+ ```yaml
151
+ - name: id
152
+ type: number
153
+ sql: id
154
+ primary_key: true
155
+ ```
156
+
157
+ ## Calculated Dimensions
158
+
159
+ Create derived attributes:
160
+
161
+ ```yaml
162
+ - name: order_size
163
+ type: string
164
+ sql: >
165
+ CASE
166
+ WHEN {CUBE}.amount > 1000 THEN 'large'
167
+ WHEN {CUBE}.amount > 100 THEN 'medium'
168
+ ELSE 'small'
169
+ END
170
+ ```
171
+
172
+ ## Best Practices
173
+
174
+ 1. **Always define a primary key** — enables joins and count_distinct
175
+ 2. **Use appropriate types** — time for dates, string for categories
176
+ 3. **Name clearly** — `customer_email` not `email1`
177
+ 4. **Document business logic** — explain calculated dimensions
178
+
179
+ ## See Also
180
+
181
+ - cubes.dimensions.types
182
+ - cubes.dimensions.primary-key
183
+ - cubes.dimensions.time
184
+ - cubes.joins
185
+
186
+ ## More Information
187
+
188
+ https://cube.dev/docs/reference/data-model/dimensions
@@ -0,0 +1,110 @@
1
+ # cubes.dimensions.primary-key
2
+
3
+ > Mark the unique identifier dimension for a cube.
4
+
5
+ ## Overview
6
+
7
+ The `primary_key` property identifies the dimension that uniquely identifies each row. This is required for `count_distinct` measures and joins to work correctly.
8
+
9
+ ## Example
10
+
11
+ ```yaml
12
+ cubes:
13
+ - name: users
14
+ sql: SELECT * FROM users
15
+
16
+ dimensions:
17
+ - name: id
18
+ type: number
19
+ sql: id
20
+ primary_key: true
21
+
22
+ - name: email
23
+ type: string
24
+ sql: email
25
+ ```
26
+
27
+ ## Why It Matters
28
+
29
+ ### Enables count_distinct
30
+
31
+ Without a primary key, count_distinct may produce incorrect results:
32
+
33
+ ```yaml
34
+ measures:
35
+ - name: unique_users
36
+ type: count_distinct
37
+ sql: "{users.id}" # Requires primary_key on users.id
38
+ ```
39
+
40
+ ### Required for Joins
41
+
42
+ Cube uses primary keys to correctly join data:
43
+
44
+ ```yaml
45
+ cubes:
46
+ - name: orders
47
+ sql: SELECT * FROM orders
48
+
49
+ dimensions:
50
+ - name: id
51
+ type: number
52
+ sql: id
53
+ primary_key: true
54
+
55
+ joins:
56
+ - name: users
57
+ relationship: many_to_one
58
+ sql: "{CUBE}.user_id = {users.id}"
59
+ ```
60
+
61
+ ### Affects Pre-aggregations
62
+
63
+ Primary keys determine how pre-aggregations handle duplicates.
64
+
65
+ ## Rules
66
+
67
+ 1. **At least one per cube** — required for joins and count_distinct to work
68
+ 2. **Composite keys supported** — multiple dimensions can be marked as primary key
69
+ 3. **Must be unique** — the combination of primary key values should not repeat
70
+ 4. **Usually numeric** — but can be string (UUID, etc.)
71
+ 5. **Auto-hides from API** — primary key dimensions default to `public: false`
72
+
73
+ ## Common Patterns
74
+
75
+ ### Auto-increment ID
76
+
77
+ ```yaml
78
+ - name: id
79
+ type: number
80
+ sql: id
81
+ primary_key: true
82
+ ```
83
+
84
+ ### UUID
85
+
86
+ ```yaml
87
+ - name: id
88
+ type: string
89
+ sql: id
90
+ primary_key: true
91
+ ```
92
+
93
+ ### Composite Key (use concat)
94
+
95
+ ```yaml
96
+ - name: composite_id
97
+ type: string
98
+ sql: "CONCAT(order_id, '-', line_item_id)"
99
+ primary_key: true
100
+ ```
101
+
102
+ ## See Also
103
+
104
+ - cubes.dimensions
105
+ - cubes.dimensions.types
106
+ - cubes.joins
107
+
108
+ ## More Information
109
+
110
+ https://cube.dev/docs/reference/data-model/dimensions#primary-key
@@ -0,0 +1,178 @@
1
+ # cubes.dimensions.sub-query
2
+
3
+ > Bring measures from other cubes into a dimension.
4
+
5
+ ## Overview
6
+
7
+ Subquery dimensions allow you to reference measures from joined cubes as dimension values. This enables nested aggregations and bringing aggregate values into row-level context.
8
+
9
+ ## Example
10
+
11
+ ```yaml
12
+ cubes:
13
+ - name: users
14
+ sql_table: users
15
+
16
+ dimensions:
17
+ - name: id
18
+ type: number
19
+ sql: id
20
+ primary_key: true
21
+
22
+ - name: name
23
+ type: string
24
+ sql: name
25
+
26
+ # Subquery dimension - brings order count as a user attribute
27
+ - name: order_count
28
+ type: number
29
+ sql: "{orders.count}"
30
+ sub_query: true
31
+
32
+ joins:
33
+ - name: orders
34
+ relationship: one_to_many
35
+ sql: "{CUBE}.id = {orders.user_id}"
36
+
37
+ - name: orders
38
+ sql_table: orders
39
+
40
+ measures:
41
+ - name: count
42
+ type: count
43
+
44
+ dimensions:
45
+ - name: id
46
+ type: number
47
+ sql: id
48
+ primary_key: true
49
+
50
+ - name: user_id
51
+ type: number
52
+ sql: user_id
53
+ ```
54
+
55
+ ## Properties
56
+
57
+ | Property | Description |
58
+ |----------|-------------|
59
+ | `sub_query: true` | Enables measure reference in dimension |
60
+ | `propagate_filters_to_sub_query` | Pass query filters to the subquery |
61
+
62
+ ## Syntax
63
+
64
+ ### Basic Subquery Dimension
65
+
66
+ ```yaml
67
+ dimensions:
68
+ - name: total_orders
69
+ type: number
70
+ sql: "{orders.count}"
71
+ sub_query: true
72
+ ```
73
+
74
+ ### With Filter Propagation
75
+
76
+ ```yaml
77
+ dimensions:
78
+ - name: recent_order_count
79
+ type: number
80
+ sql: "{orders.count}"
81
+ sub_query: true
82
+ propagate_filters_to_sub_query: true
83
+ ```
84
+
85
+ When `propagate_filters_to_sub_query: true`, filters applied in the main query also apply to the subquery aggregation.
86
+
87
+ ## How It Works
88
+
89
+ Cube generates an optimized LEFT JOIN with an aggregation subquery:
90
+
91
+ ```sql
92
+ SELECT
93
+ users.id,
94
+ users.name,
95
+ orders_subquery.count AS order_count
96
+ FROM users
97
+ LEFT JOIN (
98
+ SELECT user_id, COUNT(*) as count
99
+ FROM orders
100
+ GROUP BY user_id
101
+ ) AS orders_subquery ON users.id = orders_subquery.user_id
102
+ ```
103
+
104
+ ## Use Cases
105
+
106
+ ### User Metrics
107
+
108
+ ```yaml
109
+ # On users cube
110
+ dimensions:
111
+ - name: lifetime_order_count
112
+ type: number
113
+ sql: "{orders.count}"
114
+ sub_query: true
115
+
116
+ - name: lifetime_revenue
117
+ type: number
118
+ sql: "{orders.total_revenue}"
119
+ sub_query: true
120
+ ```
121
+
122
+ ### Product Statistics
123
+
124
+ ```yaml
125
+ # On products cube
126
+ dimensions:
127
+ - name: times_purchased
128
+ type: number
129
+ sql: "{order_items.count}"
130
+ sub_query: true
131
+
132
+ - name: total_quantity_sold
133
+ type: number
134
+ sql: "{order_items.total_quantity}"
135
+ sub_query: true
136
+ ```
137
+
138
+ ### Categorization Based on Aggregates
139
+
140
+ ```yaml
141
+ dimensions:
142
+ - name: order_count
143
+ type: number
144
+ sql: "{orders.count}"
145
+ sub_query: true
146
+
147
+ - name: customer_tier
148
+ type: string
149
+ sql: >
150
+ CASE
151
+ WHEN {order_count} >= 100 THEN 'platinum'
152
+ WHEN {order_count} >= 50 THEN 'gold'
153
+ WHEN {order_count} >= 10 THEN 'silver'
154
+ ELSE 'bronze'
155
+ END
156
+ ```
157
+
158
+ ## Requirements
159
+
160
+ 1. **Join must exist** between the cubes
161
+ 2. **Measure must exist** in the joined cube
162
+ 3. **Primary key required** on both cubes
163
+
164
+ ## Best Practices
165
+
166
+ 1. **Use for commonly needed aggregates** — avoid creating subquery dimensions for rarely used metrics
167
+ 2. **Consider performance** — subqueries add complexity to generated SQL
168
+ 3. **Document the relationship** — make it clear where the data comes from
169
+
170
+ ## See Also
171
+
172
+ - cubes.dimensions
173
+ - cubes.joins
174
+ - cubes.measures
175
+
176
+ ## More Information
177
+
178
+ https://cube.dev/docs/product/data-modeling/concepts/calculated-members#subquery-dimensions
@@ -0,0 +1,115 @@
1
+ # cubes.dimensions.time
2
+
3
+ > Enable time-based analysis with time dimensions.
4
+
5
+ ## Overview
6
+
7
+ Time dimensions (`type: time`) enable powerful time-based analysis including granularity selection, date ranges, and rolling windows. They're essential for any time-series analytics.
8
+
9
+ ## Example
10
+
11
+ ```yaml
12
+ dimensions:
13
+ - name: created_at
14
+ type: time
15
+ sql: created_at
16
+
17
+ - name: order_date
18
+ type: time
19
+ sql: DATE(ordered_at)
20
+ ```
21
+
22
+ ## Time Granularities
23
+
24
+ When querying a time dimension, you can specify granularity:
25
+
26
+ | Granularity | Description |
27
+ |-------------|-------------|
28
+ | `second` | Group by second |
29
+ | `minute` | Group by minute |
30
+ | `hour` | Group by hour |
31
+ | `day` | Group by day |
32
+ | `week` | Group by week (Monday start) |
33
+ | `month` | Group by month |
34
+ | `quarter` | Group by quarter |
35
+ | `year` | Group by year |
36
+
37
+ ## Query Usage
38
+
39
+ Time dimensions can be used in `timeDimensions` for special handling:
40
+
41
+ ```json
42
+ {
43
+ "measures": ["orders.count"],
44
+ "timeDimensions": [{
45
+ "dimension": "orders.created_at",
46
+ "granularity": "month",
47
+ "dateRange": ["2024-01-01", "2024-12-31"]
48
+ }]
49
+ }
50
+ ```
51
+
52
+ ## Date Ranges
53
+
54
+ Common date range options:
55
+
56
+ - `"today"`, `"yesterday"`
57
+ - `"this week"`, `"last week"`
58
+ - `"this month"`, `"last month"`
59
+ - `"this year"`, `"last year"`
60
+ - `"last 7 days"`, `"last 30 days"`
61
+ - `["2024-01-01", "2024-12-31"]` (custom range)
62
+
63
+ ## Best Practices
64
+
65
+ ### Use Native Timestamps
66
+
67
+ ```yaml
68
+ # Good - preserves precision
69
+ - name: created_at
70
+ type: time
71
+ sql: created_at
72
+
73
+ # Avoid - loses time component
74
+ - name: created_at
75
+ type: time
76
+ sql: DATE(created_at)
77
+ ```
78
+
79
+ ### Multiple Time Dimensions
80
+
81
+ A cube can have multiple time dimensions for different purposes:
82
+
83
+ ```yaml
84
+ - name: created_at
85
+ type: time
86
+ sql: created_at
87
+
88
+ - name: shipped_at
89
+ type: time
90
+ sql: shipped_at
91
+
92
+ - name: delivered_at
93
+ type: time
94
+ sql: delivered_at
95
+ ```
96
+
97
+ ### Timezone Handling
98
+
99
+ For consistent timezone handling, convert in SQL:
100
+
101
+ ```yaml
102
+ - name: created_at
103
+ type: time
104
+ sql: "CONVERT_TIMEZONE('UTC', 'America/New_York', created_at)"
105
+ ```
106
+
107
+ ## See Also
108
+
109
+ - cubes.dimensions
110
+ - cubes.dimensions.types
111
+ - cubes.measures.rolling
112
+
113
+ ## More Information
114
+
115
+ https://cube.dev/docs/reference/data-model/dimensions#time-dimensions
@@ -0,0 +1,111 @@
1
+ # cubes.dimensions.types
2
+
3
+ > The 6 dimension types for categorizing and filtering data.
4
+
5
+ ## Overview
6
+
7
+ Dimensions define the attributes used to group and filter data. Choose the appropriate type based on the data characteristics.
8
+
9
+ ## Dimension Types
10
+
11
+ ### string
12
+ Text values for categorization.
13
+
14
+ ```yaml
15
+ - name: status
16
+ type: string
17
+ sql: status
18
+
19
+ - name: full_name
20
+ type: string
21
+ sql: "CONCAT(first_name, ' ', last_name)"
22
+ ```
23
+
24
+ ### number
25
+ Numeric values (not aggregated).
26
+
27
+ ```yaml
28
+ - name: quantity
29
+ type: number
30
+ sql: quantity
31
+
32
+ - name: price
33
+ type: number
34
+ sql: unit_price
35
+ ```
36
+
37
+ ### boolean
38
+ True/false values.
39
+
40
+ ```yaml
41
+ - name: is_active
42
+ type: boolean
43
+ sql: is_active
44
+
45
+ - name: has_orders
46
+ type: boolean
47
+ sql: "order_count > 0"
48
+ ```
49
+
50
+ ### time
51
+ Date and timestamp values (enables time-based analysis).
52
+
53
+ ```yaml
54
+ - name: created_at
55
+ type: time
56
+ sql: created_at
57
+
58
+ - name: order_date
59
+ type: time
60
+ sql: DATE(ordered_at)
61
+ ```
62
+
63
+ ### geo
64
+ Geographic coordinates (latitude/longitude).
65
+
66
+ ```yaml
67
+ - name: location
68
+ type: geo
69
+ latitude:
70
+ sql: lat
71
+ longitude:
72
+ sql: lng
73
+ ```
74
+
75
+ ### switch
76
+ Dimension with predefined set of values.
77
+
78
+ ```yaml
79
+ - name: status_label
80
+ type: switch
81
+ sql: status
82
+ case:
83
+ when:
84
+ - sql: "{CUBE}.status = 'active'"
85
+ label: Active
86
+ - sql: "{CUBE}.status = 'inactive'"
87
+ label: Inactive
88
+ else:
89
+ label: Unknown
90
+ ```
91
+
92
+ ## Type Selection Guide
93
+
94
+ | Data | Type | Example |
95
+ |------|------|---------|
96
+ | Categories, names, IDs | `string` | status, country, user_id |
97
+ | Prices, quantities | `number` | price, quantity, score |
98
+ | Flags, toggles | `boolean` | is_active, has_subscription |
99
+ | Dates, timestamps | `time` | created_at, order_date |
100
+ | Coordinates | `geo` | location, delivery_point |
101
+ | Enumerated values | `switch` | status_label, tier_name |
102
+
103
+ ## See Also
104
+
105
+ - cubes.dimensions
106
+ - cubes.dimensions.primary-key
107
+ - cubes.dimensions.time
108
+
109
+ ## More Information
110
+
111
+ https://cube.dev/docs/reference/data-model/types-and-formats#dimension-types