yamchart 0.3.1 → 0.3.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 (38) hide show
  1. package/dist/chunk-4P5UHWYK.js +247 -0
  2. package/dist/chunk-4P5UHWYK.js.map +1 -0
  3. package/dist/chunk-A24KVXJQ.js +922 -0
  4. package/dist/chunk-A24KVXJQ.js.map +1 -0
  5. package/dist/chunk-DGUM43GV.js +11 -0
  6. package/dist/chunk-DGUM43GV.js.map +1 -0
  7. package/dist/chunk-LL3VKMZM.js +1265 -0
  8. package/dist/chunk-LL3VKMZM.js.map +1 -0
  9. package/dist/dev-PTVNJI7G.js +13557 -0
  10. package/dist/dev-PTVNJI7G.js.map +1 -0
  11. package/dist/dist-JH7OL7U4.js +16 -0
  12. package/dist/dist-JH7OL7U4.js.map +1 -0
  13. package/dist/dist-JKJLH3F6.js +56 -0
  14. package/dist/dist-JKJLH3F6.js.map +1 -0
  15. package/dist/{generate-RD3LCS73.js → generate-KNER36CB.js} +3 -1
  16. package/dist/{generate-RD3LCS73.js.map → generate-KNER36CB.js.map} +1 -1
  17. package/dist/index.js +13 -11
  18. package/dist/index.js.map +1 -1
  19. package/dist/{init-6D5VNGSP.js → init-FTSEOTAD.js} +3 -1
  20. package/dist/{init-6D5VNGSP.js.map → init-FTSEOTAD.js.map} +1 -1
  21. package/dist/public/assets/index-eDQyKtAA.js +378 -0
  22. package/dist/public/assets/index-ogBV05Wr.css +1 -0
  23. package/dist/public/assets/index.es-BMf7uM-9.js +18 -0
  24. package/dist/public/assets/purify.es-B9ZVCkUG.js +2 -0
  25. package/dist/public/index.html +13 -0
  26. package/dist/{reset-password-MJ54ICGP.js → reset-password-IZQTDTU7.js} +3 -2
  27. package/dist/{reset-password-MJ54ICGP.js.map → reset-password-IZQTDTU7.js.map} +1 -1
  28. package/dist/{sync-dbt-IDDD4X2Z.js → sync-dbt-6WY7HKP7.js} +3 -1
  29. package/dist/{sync-dbt-IDDD4X2Z.js.map → sync-dbt-6WY7HKP7.js.map} +1 -1
  30. package/dist/{test-N4KIIKQN.js → test-WYNX4RYZ.js} +11 -10
  31. package/dist/{test-N4KIIKQN.js.map → test-WYNX4RYZ.js.map} +1 -1
  32. package/dist/{update-QHLCWS56.js → update-GWPF5AS6.js} +2 -1
  33. package/dist/{update-QHLCWS56.js.map → update-GWPF5AS6.js.map} +1 -1
  34. package/package.json +25 -7
  35. package/dist/chunk-6GDL3DH4.js +0 -354
  36. package/dist/chunk-6GDL3DH4.js.map +0 -1
  37. package/dist/dev-HMLMSTA7.js +0 -106
  38. package/dist/dev-HMLMSTA7.js.map +0 -1
