@duckcodeailabs/dql-cli 0.1.1 → 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 (55) hide show
  1. package/dist/assets/notebook-browser/app.js +548 -0
  2. package/dist/assets/notebook-browser/index.html +83 -0
  3. package/dist/assets/notebook-browser/styles.css +336 -0
  4. package/dist/assets/templates/ecommerce/README.md +27 -0
  5. package/dist/assets/templates/ecommerce/blocks/repeat_rate.dql +26 -0
  6. package/dist/assets/templates/ecommerce/blocks/revenue_by_segment.dql +24 -0
  7. package/dist/assets/templates/ecommerce/dashboards/revenue_command_center.dql +25 -0
  8. package/dist/assets/templates/ecommerce/data/customers.csv +11 -0
  9. package/dist/assets/templates/ecommerce/data/funnel.csv +6 -0
  10. package/dist/assets/templates/ecommerce/data/orders.csv +16 -0
  11. package/dist/assets/templates/ecommerce/dql.config.json +13 -0
  12. package/dist/assets/templates/ecommerce/semantic-layer/dimensions/channel.yaml +4 -0
  13. package/dist/assets/templates/ecommerce/semantic-layer/metrics/gmv.yaml +4 -0
  14. package/dist/assets/templates/ecommerce/workbooks/.gitkeep +1 -0
  15. package/dist/assets/templates/saas/README.md +20 -0
  16. package/dist/assets/templates/saas/blocks/churn_pressure.dql +25 -0
  17. package/dist/assets/templates/saas/blocks/revenue_by_segment.dql +25 -0
  18. package/dist/assets/templates/saas/dashboards/growth_scorecard.dql +25 -0
  19. package/dist/assets/templates/saas/data/cohorts.csv +7 -0
  20. package/dist/assets/templates/saas/data/subscriptions.csv +13 -0
  21. package/dist/assets/templates/saas/dql.config.json +13 -0
  22. package/dist/assets/templates/saas/semantic-layer/metrics/mrr.yaml +4 -0
  23. package/dist/assets/templates/saas/workbooks/.gitkeep +1 -0
  24. package/dist/assets/templates/starter/README.md +54 -0
  25. package/dist/assets/templates/starter/blocks/revenue_by_segment.dql +29 -0
  26. package/dist/assets/templates/starter/blocks/revenue_trend_query_only.dql +20 -0
  27. package/dist/assets/templates/starter/dashboards/.gitkeep +1 -0
  28. package/dist/assets/templates/starter/data/revenue.csv +13 -0
  29. package/dist/assets/templates/starter/dql.config.json +13 -0
  30. package/dist/assets/templates/starter/semantic-layer/blocks/revenue_by_segment.yaml +11 -0
  31. package/dist/assets/templates/starter/semantic-layer/dimensions/segment_tier.yaml +6 -0
  32. package/dist/assets/templates/starter/semantic-layer/hierarchies/revenue_time.yaml +12 -0
  33. package/dist/assets/templates/starter/semantic-layer/metrics/revenue.yaml +7 -0
  34. package/dist/assets/templates/starter/workbooks/.gitkeep +1 -0
  35. package/dist/assets/templates/taxi/README.md +19 -0
  36. package/dist/assets/templates/taxi/blocks/airport_mix.dql +25 -0
  37. package/dist/assets/templates/taxi/blocks/revenue_by_segment.dql +24 -0
  38. package/dist/assets/templates/taxi/dashboards/city_operations.dql +25 -0
  39. package/dist/assets/templates/taxi/data/trips.csv +13 -0
  40. package/dist/assets/templates/taxi/dql.config.json +13 -0
  41. package/dist/assets/templates/taxi/semantic-layer/.gitkeep +1 -0
  42. package/dist/assets/templates/taxi/workbooks/.gitkeep +1 -0
  43. package/dist/commands/init.d.ts.map +1 -1
  44. package/dist/commands/init.js +3 -1
  45. package/dist/commands/init.js.map +1 -1
  46. package/dist/commands/notebook.d.ts.map +1 -1
  47. package/dist/commands/notebook.js +8 -2
  48. package/dist/commands/notebook.js.map +1 -1
  49. package/dist/local-runtime.d.ts +6 -0
  50. package/dist/local-runtime.d.ts.map +1 -1
  51. package/dist/local-runtime.js +65 -9
  52. package/dist/local-runtime.js.map +1 -1
  53. package/dist/local-runtime.test.js +24 -1
  54. package/dist/local-runtime.test.js.map +1 -1
  55. package/package.json +8 -8
@@ -0,0 +1,336 @@
1
+ :root {
2
+ color-scheme: dark;
3
+ --bg: #09111f;
4
+ --panel: #0f172a;
5
+ --panel-2: #111c31;
6
+ --border: #243248;
7
+ --text: #e5eefc;
8
+ --muted: #93a4bf;
9
+ --accent: #59c2ff;
10
+ --accent-2: #2563eb;
11
+ --danger: #ef4444;
12
+ --success: #22c55e;
13
+ }
14
+
15
+ * {
16
+ box-sizing: border-box;
17
+ }
18
+
19
+ body {
20
+ margin: 0;
21
+ font-family: Inter, system-ui, sans-serif;
22
+ background: radial-gradient(circle at top, #10203c, var(--bg) 48%);
23
+ color: var(--text);
24
+ }
25
+
26
+ button,
27
+ select,
28
+ input,
29
+ textarea {
30
+ font: inherit;
31
+ }
32
+
33
+ button {
34
+ border: 1px solid var(--border);
35
+ background: var(--panel-2);
36
+ color: var(--text);
37
+ border-radius: 10px;
38
+ padding: 0.6rem 0.9rem;
39
+ cursor: pointer;
40
+ }
41
+
42
+ button.primary {
43
+ background: linear-gradient(135deg, var(--accent), var(--accent-2));
44
+ color: #08111f;
45
+ border-color: transparent;
46
+ }
47
+
48
+ button.secondary {
49
+ background: transparent;
50
+ }
51
+
52
+ .app-shell {
53
+ display: grid;
54
+ grid-template-columns: 300px 1fr;
55
+ min-height: 100vh;
56
+ }
57
+
58
+ .sidebar {
59
+ border-right: 1px solid var(--border);
60
+ background: rgba(9, 17, 31, 0.88);
61
+ padding: 1.25rem;
62
+ position: sticky;
63
+ top: 0;
64
+ height: 100vh;
65
+ overflow: auto;
66
+ }
67
+
68
+ .brand {
69
+ display: flex;
70
+ gap: 0.9rem;
71
+ align-items: center;
72
+ margin-bottom: 1.5rem;
73
+ }
74
+
75
+ .brand p,
76
+ .subtitle,
77
+ .status,
78
+ .field-help,
79
+ .cell-status {
80
+ color: var(--muted);
81
+ }
82
+
83
+ .brand-mark {
84
+ width: 48px;
85
+ height: 48px;
86
+ border-radius: 14px;
87
+ background: linear-gradient(135deg, var(--accent), #8b5cf6);
88
+ color: #05111f;
89
+ display: grid;
90
+ place-items: center;
91
+ font-weight: 700;
92
+ }
93
+
94
+ .section-title {
95
+ font-size: 0.82rem;
96
+ text-transform: uppercase;
97
+ letter-spacing: 0.08em;
98
+ color: var(--muted);
99
+ margin: 1.25rem 0 0.75rem;
100
+ }
101
+
102
+ .panel,
103
+ .cell,
104
+ .chart-editor,
105
+ .table-shell {
106
+ background: rgba(17, 28, 49, 0.82);
107
+ border: 1px solid var(--border);
108
+ border-radius: 16px;
109
+ }
110
+
111
+ .panel {
112
+ padding: 0.85rem;
113
+ }
114
+
115
+ .panel.small {
116
+ margin-bottom: 0.8rem;
117
+ }
118
+
119
+ .main {
120
+ padding: 1.25rem 1.4rem 2rem;
121
+ }
122
+
123
+ .toolbar {
124
+ display: flex;
125
+ justify-content: space-between;
126
+ align-items: flex-start;
127
+ gap: 1rem;
128
+ margin-bottom: 1rem;
129
+ }
130
+
131
+ .toolbar h1 {
132
+ margin: 0 0 0.3rem;
133
+ }
134
+
135
+ .toolbar-actions,
136
+ .row-actions,
137
+ .cell-actions {
138
+ display: flex;
139
+ gap: 0.55rem;
140
+ flex-wrap: wrap;
141
+ }
142
+
143
+ .cells {
144
+ display: grid;
145
+ gap: 1rem;
146
+ }
147
+
148
+ .cell {
149
+ overflow: hidden;
150
+ }
151
+
152
+ .cell-header {
153
+ padding: 0.85rem 1rem;
154
+ border-bottom: 1px solid var(--border);
155
+ display: flex;
156
+ justify-content: space-between;
157
+ gap: 0.75rem;
158
+ align-items: center;
159
+ }
160
+
161
+ .cell-type {
162
+ display: inline-block;
163
+ min-width: 88px;
164
+ font-size: 0.76rem;
165
+ letter-spacing: 0.08em;
166
+ text-transform: uppercase;
167
+ color: var(--accent);
168
+ }
169
+
170
+ .cell-title,
171
+ select,
172
+ .field input {
173
+ width: 100%;
174
+ padding: 0.65rem 0.75rem;
175
+ border-radius: 10px;
176
+ border: 1px solid var(--border);
177
+ background: rgba(9, 17, 31, 0.8);
178
+ color: var(--text);
179
+ }
180
+
181
+ .cell-title {
182
+ margin-top: 0.35rem;
183
+ }
184
+
185
+ .cell-body {
186
+ padding: 1rem;
187
+ }
188
+
189
+ .cell-source {
190
+ width: 100%;
191
+ min-height: 200px;
192
+ padding: 0.85rem;
193
+ border-radius: 12px;
194
+ border: 1px solid var(--border);
195
+ background: #07101d;
196
+ color: var(--text);
197
+ resize: vertical;
198
+ }
199
+
200
+ .cell-output {
201
+ margin-top: 1rem;
202
+ }
203
+
204
+ .file-list {
205
+ list-style: none;
206
+ padding: 0;
207
+ margin: 0;
208
+ }
209
+
210
+ .file-list li {
211
+ padding: 0.42rem 0;
212
+ color: var(--muted);
213
+ border-bottom: 1px solid rgba(36, 50, 72, 0.35);
214
+ }
215
+
216
+ .field {
217
+ margin-top: 0.75rem;
218
+ }
219
+
220
+ .field-label {
221
+ display: block;
222
+ margin-top: 0.6rem;
223
+ margin-bottom: 0.35rem;
224
+ color: var(--muted);
225
+ }
226
+
227
+ .checkbox {
228
+ display: flex;
229
+ align-items: center;
230
+ gap: 0.5rem;
231
+ }
232
+
233
+ .chart-editor {
234
+ display: grid;
235
+ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
236
+ gap: 0.75rem;
237
+ padding: 0.9rem;
238
+ margin-bottom: 1rem;
239
+ }
240
+
241
+ .chart-card {
242
+ padding: 1rem;
243
+ background: linear-gradient(180deg, rgba(12, 21, 37, 0.98), rgba(17, 28, 49, 0.9));
244
+ border-radius: 14px;
245
+ border: 1px solid var(--border);
246
+ }
247
+
248
+ .kpi-value {
249
+ font-size: 2rem;
250
+ font-weight: 700;
251
+ margin-top: 0.5rem;
252
+ }
253
+
254
+ .bar-row {
255
+ display: grid;
256
+ grid-template-columns: 140px 1fr 90px;
257
+ gap: 0.75rem;
258
+ align-items: center;
259
+ margin-bottom: 0.5rem;
260
+ }
261
+
262
+ .bar-track {
263
+ height: 12px;
264
+ background: rgba(255, 255, 255, 0.06);
265
+ border-radius: 999px;
266
+ overflow: hidden;
267
+ }
268
+
269
+ .bar-fill {
270
+ height: 100%;
271
+ background: linear-gradient(90deg, var(--accent), #8b5cf6);
272
+ }
273
+
274
+ .table-shell {
275
+ overflow: auto;
276
+ }
277
+
278
+ table {
279
+ width: 100%;
280
+ border-collapse: collapse;
281
+ }
282
+
283
+ th,
284
+ td {
285
+ text-align: left;
286
+ padding: 0.7rem 0.85rem;
287
+ border-bottom: 1px solid rgba(36, 50, 72, 0.6);
288
+ }
289
+
290
+ th {
291
+ color: var(--muted);
292
+ font-size: 0.85rem;
293
+ }
294
+
295
+ .markdown-preview {
296
+ padding: 1rem;
297
+ border: 1px solid var(--border);
298
+ border-radius: 12px;
299
+ background: rgba(7, 16, 29, 0.7);
300
+ line-height: 1.6;
301
+ }
302
+
303
+ .markdown-preview h1,
304
+ .markdown-preview h2,
305
+ .markdown-preview h3 {
306
+ margin-top: 0;
307
+ }
308
+
309
+ .status.ok {
310
+ color: var(--success);
311
+ }
312
+
313
+ .status.error {
314
+ color: var(--danger);
315
+ }
316
+
317
+ .hidden {
318
+ display: none;
319
+ }
320
+
321
+ @media (max-width: 1100px) {
322
+ .app-shell {
323
+ grid-template-columns: 1fr;
324
+ }
325
+
326
+ .sidebar {
327
+ position: static;
328
+ height: auto;
329
+ border-right: 0;
330
+ border-bottom: 1px solid var(--border);
331
+ }
332
+
333
+ .toolbar {
334
+ flex-direction: column;
335
+ }
336
+ }
@@ -0,0 +1,27 @@
1
+ # __PROJECT_NAME__
2
+
3
+ This template packages a realistic e-commerce analytics sandbox for DQL.
4
+
5
+ ## Included assets
6
+
7
+ - `blocks/revenue_by_segment.dql` — channel revenue block
8
+ - `blocks/repeat_rate.dql` — repeat purchase mix block
9
+ - `dashboards/revenue_command_center.dql` — KPI + bar + table dashboard
10
+ - `data/orders.csv` — orders with channel, region, and repeat purchase flags
11
+ - `data/funnel.csv` — acquisition and checkout funnel snapshot
12
+ - `data/customers.csv` — customer dimension data
13
+ - `notebooks/welcome.dqlnb` — browser notebook walkthrough
14
+
15
+ ## Quick start
16
+
17
+ ```bash
18
+ dql doctor
19
+ dql notebook
20
+ dql preview blocks/revenue_by_segment.dql --open
21
+ ```
22
+
23
+ ## What to explore
24
+
25
+ - Compare performance across paid, partner, organic, and lifecycle channels
26
+ - Track repeat order contribution by region and segment
27
+ - Use the notebook to iterate on funnel SQL before promoting it into reusable blocks
@@ -0,0 +1,26 @@
1
+ block "Repeat Revenue Mix" {
2
+ domain = "commerce"
3
+ type = "custom"
4
+ description = "Repeat versus first-time order revenue mix"
5
+ tags = ["commerce", "retention"]
6
+ owner = "template"
7
+
8
+ query = """
9
+ SELECT
10
+ CASE WHEN is_repeat THEN 'Repeat' ELSE 'First Order' END AS order_type,
11
+ ROUND(SUM(order_total), 2) AS revenue
12
+ FROM read_csv_auto('./data/orders.csv')
13
+ GROUP BY order_type
14
+ ORDER BY revenue DESC
15
+ """
16
+
17
+ visualization {
18
+ chart = "bar"
19
+ x = order_type
20
+ y = revenue
21
+ }
22
+
23
+ tests {
24
+ assert row_count > 0
25
+ }
26
+ }
@@ -0,0 +1,24 @@
1
+ block "GMV by Channel" {
2
+ domain = "commerce"
3
+ type = "custom"
4
+ description = "Gross merchandise value by acquisition channel"
5
+ tags = ["commerce", "gmv", "channel"]
6
+ owner = "template"
7
+
8
+ query = """
9
+ SELECT channel, ROUND(SUM(order_total), 2) AS revenue
10
+ FROM read_csv_auto('./data/orders.csv')
11
+ GROUP BY channel
12
+ ORDER BY revenue DESC
13
+ """
14
+
15
+ visualization {
16
+ chart = "bar"
17
+ x = channel
18
+ y = revenue
19
+ }
20
+
21
+ tests {
22
+ assert row_count > 0
23
+ }
24
+ }
@@ -0,0 +1,25 @@
1
+ dashboard "Revenue Command Center" {
2
+ chart.kpi(
3
+ SELECT ROUND(SUM(order_total), 2) AS gmv
4
+ FROM read_csv_auto('./data/orders.csv'),
5
+ metrics = ["gmv"],
6
+ title = "Gross Merchandise Value"
7
+ )
8
+
9
+ chart.bar(
10
+ SELECT channel, ROUND(SUM(order_total), 2) AS revenue
11
+ FROM read_csv_auto('./data/orders.csv')
12
+ GROUP BY channel
13
+ ORDER BY revenue DESC,
14
+ x = channel,
15
+ y = revenue,
16
+ title = "Revenue by Channel"
17
+ )
18
+
19
+ chart.table(
20
+ SELECT order_date, customer_id, channel, region, order_total, is_repeat
21
+ FROM read_csv_auto('./data/orders.csv')
22
+ ORDER BY order_total DESC,
23
+ title = "Top Orders"
24
+ )
25
+ }
@@ -0,0 +1,11 @@
1
+ customer_id,customer_name,segment,region,acquisition_channel,first_order_date,health_score
2
+ C-001,Northstar Health,Enterprise,North America,Paid Search,2025-01-03,92
3
+ C-002,Blue Pine Retail,Mid-Market,EMEA,Organic Search,2024-11-19,87
4
+ C-003,Maple & Co,SMB,North America,Lifecycle,2024-12-01,79
5
+ C-004,Harbor Commerce,Enterprise,APAC,Partner,2025-01-11,90
6
+ C-005,Studio Relay,Mid-Market,North America,Paid Social,2025-01-14,74
7
+ C-006,Rio Goods,SMB,LATAM,Organic Search,2024-10-08,82
8
+ C-007,Vertex Home,Enterprise,North America,Partner,2024-09-22,95
9
+ C-008,Atlas Europe,Mid-Market,EMEA,Paid Search,2025-02-02,71
10
+ C-009,North Loop,SMB,North America,Organic Search,2025-02-06,77
11
+ C-010,Pacific Devices,Enterprise,APAC,Lifecycle,2024-08-12,88
@@ -0,0 +1,6 @@
1
+ step,users,conversion_rate,sort_order
2
+ Landing Session,18000,1.00,1
3
+ Product View,13420,0.75,2
4
+ Add to Cart,6280,0.35,3
5
+ Checkout Start,3125,0.17,4
6
+ Purchase,1543,0.09,5
@@ -0,0 +1,16 @@
1
+ order_id,order_date,customer_id,segment,channel,region,order_total,gross_margin,is_repeat,payment_method
2
+ 1001,2025-01-03,C-001,Enterprise,Paid Search,North America,12400,0.41,false,Card
3
+ 1002,2025-01-05,C-002,Mid-Market,Organic Search,EMEA,8600,0.37,true,Card
4
+ 1003,2025-01-08,C-003,SMB,Lifecycle,North America,2400,0.54,true,ACH
5
+ 1004,2025-01-11,C-004,Enterprise,Partner,APAC,15200,0.46,false,Wire
6
+ 1005,2025-01-14,C-005,Mid-Market,Paid Social,North America,5400,0.35,false,Card
7
+ 1006,2025-01-18,C-006,SMB,Organic Search,LATAM,1800,0.51,true,Card
8
+ 1007,2025-01-22,C-002,Mid-Market,Lifecycle,EMEA,9200,0.39,true,Card
9
+ 1008,2025-01-27,C-007,Enterprise,Partner,North America,17600,0.48,true,Wire
10
+ 1009,2025-02-02,C-008,Mid-Market,Paid Search,EMEA,7300,0.36,false,Card
11
+ 1010,2025-02-06,C-009,SMB,Organic Search,North America,2100,0.56,false,ACH
12
+ 1011,2025-02-10,C-010,Enterprise,Lifecycle,APAC,13800,0.43,true,Card
13
+ 1012,2025-02-15,C-011,Mid-Market,Partner,LATAM,6900,0.34,false,Wire
14
+ 1013,2025-02-18,C-012,Enterprise,Paid Social,North America,9800,0.38,false,Card
15
+ 1014,2025-02-21,C-007,Enterprise,Lifecycle,North America,12100,0.45,true,Wire
16
+ 1015,2025-02-25,C-013,SMB,Organic Search,EMEA,1700,0.53,true,Card
@@ -0,0 +1,13 @@
1
+ {
2
+ "project": "__PROJECT_NAME__",
3
+ "defaultConnection": {
4
+ "driver": "file",
5
+ "filepath": ":memory:"
6
+ },
7
+ "dataDir": "./data",
8
+ "preview": {
9
+ "port": 3474,
10
+ "open": true,
11
+ "theme": "dark"
12
+ }
13
+ }
@@ -0,0 +1,4 @@
1
+ name: channel
2
+ label: Channel
3
+ domain: commerce
4
+ description: Order acquisition channel.
@@ -0,0 +1,4 @@
1
+ name: gmv
2
+ label: Gross Merchandise Value
3
+ domain: commerce
4
+ description: Total order value across the commerce sample dataset.
@@ -0,0 +1,20 @@
1
+ # __PROJECT_NAME__
2
+
3
+ This template packages a SaaS KPI sandbox focused on MRR, retention, and expansion.
4
+
5
+ ## Included assets
6
+
7
+ - `blocks/revenue_by_segment.dql` — MRR by plan tier
8
+ - `blocks/churn_pressure.dql` — at-risk and churned revenue view
9
+ - `dashboards/growth_scorecard.dql` — executive SaaS KPI dashboard
10
+ - `data/subscriptions.csv` — recurring revenue and expansion sample data
11
+ - `data/cohorts.csv` — cohort retention snapshot
12
+ - `notebooks/welcome.dqlnb` — browser notebook walkthrough
13
+
14
+ ## Quick start
15
+
16
+ ```bash
17
+ dql doctor
18
+ dql notebook
19
+ dql preview blocks/revenue_by_segment.dql --open
20
+ ```
@@ -0,0 +1,25 @@
1
+ block "Churn Pressure by Segment" {
2
+ domain = "saas"
3
+ type = "custom"
4
+ description = "MRR currently flagged as at risk or churned"
5
+ tags = ["saas", "churn"]
6
+ owner = "template"
7
+
8
+ query = """
9
+ SELECT risk_bucket, ROUND(SUM(mrr), 2) AS at_risk_mrr
10
+ FROM read_csv_auto('./data/subscriptions.csv')
11
+ WHERE status != 'active' OR risk_bucket IN ('high', 'critical')
12
+ GROUP BY risk_bucket
13
+ ORDER BY at_risk_mrr DESC
14
+ """
15
+
16
+ visualization {
17
+ chart = "bar"
18
+ x = risk_bucket
19
+ y = at_risk_mrr
20
+ }
21
+
22
+ tests {
23
+ assert row_count > 0
24
+ }
25
+ }
@@ -0,0 +1,25 @@
1
+ block "MRR by Plan Tier" {
2
+ domain = "saas"
3
+ type = "custom"
4
+ description = "Monthly recurring revenue by plan tier"
5
+ tags = ["saas", "mrr"]
6
+ owner = "template"
7
+
8
+ query = """
9
+ SELECT plan_tier, ROUND(SUM(mrr), 2) AS revenue
10
+ FROM read_csv_auto('./data/subscriptions.csv')
11
+ WHERE status = 'active'
12
+ GROUP BY plan_tier
13
+ ORDER BY revenue DESC
14
+ """
15
+
16
+ visualization {
17
+ chart = "bar"
18
+ x = plan_tier
19
+ y = revenue
20
+ }
21
+
22
+ tests {
23
+ assert row_count > 0
24
+ }
25
+ }
@@ -0,0 +1,25 @@
1
+ dashboard "Growth Scorecard" {
2
+ chart.kpi(
3
+ SELECT ROUND(SUM(mrr), 2) AS active_mrr
4
+ FROM read_csv_auto('./data/subscriptions.csv')
5
+ WHERE status = 'active',
6
+ metrics = ["active_mrr"],
7
+ title = "Active MRR"
8
+ )
9
+
10
+ chart.line(
11
+ SELECT cohort_month, retained_accounts
12
+ FROM read_csv_auto('./data/cohorts.csv')
13
+ ORDER BY cohort_month,
14
+ x = cohort_month,
15
+ y = retained_accounts,
16
+ title = "Retained Accounts by Cohort"
17
+ )
18
+
19
+ chart.table(
20
+ SELECT account_name, owner_segment, plan_tier, status, mrr, expansion_mrr, risk_bucket
21
+ FROM read_csv_auto('./data/subscriptions.csv')
22
+ ORDER BY mrr DESC,
23
+ title = "Account Revenue Snapshot"
24
+ )
25
+ }
@@ -0,0 +1,7 @@
1
+ cohort_month,starting_accounts,retained_accounts,retention_rate
2
+ 2024-07,24,22,0.92
3
+ 2024-08,31,27,0.87
4
+ 2024-09,28,24,0.86
5
+ 2024-10,34,28,0.82
6
+ 2024-11,29,23,0.79
7
+ 2024-12,37,28,0.76
@@ -0,0 +1,13 @@
1
+ account_id,account_name,owner_segment,plan_tier,status,mrr,expansion_mrr,risk_bucket,renewal_month
2
+ A-100,Acme Cloud,Enterprise,Enterprise,active,48000,6200,low,2025-06
3
+ A-101,North Ridge,Mid-Market,Growth,active,18400,2400,medium,2025-05
4
+ A-102,Blue Orbit,SMB,Starter,active,3400,200,low,2025-04
5
+ A-103,Helio Systems,Enterprise,Enterprise,at_risk,52100,0,high,2025-03
6
+ A-104,Vector Health,Mid-Market,Growth,active,19600,1800,medium,2025-08
7
+ A-105,Studio Works,SMB,Starter,churned,2200,0,critical,2025-02
8
+ A-106,SignalWare,Enterprise,Enterprise,active,43500,4100,low,2025-07
9
+ A-107,Maple Commerce,Mid-Market,Growth,active,17100,1200,medium,2025-04
10
+ A-108,Linea Labs,SMB,Starter,active,2800,0,medium,2025-06
11
+ A-109,Quartz Energy,Enterprise,Enterprise,active,50300,7300,low,2025-09
12
+ A-110,Summit Bio,Mid-Market,Growth,at_risk,15800,0,high,2025-03
13
+ A-111,Glider Ops,SMB,Starter,active,2600,150,low,2025-05
@@ -0,0 +1,13 @@
1
+ {
2
+ "project": "__PROJECT_NAME__",
3
+ "defaultConnection": {
4
+ "driver": "file",
5
+ "filepath": ":memory:"
6
+ },
7
+ "dataDir": "./data",
8
+ "preview": {
9
+ "port": 3474,
10
+ "open": true,
11
+ "theme": "dark"
12
+ }
13
+ }
@@ -0,0 +1,4 @@
1
+ name: mrr
2
+ label: Monthly Recurring Revenue
3
+ domain: saas
4
+ description: Monthly recurring revenue across active subscriptions.