@@ -0,0 +1,922 @@
1
+ import {
2
+ parseModelMetadata
3
+ } from "./chunk-LL3VKMZM.js";
4
+
5
+ // src/commands/validate.ts
6
+ import { readFile, readdir, access } from "fs/promises";
7
+ import { join, extname, relative } from "path";
8
+ import { parse as parseYaml } from "yaml";
9
+
10
+ // ../../packages/schema/dist/connection.js
11
+ import { z } from "zod";
12
+ var EnvAuthSchema = z.object({
13
+ type: z.literal("env"),
14
+ user_var: z.string(),
15
+ password_var: z.string()
16
+ });
17
+ var KeyPairAuthSchema = z.object({
18
+ type: z.literal("key_pair"),
19
+ user_var: z.string(),
20
+ private_key_path: z.string()
21
+ });
22
+ var SecretManagerAuthSchema = z.object({
23
+ type: z.literal("secret_manager"),
24
+ provider: z.enum(["aws_secrets_manager", "gcp_secret_manager", "vault"]),
25
+ secret_id: z.string()
26
+ });
27
+ var AuthSchema = z.discriminatedUnion("type", [
28
+ EnvAuthSchema,
29
+ KeyPairAuthSchema,
30
+ SecretManagerAuthSchema
31
+ ]);
32
+ var PoolConfigSchema = z.object({
33
+ min_connections: z.number().int().positive().optional(),
34
+ max_connections: z.number().int().positive().optional(),
35
+ idle_timeout: z.number().int().positive().optional()
36
+ });
37
+ var QueryConfigSchema = z.object({
38
+ timeout: z.number().int().positive().optional(),
39
+ max_rows: z.number().int().positive().optional()
40
+ });
41
+ var DuckDBConfigSchema = z.object({
42
+ path: z.string()
43
+ // file path or :memory:
44
+ });
45
+ var PostgresConfigSchema = z.object({
46
+ host: z.string(),
47
+ port: z.number().int().positive().default(5432),
48
+ database: z.string(),
49
+ schema: z.string().optional(),
50
+ ssl: z.boolean().optional()
51
+ });
52
+ var SnowflakeConfigSchema = z.object({
53
+ account: z.string(),
54
+ warehouse: z.string(),
55
+ database: z.string(),
56
+ schema: z.string().optional(),
57
+ role: z.string().optional()
58
+ });
59
+ var MySQLConfigSchema = z.object({
60
+ host: z.string(),
61
+ port: z.number().int().positive().default(3306),
62
+ database: z.string(),
63
+ ssl: z.boolean().optional()
64
+ });
65
+ var SQLiteConfigSchema = z.object({
66
+ path: z.string()
67
+ // file path or :memory:
68
+ });
69
+ var BaseConnectionSchema = z.object({
70
+ name: z.string().min(1),
71
+ description: z.string().optional(),
72
+ pool: PoolConfigSchema.optional(),
73
+ query: QueryConfigSchema.optional()
74
+ });
75
+ var DuckDBConnectionSchema = BaseConnectionSchema.extend({
76
+ type: z.literal("duckdb"),
77
+ config: DuckDBConfigSchema,
78
+ auth: z.undefined().optional()
79
+ });
80
+ var PostgresConnectionSchema = BaseConnectionSchema.extend({
81
+ type: z.literal("postgres"),
82
+ config: PostgresConfigSchema,
83
+ auth: AuthSchema.optional()
84
+ });
85
+ var SnowflakeConnectionSchema = BaseConnectionSchema.extend({
86
+ type: z.literal("snowflake"),
87
+ config: SnowflakeConfigSchema,
88
+ auth: AuthSchema
89
+ });
90
+ var MySQLConnectionSchema = BaseConnectionSchema.extend({
91
+ type: z.literal("mysql"),
92
+ config: MySQLConfigSchema,
93
+ auth: AuthSchema.optional()
94
+ });
95
+ var SQLiteConnectionSchema = BaseConnectionSchema.extend({
96
+ type: z.literal("sqlite"),
97
+ config: SQLiteConfigSchema,
98
+ auth: z.undefined().optional()
99
+ });
100
+ var ConnectionSchema = z.discriminatedUnion("type", [
101
+ DuckDBConnectionSchema,
102
+ PostgresConnectionSchema,
103
+ SnowflakeConnectionSchema,
104
+ MySQLConnectionSchema,
105
+ SQLiteConnectionSchema
106
+ ]);
107
+
108
+ // ../../packages/schema/dist/chart.js
109
+ import { z as z2 } from "zod";
110
+ var AxisTypeSchema = z2.enum(["temporal", "quantitative", "ordinal", "nominal"]);
111
+ var AxisSchema = z2.object({
112
+ field: z2.string().min(1),
113
+ type: AxisTypeSchema,
114
+ format: z2.string().optional(),
115
+ label: z2.string().optional()
116
+ });
117
+ var ChartTypeSchema = z2.enum([
118
+ "line",
119
+ "bar",
120
+ "area",
121
+ "pie",
122
+ "donut",
123
+ "table",
124
+ "metric",
125
+ "map",
126
+ "heatmap",
127
+ "funnel",
128
+ "sankey",
129
+ "treemap",
130
+ "waterfall",
131
+ "gauge"
132
+ ]);
133
+ var GradientSchema = z2.union([
134
+ z2.boolean(),
135
+ z2.object({
136
+ from: z2.string(),
137
+ to: z2.string()
138
+ })
139
+ ]);
140
+ var LongFormatSeriesSchema = z2.object({
141
+ field: z2.string().min(1),
142
+ colors: z2.record(z2.string(), z2.string()).optional()
143
+ });
144
+ var WideFormatColumnSchema = z2.object({
145
+ field: z2.string().min(1),
146
+ name: z2.string().optional(),
147
+ type: z2.enum(["line", "bar", "area"]).optional(),
148
+ axis: z2.enum(["left", "right"]).optional(),
149
+ color: z2.string().optional(),
150
+ style: z2.enum(["solid", "dashed", "dotted"]).optional(),
151
+ opacity: z2.number().min(0).max(1).optional(),
152
+ gradient: GradientSchema.optional()
153
+ });
154
+ var WideFormatSeriesSchema = z2.object({
155
+ columns: z2.array(WideFormatColumnSchema).min(1)
156
+ });
157
+ var SeriesConfigSchema = z2.union([
158
+ LongFormatSeriesSchema,
159
+ WideFormatSeriesSchema
160
+ ]);
161
+ var ColorConditionSchema = z2.object({
162
+ when: z2.string(),
163
+ color: z2.string()
164
+ });
165
+ var ConditionalColorSchema = z2.object({
166
+ conditions: z2.array(ColorConditionSchema).min(1),
167
+ default: z2.string().optional()
168
+ });
169
+ var ColorSchema = z2.union([
170
+ z2.string(),
171
+ ConditionalColorSchema
172
+ ]);
173
+ var LegendSchema = z2.object({
174
+ show: z2.boolean().optional(),
175
+ position: z2.enum(["top", "bottom", "left", "right"]).optional()
176
+ });
177
+ var LineAnnotationSchema = z2.object({
178
+ type: z2.literal("line"),
179
+ value: z2.number(),
180
+ label: z2.string().optional(),
181
+ color: z2.string().optional(),
182
+ style: z2.enum(["solid", "dashed", "dotted"]).optional()
183
+ });
184
+ var BandAnnotationSchema = z2.object({
185
+ type: z2.literal("band"),
186
+ from: z2.number(),
187
+ to: z2.number(),
188
+ label: z2.string().optional(),
189
+ color: z2.string().optional()
190
+ });
191
+ var AnnotationSchema = z2.discriminatedUnion("type", [
192
+ LineAnnotationSchema,
193
+ BandAnnotationSchema
194
+ ]);
195
+ var InteractionsSchema = z2.object({
196
+ tooltip: z2.boolean().default(true),
197
+ zoom: z2.boolean().default(false),
198
+ brush: z2.boolean().default(false)
199
+ });
200
+ var KpiFormatSchema = z2.object({
201
+ type: z2.enum(["number", "currency", "percent"]),
202
+ currency: z2.string().optional(),
203
+ // e.g., 'USD', 'EUR'
204
+ decimals: z2.number().optional()
205
+ });
206
+ var KpiComparisonSchema = z2.object({
207
+ enabled: z2.boolean(),
208
+ field: z2.string().min(1),
209
+ label: z2.string().optional(),
210
+ type: z2.enum(["percent_change", "absolute"])
211
+ });
212
+ var KpiValueSchema = z2.object({
213
+ field: z2.string().min(1)
214
+ });
215
+ var KpiConfigSchema = z2.object({
216
+ type: z2.literal("kpi"),
217
+ value: KpiValueSchema,
218
+ format: KpiFormatSchema,
219
+ comparison: KpiComparisonSchema.optional()
220
+ });
221
+ var CenterValueSchema = z2.object({
222
+ field: z2.string().optional(),
223
+ // 'total' for sum, or specific field
224
+ label: z2.string().optional(),
225
+ format: z2.string().optional()
226
+ });
227
+ var StandardChartConfigSchema = z2.object({
228
+ type: ChartTypeSchema,
229
+ x: AxisSchema,
230
+ y: AxisSchema.optional(),
231
+ series: SeriesConfigSchema.optional(),
232
+ stacking: z2.enum(["stacked", "percent"]).optional(),
233
+ color: ColorSchema.optional(),
234
+ gradient: GradientSchema.optional(),
235
+ legend: LegendSchema.optional(),
236
+ annotations: z2.array(AnnotationSchema).optional(),
237
+ interactions: InteractionsSchema.optional(),
238
+ centerValue: CenterValueSchema.optional()
239
+ // For donut charts
240
+ });
241
+ var DualAxesSchema = z2.object({
242
+ left: AxisSchema.optional(),
243
+ right: AxisSchema.optional()
244
+ });
245
+ var ComboChartConfigSchema = z2.object({
246
+ type: z2.literal("combo"),
247
+ x: AxisSchema,
248
+ series: WideFormatSeriesSchema,
249
+ axes: DualAxesSchema,
250
+ legend: LegendSchema.optional(),
251
+ interactions: InteractionsSchema.optional(),
252
+ gradient: GradientSchema.optional()
253
+ });
254
+ var ScatterSizeSchema = z2.object({
255
+ field: z2.string().min(1),
256
+ min: z2.number().optional(),
257
+ max: z2.number().optional(),
258
+ label: z2.string().optional()
259
+ });
260
+ var ScatterGroupSchema = z2.object({
261
+ field: z2.string().min(1)
262
+ });
263
+ var RegressionSchema = z2.object({
264
+ type: z2.literal("linear"),
265
+ show_equation: z2.boolean().optional(),
266
+ show_r_squared: z2.boolean().optional()
267
+ });
268
+ var ScatterChartConfigSchema = z2.object({
269
+ type: z2.literal("scatter"),
270
+ x: AxisSchema,
271
+ y: AxisSchema,
272
+ size: ScatterSizeSchema.optional(),
273
+ group: ScatterGroupSchema.optional(),
274
+ regression: RegressionSchema.optional(),
275
+ color: ColorSchema.optional(),
276
+ legend: LegendSchema.optional(),
277
+ interactions: InteractionsSchema.optional()
278
+ });
279
+ var HeatmapChartConfigSchema = z2.object({
280
+ type: z2.literal("heatmap"),
281
+ x: AxisSchema,
282
+ y: AxisSchema,
283
+ value: z2.object({
284
+ field: z2.string().min(1),
285
+ label: z2.string().optional()
286
+ }),
287
+ color_range: z2.object({
288
+ min: z2.string().optional(),
289
+ max: z2.string().optional()
290
+ }).optional(),
291
+ show_values: z2.boolean().optional()
292
+ });
293
+ var FunnelChartConfigSchema = z2.object({
294
+ type: z2.literal("funnel"),
295
+ stage: z2.object({ field: z2.string().min(1) }),
296
+ value: z2.object({ field: z2.string().min(1) }),
297
+ show_conversion: z2.boolean().optional(),
298
+ color: ColorSchema.optional()
299
+ });
300
+ var WaterfallChartConfigSchema = z2.object({
301
+ type: z2.literal("waterfall"),
302
+ category: z2.object({ field: z2.string().min(1) }),
303
+ value: z2.object({ field: z2.string().min(1) }),
304
+ total_field: z2.string().optional(),
305
+ colors: z2.object({
306
+ increase: z2.string().optional(),
307
+ decrease: z2.string().optional(),
308
+ total: z2.string().optional()
309
+ }).optional()
310
+ });
311
+ var GaugeThresholdSchema = z2.object({
312
+ value: z2.number(),
313
+ color: z2.string()
314
+ });
315
+ var GaugeChartConfigSchema = z2.object({
316
+ type: z2.literal("gauge"),
317
+ value: z2.object({ field: z2.string().min(1) }),
318
+ min: z2.number().optional(),
319
+ max: z2.number().optional(),
320
+ thresholds: z2.array(GaugeThresholdSchema).optional(),
321
+ format: z2.string().optional()
322
+ });
323
+ var ChartConfigSchema = z2.union([
324
+ ScatterChartConfigSchema,
325
+ ComboChartConfigSchema,
326
+ HeatmapChartConfigSchema,
327
+ FunnelChartConfigSchema,
328
+ WaterfallChartConfigSchema,
329
+ GaugeChartConfigSchema,
330
+ StandardChartConfigSchema,
331
+ KpiConfigSchema
332
+ ]);
333
+ var ParameterTypeSchema = z2.enum([
334
+ "date_range",
335
+ "select",
336
+ "multi_select",
337
+ "dynamic_select",
338
+ "text",
339
+ "number"
340
+ ]);
341
+ var ParameterOptionSchema = z2.union([
342
+ z2.string(),
343
+ z2.object({
344
+ value: z2.string(),
345
+ label: z2.string()
346
+ })
347
+ ]);
348
+ var ParameterSourceSchema = z2.object({
349
+ model: z2.string(),
350
+ value_field: z2.string(),
351
+ label_field: z2.string()
352
+ });
353
+ var ParameterSchema = z2.object({
354
+ name: z2.string().min(1),
355
+ type: ParameterTypeSchema,
356
+ label: z2.string().optional(),
357
+ default: z2.union([z2.string(), z2.number(), z2.array(z2.string())]).optional(),
358
+ options: z2.array(ParameterOptionSchema).optional(),
359
+ source: ParameterSourceSchema.optional()
360
+ });
361
+ var SourceSchema = z2.object({
362
+ model: z2.string().optional(),
363
+ sql: z2.string().optional()
364
+ }).refine((data) => data.model !== void 0 || data.sql !== void 0, { message: "Source must specify either model or sql" }).refine((data) => !(data.model !== void 0 && data.sql !== void 0), { message: "Source cannot specify both model and sql" });
365
+ var RefreshSchema = z2.object({
366
+ schedule: z2.string().optional(),
367
+ // cron expression
368
+ timezone: z2.string().optional(),
369
+ cache_ttl: z2.string().optional()
370
+ // e.g., "1h", "30m"
371
+ });
372
+ var DrillDownColumnSchema = z2.object({
373
+ field: z2.string().min(1),
374
+ label: z2.string().optional(),
375
+ format: z2.string().optional()
376
+ });
377
+ var DrillDownConfigSchema = z2.object({
378
+ chart: z2.string().optional(),
379
+ // target chart name (source side)
380
+ field: z2.string().optional(),
381
+ // field to pass as filter, defaults to x-axis field
382
+ columns: z2.array(DrillDownColumnSchema).optional()
383
+ // data table columns (target side)
384
+ });
385
+ var ChartSchema = z2.object({
386
+ // Identity
387
+ name: z2.string().min(1),
388
+ title: z2.string().min(1),
389
+ description: z2.string().optional(),
390
+ // Metadata
391
+ owner: z2.string().optional(),
392
+ tags: z2.array(z2.string()).optional(),
393
+ created: z2.string().optional(),
394
+ updated: z2.string().optional(),
395
+ // Data
396
+ source: SourceSchema,
397
+ parameters: z2.array(ParameterSchema).optional(),
398
+ // Visualization
399
+ chart: ChartConfigSchema,
400
+ // Caching
401
+ refresh: RefreshSchema.optional(),
402
+ // Drill-down navigation
403
+ drillDown: DrillDownConfigSchema.optional()
404
+ });
405
+
406
+ // ../../packages/schema/dist/project.js
407
+ import { z as z3 } from "zod";
408
+ var DefaultsSchema = z3.object({
409
+ connection: z3.string().optional(),
410
+ theme: z3.string().optional(),
411
+ timezone: z3.string().optional(),
412
+ cache_ttl: z3.string().optional(),
413
+ base_url: z3.string().url().optional()
414
+ });
415
+ var EnvironmentSchema = z3.object({
416
+ connection: z3.string().optional(),
417
+ base_url: z3.string().url().optional()
418
+ });
419
+ var GitSchema = z3.object({
420
+ provider: z3.enum(["github", "gitlab", "bitbucket"]).optional(),
421
+ repo: z3.string().optional(),
422
+ branch: z3.string().optional(),
423
+ preview_branches: z3.boolean().optional()
424
+ });
425
+ var SSOProviderSchema = z3.object({
426
+ client_id: z3.string(),
427
+ client_secret: z3.string(),
428
+ tenant: z3.string().optional(),
429
+ issuer: z3.string().optional(),
430
+ display_name: z3.string().optional()
431
+ });
432
+ var AuthSchema2 = z3.object({
433
+ enabled: z3.boolean(),
434
+ db_path: z3.string().optional(),
435
+ session_ttl: z3.string().optional(),
436
+ providers: z3.object({
437
+ google: SSOProviderSchema.optional(),
438
+ microsoft: SSOProviderSchema.optional(),
439
+ oidc: SSOProviderSchema.optional()
440
+ }).optional()
441
+ });
442
+ var FeaturesSchema = z3.object({
443
+ enable_sql_editor: z3.boolean().optional(),
444
+ enable_csv_export: z3.boolean().optional(),
445
+ enable_scheduling: z3.boolean().optional()
446
+ });
447
+ var ThemeSchema = z3.object({
448
+ palette: z3.array(z3.string()).optional(),
449
+ gradient: z3.boolean().default(false),
450
+ opacity: z3.number().min(0).max(1).default(1)
451
+ });
452
+ var ProjectSchema = z3.object({
453
+ version: z3.string().min(1),
454
+ name: z3.string().min(1),
455
+ description: z3.string().optional(),
456
+ defaults: DefaultsSchema.optional(),
457
+ environments: z3.record(z3.string(), EnvironmentSchema).optional(),
458
+ git: GitSchema.optional(),
459
+ auth: AuthSchema2.optional(),
460
+ features: FeaturesSchema.optional(),
461
+ theme: ThemeSchema.optional()
462
+ });
463
+
464
+ // ../../packages/schema/dist/model.js
465
+ import { z as z4 } from "zod";
466
+ var ParamTypeSchema = z4.enum(["string", "number", "date", "boolean", "string[]", "number[]"]);
467
+ var ModelParamSchema = z4.object({
468
+ name: z4.string().min(1),
469
+ type: ParamTypeSchema,
470
+ default: z4.string().optional(),
471
+ options: z4.array(z4.string()).optional(),
472
+ // For enum-like params
473
+ description: z4.string().optional()
474
+ });
475
+ var ReturnColumnSchema = z4.object({
476
+ name: z4.string().min(1),
477
+ type: z4.string(),
478
+ description: z4.string().optional()
479
+ });
480
+ var ModelMetadataSchema = z4.object({
481
+ name: z4.string().min(1),
482
+ description: z4.string().optional(),
483
+ owner: z4.string().optional(),
484
+ tags: z4.array(z4.string()).optional(),
485
+ params: z4.array(ModelParamSchema).optional(),
486
+ returns: z4.array(ReturnColumnSchema).optional(),
487
+ tests: z4.array(z4.string()).optional()
488
+ // SQL assertions
489
+ });
490
+ var ModelSchema = z4.object({
491
+ metadata: ModelMetadataSchema,
492
+ sql: z4.string().min(1),
493
+ filePath: z4.string().optional()
494
+ });
495
+
496
+ // ../../packages/schema/dist/dashboard.js
497
+ import { z as z5 } from "zod";
498
+ var ChartWidgetSchema = z5.object({
499
+ type: z5.literal("chart"),
500
+ ref: z5.string().min(1),
501
+ cols: z5.number().min(1).max(12)
502
+ });
503
+ var TextWidgetSchema = z5.object({
504
+ type: z5.literal("text"),
505
+ content: z5.string().min(1),
506
+ cols: z5.number().min(1).max(12)
507
+ });
508
+ var WidgetSchema = z5.discriminatedUnion("type", [
509
+ ChartWidgetSchema,
510
+ TextWidgetSchema
511
+ ]);
512
+ var RowSchema = z5.object({
513
+ height: z5.number().min(50),
514
+ widgets: z5.array(WidgetSchema).min(1)
515
+ });
516
+ var LayoutSchema = z5.object({
517
+ gap: z5.number().min(0).default(16),
518
+ rows: z5.array(RowSchema).min(1)
519
+ });
520
+ var DashboardSchema = z5.object({
521
+ // Identity
522
+ name: z5.string().min(1),
523
+ title: z5.string().min(1),
524
+ description: z5.string().optional(),
525
+ // Filters inherited by all widgets
526
+ filters: z5.array(ParameterSchema).optional(),
527
+ // Layout definition
528
+ layout: LayoutSchema
529
+ });
530
+
531
+ // ../../packages/schema/dist/schedule.js
532
+ import { z as z6 } from "zod";
533
+ var SlackChannelSchema = z6.object({
534
+ webhook_url: z6.string().min(1),
535
+ channel: z6.string().optional()
536
+ });
537
+ var ChannelSchema = z6.object({
538
+ slack: SlackChannelSchema
539
+ });
540
+ var ConditionOperatorSchema = z6.enum(["lt", "gt", "lte", "gte", "eq"]);
541
+ var ConditionSchema = z6.object({
542
+ field: z6.string().min(1),
543
+ operator: ConditionOperatorSchema,
544
+ value: z6.number()
545
+ });
546
+ var ReportScheduleSchema = z6.object({
547
+ name: z6.string().min(1),
548
+ type: z6.literal("report"),
549
+ schedule: z6.string().min(1),
550
+ timezone: z6.string().optional(),
551
+ channel: ChannelSchema,
552
+ charts: z6.array(z6.string().min(1)).min(1),
553
+ params: z6.record(z6.unknown()).optional(),
554
+ message: z6.string().optional(),
555
+ notify_on_error: z6.boolean().optional()
556
+ });
557
+ var AlertScheduleSchema = z6.object({
558
+ name: z6.string().min(1),
559
+ type: z6.literal("alert"),
560
+ schedule: z6.string().min(1),
561
+ timezone: z6.string().optional(),
562
+ channel: ChannelSchema,
563
+ chart: z6.string().min(1),
564
+ params: z6.record(z6.unknown()).optional(),
565
+ condition: ConditionSchema,
566
+ cooldown: z6.string().optional(),
567
+ message: z6.string().optional(),
568
+ notify_on_error: z6.boolean().optional()
569
+ });
570
+ var ScheduleSchema = z6.discriminatedUnion("type", [
571
+ ReportScheduleSchema,
572
+ AlertScheduleSchema
573
+ ]);
574
+
575
+ // src/commands/validate.ts
576
+ async function validateProject(projectDir, options) {
577
+ const errors = [];
578
+ const warnings = [];
579
+ let filesChecked = 0;
580
+ let filesPassed = 0;
581
+ const config = {
582
+ project: null,
583
+ connections: /* @__PURE__ */ new Map(),
584
+ models: /* @__PURE__ */ new Map(),
585
+ charts: /* @__PURE__ */ new Map(),
586
+ dashboards: /* @__PURE__ */ new Map(),
587
+ schedules: /* @__PURE__ */ new Map()
588
+ };
589
+ const projectPath = join(projectDir, "yamchart.yaml");
590
+ try {
591
+ await access(projectPath);
592
+ filesChecked++;
593
+ const content = await readFile(projectPath, "utf-8");
594
+ const parsed = parseYaml(content);
595
+ const result = ProjectSchema.safeParse(parsed);
596
+ if (result.success) {
597
+ config.project = result.data;
598
+ filesPassed++;
599
+ } else {
600
+ errors.push({
601
+ file: "yamchart.yaml",
602
+ message: `Invalid schema: ${result.error.errors[0]?.message || "Unknown error"}`
603
+ });
604
+ }
605
+ } catch {
606
+ errors.push({
607
+ file: "yamchart.yaml",
608
+ message: "yamchart.yaml not found"
609
+ });
610
+ return {
611
+ success: false,
612
+ errors,
613
+ warnings,
614
+ stats: { files: filesChecked, passed: filesPassed, failed: filesChecked - filesPassed }
615
+ };
616
+ }
617
+ const connectionsDir = join(projectDir, "connections");
618
+ try {
619
+ await access(connectionsDir);
620
+ const files = await readdir(connectionsDir);
621
+ for (const file of files) {
622
+ if (extname(file) !== ".yaml" && extname(file) !== ".yml") continue;
623
+ filesChecked++;
624
+ const filePath = join(connectionsDir, file);
625
+ const content = await readFile(filePath, "utf-8");
626
+ const parsed = parseYaml(content);
627
+ const result = ConnectionSchema.safeParse(parsed);
628
+ if (result.success) {
629
+ config.connections.set(result.data.name, result.data);
630
+ filesPassed++;
631
+ } else {
632
+ errors.push({
633
+ file: `connections/${file}`,
634
+ message: `Invalid schema: ${result.error.errors[0]?.message || "Unknown error"}`
635
+ });
636
+ }
637
+ }
638
+ } catch {
639
+ }
640
+ const modelsDir = join(projectDir, "models");
641
+ const modelStats = { filesChecked: 0, filesPassed: 0 };
642
+ try {
643
+ await access(modelsDir);
644
+ await validateModelsDir(modelsDir, projectDir, config, errors, modelStats);
645
+ filesChecked += modelStats.filesChecked;
646
+ filesPassed += modelStats.filesPassed;
647
+ } catch {
648
+ }
649
+ const chartsDir = join(projectDir, "charts");
650
+ try {
651
+ await access(chartsDir);
652
+ const files = await readdir(chartsDir);
653
+ for (const file of files) {
654
+ if (extname(file) !== ".yaml" && extname(file) !== ".yml") continue;
655
+ filesChecked++;
656
+ const filePath = join(chartsDir, file);
657
+ const content = await readFile(filePath, "utf-8");
658
+ const parsed = parseYaml(content);
659
+ const result = ChartSchema.safeParse(parsed);
660
+ if (result.success) {
661
+ config.charts.set(result.data.name, result.data);
662
+ filesPassed++;
663
+ } else {
664
+ errors.push({
665
+ file: `charts/${file}`,
666
+ message: `Invalid schema: ${result.error.errors[0]?.message || "Unknown error"}`
667
+ });
668
+ }
669
+ }
670
+ } catch {
671
+ }
672
+ const dashboardsDir = join(projectDir, "dashboards");
673
+ try {
674
+ await access(dashboardsDir);
675
+ const files = await readdir(dashboardsDir);
676
+ for (const file of files) {
677
+ if (extname(file) !== ".yaml" && extname(file) !== ".yml") continue;
678
+ filesChecked++;
679
+ const filePath = join(dashboardsDir, file);
680
+ const content = await readFile(filePath, "utf-8");
681
+ const parsed = parseYaml(content);
682
+ const result = DashboardSchema.safeParse(parsed);
683
+ if (result.success) {
684
+ config.dashboards.set(result.data.name, result.data);
685
+ filesPassed++;
686
+ } else {
687
+ errors.push({
688
+ file: `dashboards/${file}`,
689
+ message: `Invalid schema: ${result.error.errors[0]?.message || "Unknown error"}`
690
+ });
691
+ }
692
+ }
693
+ } catch {
694
+ }
695
+ const schedulesDir = join(projectDir, "schedules");
696
+ try {
697
+ await access(schedulesDir);
698
+ const files = await readdir(schedulesDir);
699
+ for (const file of files) {
700
+ if (extname(file) !== ".yaml" && extname(file) !== ".yml") continue;
701
+ filesChecked++;
702
+ const filePath = join(schedulesDir, file);
703
+ const content = await readFile(filePath, "utf-8");
704
+ const parsed = parseYaml(content);
705
+ const result = ScheduleSchema.safeParse(parsed);
706
+ if (result.success) {
707
+ config.schedules.set(result.data.name, result.data);
708
+ filesPassed++;
709
+ } else {
710
+ errors.push({
711
+ file: `schedules/${file}`,
712
+ message: `Invalid schema: ${result.error.errors[0]?.message || "Unknown error"}`
713
+ });
714
+ }
715
+ }
716
+ } catch {
717
+ }
718
+ crossReferenceValidation(config, errors, warnings);
719
+ let dryRunStats;
720
+ if (options.dryRun) {
721
+ dryRunStats = await dryRunValidation(projectDir, config, options.connection, errors);
722
+ }
723
+ return {
724
+ success: errors.length === 0,
725
+ errors,
726
+ warnings,
727
+ stats: {
728
+ files: filesChecked,
729
+ passed: filesPassed,
730
+ failed: filesChecked - filesPassed
731
+ },
732
+ dryRunStats
733
+ };
734
+ }
735
+ async function validateModelsDir(dir, projectDir, config, errors, stats) {
736
+ const entries = await readdir(dir, { withFileTypes: true });
737
+ for (const entry of entries) {
738
+ const fullPath = join(dir, entry.name);
739
+ if (entry.isDirectory()) {
740
+ await validateModelsDir(fullPath, projectDir, config, errors, stats);
741
+ } else if (extname(entry.name) === ".sql") {
742
+ stats.filesChecked++;
743
+ const relPath = relative(projectDir, fullPath);
744
+ const content = await readFile(fullPath, "utf-8");
745
+ try {
746
+ const parsed = parseModelMetadata(content);
747
+ config.models.set(parsed.name, { name: parsed.name, sql: parsed.sql });
748
+ stats.filesPassed++;
749
+ } catch (err) {
750
+ errors.push({
751
+ file: relPath,
752
+ message: err instanceof Error ? err.message : "Failed to parse model"
753
+ });
754
+ }
755
+ }
756
+ }
757
+ }
758
+ function crossReferenceValidation(config, errors, warnings) {
759
+ for (const [chartName, chart] of config.charts) {
760
+ if (chart.source.model && !config.models.has(chart.source.model)) {
761
+ const suggestion = findSimilar(chart.source.model, Array.from(config.models.keys()));
762
+ errors.push({
763
+ file: `charts/${chartName}.yaml`,
764
+ message: `Unknown model reference "${chart.source.model}"`,
765
+ suggestion: suggestion ? `Did you mean "${suggestion}"?` : void 0
766
+ });
767
+ }
768
+ }
769
+ for (const [scheduleName, schedule] of config.schedules) {
770
+ const chartNames = schedule.type === "report" ? schedule.charts : [schedule.chart];
771
+ for (const chartName of chartNames) {
772
+ if (!config.charts.has(chartName)) {
773
+ const suggestion = findSimilar(chartName, Array.from(config.charts.keys()));
774
+ warnings.push({
775
+ file: `schedules/${scheduleName}.yaml`,
776
+ message: `Unknown chart reference "${chartName}"`,
777
+ suggestion: suggestion ? `Did you mean "${suggestion}"?` : void 0
778
+ });
779
+ }
780
+ }
781
+ const cronFields = schedule.schedule.trim().split(/\s+/);
782
+ if (cronFields.length < 5 || cronFields.length > 6) {
783
+ errors.push({
784
+ file: `schedules/${scheduleName}.yaml`,
785
+ message: `Invalid cron expression "${schedule.schedule}" (expected 5-6 fields)`
786
+ });
787
+ }
788
+ }
789
+ if (config.project?.defaults?.connection) {
790
+ const connName = config.project.defaults.connection;
791
+ if (!config.connections.has(connName)) {
792
+ const suggestion = findSimilar(connName, Array.from(config.connections.keys()));
793
+ errors.push({
794
+ file: "yamchart.yaml",
795
+ message: `Default connection "${connName}" not found`,
796
+ suggestion: suggestion ? `Did you mean "${suggestion}"?` : void 0
797
+ });
798
+ }
799
+ }
800
+ }
801
+ function findSimilar(target, candidates) {
802
+ const threshold = 3;
803
+ for (const candidate of candidates) {
804
+ if (levenshtein(target.toLowerCase(), candidate.toLowerCase()) <= threshold) {
805
+ return candidate;
806
+ }
807
+ }
808
+ return null;
809
+ }
810
+ function levenshtein(a, b) {
811
+ const matrix = [];
812
+ for (let i = 0; i <= b.length; i++) {
813
+ matrix[i] = [i];
814
+ }
815
+ for (let j = 0; j <= a.length; j++) {
816
+ matrix[0][j] = j;
817
+ }
818
+ for (let i = 1; i <= b.length; i++) {
819
+ for (let j = 1; j <= a.length; j++) {
820
+ if (b.charAt(i - 1) === a.charAt(j - 1)) {
821
+ matrix[i][j] = matrix[i - 1][j - 1];
822
+ } else {
823
+ matrix[i][j] = Math.min(
824
+ matrix[i - 1][j - 1] + 1,
825
+ matrix[i][j - 1] + 1,
826
+ matrix[i - 1][j] + 1
827
+ );
828
+ }
829
+ }
830
+ }
831
+ return matrix[b.length][a.length];
832
+ }
833
+ async function dryRunValidation(projectDir, config, connectionName, errors) {
834
+ const { DuckDBConnector } = await import("./dist-JKJLH3F6.js");
835
+ let passed = 0;
836
+ let failed = 0;
837
+ const connName = connectionName || config.project?.defaults?.connection;
838
+ if (!connName) {
839
+ errors.push({
840
+ file: "yamchart.yaml",
841
+ message: "No connection specified for dry-run (use --connection or set defaults.connection)"
842
+ });
843
+ return { passed, failed: 1 };
844
+ }
845
+ const connection = config.connections.get(connName);
846
+ if (!connection) {
847
+ errors.push({
848
+ file: "yamchart.yaml",
849
+ message: `Connection "${connName}" not found`
850
+ });
851
+ return { passed, failed: 1 };
852
+ }
853
+ if (connection.type !== "duckdb") {
854
+ errors.push({
855
+ file: `connections/${connName}.yaml`,
856
+ message: `Dry-run not yet supported for connection type "${connection.type}"`
857
+ });
858
+ return { passed, failed: 1 };
859
+ }
860
+ const connPath = join(projectDir, "connections", `${connName}.yaml`);
861
+ const connContent = await readFile(connPath, "utf-8");
862
+ const connConfig = parseYaml(connContent);
863
+ const dbPath = connConfig.config.path.startsWith("/") ? connConfig.config.path : join(projectDir, connConfig.config.path);
864
+ const connector = new DuckDBConnector({ path: dbPath });
865
+ try {
866
+ await connector.connect();
867
+ for (const [modelName, model] of config.models) {
868
+ const result = await connector.explain(model.sql);
869
+ if (result.valid) {
870
+ passed++;
871
+ } else {
872
+ failed++;
873
+ errors.push({
874
+ file: `models/${modelName}.sql`,
875
+ message: result.error || "Query validation failed"
876
+ });
877
+ }
878
+ }
879
+ } finally {
880
+ await connector.disconnect();
881
+ }
882
+ return { passed, failed };
883
+ }
884
+
885
+ // src/utils/config.ts
886
+ import { access as access2 } from "fs/promises";
887
+ import { join as join2, dirname, resolve } from "path";
888
+ import { config as loadDotenv } from "dotenv";
889
+ async function findProjectRoot(startDir) {
890
+ let currentDir = resolve(startDir);
891
+ const root = dirname(currentDir);
892
+ while (currentDir !== root) {
893
+ const configPath = join2(currentDir, "yamchart.yaml");
894
+ try {
895
+ await access2(configPath);
896
+ return currentDir;
897
+ } catch {
898
+ currentDir = dirname(currentDir);
899
+ }
900
+ }
901
+ try {
902
+ await access2(join2(root, "yamchart.yaml"));
903
+ return root;
904
+ } catch {
905
+ return null;
906
+ }
907
+ }
908
+ function loadEnvFile(projectDir) {
909
+ loadDotenv({ path: join2(projectDir, ".env") });
910
+ }
911
+
912
+ export {
913
+ ConnectionSchema,
914
+ ChartSchema,
915
+ ProjectSchema,
916
+ DashboardSchema,
917
+ ScheduleSchema,
918
+ validateProject,
919
+ findProjectRoot,
920
+ loadEnvFile
921
+ };
922
+ //# sourceMappingURL=chunk-A24KVXJQ.js.map