yamchart 0.3.1 → 0.3.3

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 (33) 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/{reset-password-MJ54ICGP.js → reset-password-IZQTDTU7.js} +3 -2
  22. package/dist/{reset-password-MJ54ICGP.js.map → reset-password-IZQTDTU7.js.map} +1 -1
  23. package/dist/{sync-dbt-IDDD4X2Z.js → sync-dbt-6WY7HKP7.js} +3 -1
  24. package/dist/{sync-dbt-IDDD4X2Z.js.map → sync-dbt-6WY7HKP7.js.map} +1 -1
  25. package/dist/{test-N4KIIKQN.js → test-WYNX4RYZ.js} +11 -10
  26. package/dist/{test-N4KIIKQN.js.map → test-WYNX4RYZ.js.map} +1 -1
  27. package/dist/{update-QHLCWS56.js → update-GWPF5AS6.js} +2 -1
  28. package/dist/{update-QHLCWS56.js.map → update-GWPF5AS6.js.map} +1 -1
  29. package/package.json +25 -7
  30. package/dist/chunk-6GDL3DH4.js +0 -354
  31. package/dist/chunk-6GDL3DH4.js.map +0 -1
  32. package/dist/dev-HMLMSTA7.js +0 -106
  33. package/dist/dev-HMLMSTA7.js.map +0 -1
@@ -0,0 +1,16 @@
1
+ import {
2
+ AuthDatabase,
3
+ generateSessionToken,
4
+ hashPassword,
5
+ parseTtl,
6
+ verifyPassword
7
+ } from "./chunk-4P5UHWYK.js";
8
+ import "./chunk-DGUM43GV.js";
9
+ export {
10
+ AuthDatabase,
11
+ generateSessionToken,
12
+ hashPassword,
13
+ parseTtl,
14
+ verifyPassword
15
+ };
16
+ //# sourceMappingURL=dist-JH7OL7U4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,56 @@
1
+ import {
2
+ DATE_PRESETS,
3
+ DuckDBConnector,
4
+ MySQLConnector,
5
+ PostgresConnector,
6
+ QueryCompiler,
7
+ SQLiteConnector,
8
+ SnowflakeConnector,
9
+ VERSION,
10
+ checkSchema,
11
+ createTemplateContext,
12
+ expandCustomDateRange,
13
+ expandDatePreset,
14
+ expandThis,
15
+ extractTemplateVariables,
16
+ isCustomDateRange,
17
+ isDatePreset,
18
+ parseModelMetadata,
19
+ renderTemplate,
20
+ resolveMySQLAuth,
21
+ resolvePostgresAuth,
22
+ resolveSnowflakeAuth,
23
+ runAll,
24
+ runAssertion,
25
+ runModel,
26
+ templateHasVariable
27
+ } from "./chunk-LL3VKMZM.js";
28
+ import "./chunk-DGUM43GV.js";
29
+ export {
30
+ DATE_PRESETS,
31
+ DuckDBConnector,
32
+ MySQLConnector,
33
+ PostgresConnector,
34
+ QueryCompiler,
35
+ SQLiteConnector,
36
+ SnowflakeConnector,
37
+ VERSION,
38
+ checkSchema,
39
+ createTemplateContext,
40
+ expandCustomDateRange,
41
+ expandDatePreset,
42
+ expandThis,
43
+ extractTemplateVariables,
44
+ isCustomDateRange,
45
+ isDatePreset,
46
+ parseModelMetadata,
47
+ renderTemplate,
48
+ resolveMySQLAuth,
49
+ resolvePostgresAuth,
50
+ resolveSnowflakeAuth,
51
+ runAll,
52
+ runAssertion,
53
+ runModel,
54
+ templateHasVariable
55
+ };
56
+ //# sourceMappingURL=dist-JKJLH3F6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,3 +1,5 @@
1
+ import "./chunk-DGUM43GV.js";
2
+
1
3
  // src/commands/generate.ts
2
4
  import { readFile } from "fs/promises";
3
5
  import { join as join2 } from "path";
@@ -312,4 +314,4 @@ async function generate(projectDir, options) {
312
314
  export {
313
315
  generate
314
316
  };
315
- //# sourceMappingURL=generate-RD3LCS73.js.map
317
+ //# sourceMappingURL=generate-KNER36CB.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/generate.ts","../src/generate/detector.ts","../src/generate/variants.ts","../src/generate/writer.ts","../src/generate/prompts.ts"],"sourcesContent":["// apps/cli/src/commands/generate.ts\nimport { readFile } from 'fs/promises';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\nimport type { CatalogData, CatalogModel } from '../dbt/catalog.js';\nimport { detectColumnTypes } from '../generate/detector.js';\nimport { generateVariants, type MetricColumn } from '../generate/variants.js';\nimport { writeStub, stubExists } from '../generate/writer.js';\nimport {\n promptDateColumn,\n promptMetrics,\n promptDimensions,\n promptConfirmVariants,\n promptOverwrite,\n} from '../generate/prompts.js';\n\nexport interface GenerateOptions {\n model?: string;\n yolo?: boolean;\n}\n\nexport interface GenerateResult {\n success: boolean;\n error?: string;\n modelsProcessed: number;\n filesCreated: number;\n filesSkipped: number;\n}\n\nasync function loadCatalog(projectDir: string): Promise<CatalogData | null> {\n const catalogPath = join(projectDir, '.yamchart', 'catalog.json');\n if (!existsSync(catalogPath)) return null;\n\n const content = await readFile(catalogPath, 'utf-8');\n return JSON.parse(content);\n}\n\nasync function processModel(\n projectDir: string,\n model: CatalogModel,\n yolo: boolean\n): Promise<{ created: number; skipped: number }> {\n const detected = detectColumnTypes(model.columns);\n\n let dateColumn: string | null;\n let metrics: MetricColumn[];\n let dimensions: string[];\n\n if (yolo) {\n // Use all defaults\n dateColumn = detected.dateColumns[0] || null;\n metrics = detected.metricColumns.map(name => ({ name, aggregation: 'sum' as const }));\n dimensions = detected.dimensionColumns;\n } else {\n // Interactive prompts\n dateColumn = await promptDateColumn(model.name, detected);\n metrics = await promptMetrics(model.name, detected);\n dimensions = await promptDimensions(model.name, detected);\n }\n\n if (metrics.length === 0) {\n return { created: 0, skipped: 0 };\n }\n\n const variants = generateVariants({\n modelName: model.name,\n tableName: model.table || model.name,\n dateColumn,\n metricColumns: metrics,\n dimensionColumns: dimensions,\n });\n\n let confirmedVariants = variants;\n if (!yolo && variants.length > 0) {\n const selected = await promptConfirmVariants(\n model.name,\n variants.map(v => v.name)\n );\n confirmedVariants = variants.filter(v => selected.includes(v.name));\n }\n\n let created = 0;\n let skipped = 0;\n\n for (const variant of confirmedVariants) {\n const exists = await stubExists(projectDir, variant.filename);\n\n if (exists && !yolo) {\n const action = await promptOverwrite(variant.filename);\n if (action === 'skip') {\n skipped++;\n continue;\n }\n if (action === 'rename') {\n variant.filename = variant.filename.replace('.sql', '_new.sql');\n }\n }\n\n await writeStub(projectDir, variant.filename, variant.sql);\n created++;\n }\n\n return { created, skipped };\n}\n\nexport async function generate(\n projectDir: string,\n options: GenerateOptions\n): Promise<GenerateResult> {\n const catalog = await loadCatalog(projectDir);\n\n if (!catalog) {\n return {\n success: false,\n error: 'catalog.json not found. Run `yamchart sync-dbt` first.',\n modelsProcessed: 0,\n filesCreated: 0,\n filesSkipped: 0,\n };\n }\n\n let models = catalog.models;\n\n if (options.model) {\n models = models.filter(m => m.name === options.model);\n if (models.length === 0) {\n return {\n success: false,\n error: `Model '${options.model}' not found in catalog`,\n modelsProcessed: 0,\n filesCreated: 0,\n filesSkipped: 0,\n };\n }\n }\n\n let totalCreated = 0;\n let totalSkipped = 0;\n\n for (const model of models) {\n const { created, skipped } = await processModel(\n projectDir,\n model,\n options.yolo ?? false\n );\n totalCreated += created;\n totalSkipped += skipped;\n }\n\n return {\n success: true,\n modelsProcessed: models.length,\n filesCreated: totalCreated,\n filesSkipped: totalSkipped,\n };\n}\n","import type { DbtColumn } from '../dbt/types.js';\n\nexport interface DetectedColumns {\n dateColumns: string[];\n metricColumns: string[];\n dimensionColumns: string[];\n primaryKeys: string[];\n foreignKeys: string[];\n}\n\nconst DATE_TYPES = ['date', 'timestamp', 'datetime', 'timestamptz', 'timestamp_ntz'];\nconst NUMERIC_TYPES = ['int', 'integer', 'bigint', 'smallint', 'numeric', 'decimal', 'float', 'double', 'real', 'number'];\nconst STRING_TYPES = ['string', 'varchar', 'char', 'text'];\nconst BOOLEAN_TYPES = ['boolean', 'bool', 'bit'];\n\nfunction isDateColumn(col: DbtColumn): boolean {\n const typeLower = (col.data_type || '').toLowerCase();\n if (DATE_TYPES.some(t => typeLower.includes(t))) return true;\n\n const nameLower = col.name.toLowerCase();\n return nameLower.endsWith('_at') || nameLower.endsWith('_date') || nameLower.endsWith('_time');\n}\n\nfunction isNumericColumn(col: DbtColumn): boolean {\n const typeLower = (col.data_type || '').toLowerCase();\n return NUMERIC_TYPES.some(t => typeLower.includes(t));\n}\n\nfunction isStringColumn(col: DbtColumn): boolean {\n const typeLower = (col.data_type || '').toLowerCase();\n return STRING_TYPES.some(t => typeLower.includes(t));\n}\n\nfunction isBooleanColumn(col: DbtColumn): boolean {\n const typeLower = (col.data_type || '').toLowerCase();\n return BOOLEAN_TYPES.some(t => typeLower.includes(t));\n}\n\nfunction isPrimaryKey(col: DbtColumn): boolean {\n if (col.hints.includes('primary_key') || col.hints.includes('unique')) return true;\n return col.name === 'id';\n}\n\nfunction isForeignKey(col: DbtColumn): boolean {\n return col.hints.some(h => h.startsWith('fk:'));\n}\n\nexport function detectColumnTypes(columns: DbtColumn[]): DetectedColumns {\n const dateColumns: string[] = [];\n const metricColumns: string[] = [];\n const dimensionColumns: string[] = [];\n const primaryKeys: string[] = [];\n const foreignKeys: string[] = [];\n\n for (const col of columns) {\n if (isPrimaryKey(col)) {\n primaryKeys.push(col.name);\n continue;\n }\n\n if (isForeignKey(col)) {\n foreignKeys.push(col.name);\n continue;\n }\n\n if (isDateColumn(col)) {\n dateColumns.push(col.name);\n } else if (isNumericColumn(col)) {\n metricColumns.push(col.name);\n } else {\n // String, boolean, or unknown types all become dimensions\n dimensionColumns.push(col.name);\n }\n }\n\n return { dateColumns, metricColumns, dimensionColumns, primaryKeys, foreignKeys };\n}\n","// apps/cli/src/generate/variants.ts\n\nexport interface MetricColumn {\n name: string;\n aggregation: 'sum' | 'avg' | 'count' | 'min' | 'max';\n}\n\nexport interface VariantConfig {\n modelName: string;\n tableName: string;\n dateColumn: string | null;\n metricColumns: MetricColumn[];\n dimensionColumns: string[];\n}\n\nexport interface GeneratedVariant {\n name: string;\n filename: string;\n description: string;\n sql: string;\n}\n\nfunction formatDate(): string {\n return new Date().toISOString().split('T')[0];\n}\n\nfunction quoteIdentifier(name: string): string {\n // Double quotes for ANSI SQL standard\n // Escape any existing double quotes by doubling them\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\nfunction generateHeader(modelName: string, variantName: string, description: string, tableName: string): string {\n return `-- @generated: from dbt model '${modelName}' on ${formatDate()}\n-- @name: ${variantName}\n-- @description: ${description}\n-- @source: ${tableName}\n\n`;\n}\n\nfunction generateMetricSelects(metrics: MetricColumn[]): string {\n return metrics\n .map(m => ` ${m.aggregation.toUpperCase()}(${quoteIdentifier(m.name)}) AS ${quoteIdentifier(m.aggregation + '_' + m.name)}`)\n .join(',\\n');\n}\n\nexport function generateVariants(config: VariantConfig): GeneratedVariant[] {\n const variants: GeneratedVariant[] = [];\n const { modelName, tableName, dateColumn, metricColumns, dimensionColumns } = config;\n\n // Time series variant\n if (dateColumn && metricColumns.length > 0) {\n const name = `${modelName}_over_time`;\n const description = `${modelName} aggregated over time`;\n const sql = `${generateHeader(modelName, name, description, tableName)}SELECT\n date_trunc('{{ granularity }}', ${quoteIdentifier(dateColumn)}) AS period,\n${generateMetricSelects(metricColumns)}\nFROM ${tableName}\nWHERE ${quoteIdentifier(dateColumn)} >= '{{ start_date }}'\n AND ${quoteIdentifier(dateColumn)} <= '{{ end_date }}'\nGROUP BY 1\nORDER BY 1\n`;\n variants.push({ name, filename: `${name}.sql`, description, sql });\n }\n\n // Dimension variants\n for (const dim of dimensionColumns) {\n const name = `${modelName}_by_${dim}`;\n const description = `${modelName} grouped by ${dim}`;\n let sql = generateHeader(modelName, name, description, tableName);\n sql += `SELECT\n ${quoteIdentifier(dim)},\n${generateMetricSelects(metricColumns)}\nFROM ${tableName}\n`;\n if (dateColumn) {\n sql += `WHERE ${quoteIdentifier(dateColumn)} >= '{{ start_date }}'\n AND ${quoteIdentifier(dateColumn)} <= '{{ end_date }}'\n`;\n }\n sql += `GROUP BY 1\nORDER BY 2 DESC\n`;\n variants.push({ name, filename: `${name}.sql`, description, sql });\n }\n\n // KPI variant\n if (metricColumns.length > 0) {\n const name = `${modelName}_kpi`;\n const description = `${modelName} summary metrics`;\n let sql = generateHeader(modelName, name, description, tableName);\n sql += `SELECT\n${generateMetricSelects(metricColumns)}\nFROM ${tableName}\n`;\n if (dateColumn) {\n sql += `WHERE ${quoteIdentifier(dateColumn)} >= '{{ start_date }}'\n AND ${quoteIdentifier(dateColumn)} <= '{{ end_date }}'\n`;\n }\n variants.push({ name, filename: `${name}.sql`, description, sql });\n }\n\n return variants;\n}\n","// apps/cli/src/generate/writer.ts\nimport { writeFile, mkdir } from 'fs/promises';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\n\nexport async function writeStub(projectDir: string, filename: string, content: string): Promise<void> {\n const modelsDir = join(projectDir, 'models');\n await mkdir(modelsDir, { recursive: true });\n await writeFile(join(modelsDir, filename), content, 'utf-8');\n}\n\nexport async function stubExists(projectDir: string, filename: string): Promise<boolean> {\n return existsSync(join(projectDir, 'models', filename));\n}\n","// apps/cli/src/generate/prompts.ts\nimport { confirm, select, checkbox } from '@inquirer/prompts';\nimport type { DetectedColumns } from './detector.js';\nimport type { MetricColumn } from './variants.js';\n\nexport interface DateColumnChoice {\n name: string;\n value: string | null;\n checked: boolean;\n}\n\nexport interface MetricChoice {\n name: string;\n value: MetricColumn;\n checked: boolean;\n}\n\nexport interface DimensionChoice {\n name: string;\n value: string;\n checked: boolean;\n}\n\nexport function buildDateColumnChoices(detected: DetectedColumns): DateColumnChoice[] {\n const choices: DateColumnChoice[] = detected.dateColumns.map((col, i) => ({\n name: col,\n value: col,\n checked: i === 0,\n }));\n choices.push({ name: 'Skip time series', value: null, checked: false });\n return choices;\n}\n\nexport function buildMetricChoices(detected: DetectedColumns): MetricChoice[] {\n return detected.metricColumns.map(col => ({\n name: `${col} (sum)`,\n value: { name: col, aggregation: 'sum' as const },\n checked: true,\n }));\n}\n\nexport function buildDimensionChoices(detected: DetectedColumns): DimensionChoice[] {\n return detected.dimensionColumns.map(col => ({\n name: col,\n value: col,\n checked: true,\n }));\n}\n\nexport async function promptDateColumn(modelName: string, detected: DetectedColumns): Promise<string | null> {\n if (detected.dateColumns.length === 0) return null;\n\n const defaultCol = detected.dateColumns[0];\n const confirmed = await confirm({\n message: `${modelName}: Use '${defaultCol}' for time series?`,\n default: true,\n });\n\n if (confirmed) return defaultCol;\n\n if (detected.dateColumns.length === 1) return null;\n\n return select({\n message: 'Select date column:',\n choices: buildDateColumnChoices(detected).map(c => ({ name: c.name, value: c.value })),\n });\n}\n\nexport async function promptMetrics(modelName: string, detected: DetectedColumns): Promise<MetricColumn[]> {\n if (detected.metricColumns.length === 0) return [];\n\n const choices = buildMetricChoices(detected);\n const selected = await checkbox({\n message: `${modelName}: Select metrics to aggregate:`,\n choices: choices.map(c => ({ name: c.name, value: c.value, checked: c.checked })),\n });\n\n return selected;\n}\n\nexport async function promptDimensions(modelName: string, detected: DetectedColumns): Promise<string[]> {\n if (detected.dimensionColumns.length === 0) return [];\n\n const choices = buildDimensionChoices(detected);\n const selected = await checkbox({\n message: `${modelName}: Select dimensions for grouping:`,\n choices: choices.map(c => ({ name: c.name, value: c.value, checked: c.checked })),\n });\n\n return selected;\n}\n\nexport async function promptConfirmVariants(modelName: string, variantNames: string[]): Promise<string[]> {\n const choices = variantNames.map(name => ({ name, value: name, checked: true }));\n\n return checkbox({\n message: `${modelName}: Generate these stubs?`,\n choices,\n });\n}\n\nexport async function promptOverwrite(filename: string): Promise<'overwrite' | 'skip' | 'rename'> {\n return select({\n message: `${filename} already exists:`,\n choices: [\n { name: 'Overwrite', value: 'overwrite' as const },\n { name: 'Skip', value: 'skip' as const },\n { name: 'Rename (add suffix)', value: 'rename' as const },\n ],\n });\n}\n"],"mappings":"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","names":["join","existsSync","join","existsSync"]}
1
+ {"version":3,"sources":["../src/commands/generate.ts","../src/generate/detector.ts","../src/generate/variants.ts","../src/generate/writer.ts","../src/generate/prompts.ts"],"sourcesContent":["// apps/cli/src/commands/generate.ts\nimport { readFile } from 'fs/promises';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\nimport type { CatalogData, CatalogModel } from '../dbt/catalog.js';\nimport { detectColumnTypes } from '../generate/detector.js';\nimport { generateVariants, type MetricColumn } from '../generate/variants.js';\nimport { writeStub, stubExists } from '../generate/writer.js';\nimport {\n promptDateColumn,\n promptMetrics,\n promptDimensions,\n promptConfirmVariants,\n promptOverwrite,\n} from '../generate/prompts.js';\n\nexport interface GenerateOptions {\n model?: string;\n yolo?: boolean;\n}\n\nexport interface GenerateResult {\n success: boolean;\n error?: string;\n modelsProcessed: number;\n filesCreated: number;\n filesSkipped: number;\n}\n\nasync function loadCatalog(projectDir: string): Promise<CatalogData | null> {\n const catalogPath = join(projectDir, '.yamchart', 'catalog.json');\n if (!existsSync(catalogPath)) return null;\n\n const content = await readFile(catalogPath, 'utf-8');\n return JSON.parse(content);\n}\n\nasync function processModel(\n projectDir: string,\n model: CatalogModel,\n yolo: boolean\n): Promise<{ created: number; skipped: number }> {\n const detected = detectColumnTypes(model.columns);\n\n let dateColumn: string | null;\n let metrics: MetricColumn[];\n let dimensions: string[];\n\n if (yolo) {\n // Use all defaults\n dateColumn = detected.dateColumns[0] || null;\n metrics = detected.metricColumns.map(name => ({ name, aggregation: 'sum' as const }));\n dimensions = detected.dimensionColumns;\n } else {\n // Interactive prompts\n dateColumn = await promptDateColumn(model.name, detected);\n metrics = await promptMetrics(model.name, detected);\n dimensions = await promptDimensions(model.name, detected);\n }\n\n if (metrics.length === 0) {\n return { created: 0, skipped: 0 };\n }\n\n const variants = generateVariants({\n modelName: model.name,\n tableName: model.table || model.name,\n dateColumn,\n metricColumns: metrics,\n dimensionColumns: dimensions,\n });\n\n let confirmedVariants = variants;\n if (!yolo && variants.length > 0) {\n const selected = await promptConfirmVariants(\n model.name,\n variants.map(v => v.name)\n );\n confirmedVariants = variants.filter(v => selected.includes(v.name));\n }\n\n let created = 0;\n let skipped = 0;\n\n for (const variant of confirmedVariants) {\n const exists = await stubExists(projectDir, variant.filename);\n\n if (exists && !yolo) {\n const action = await promptOverwrite(variant.filename);\n if (action === 'skip') {\n skipped++;\n continue;\n }\n if (action === 'rename') {\n variant.filename = variant.filename.replace('.sql', '_new.sql');\n }\n }\n\n await writeStub(projectDir, variant.filename, variant.sql);\n created++;\n }\n\n return { created, skipped };\n}\n\nexport async function generate(\n projectDir: string,\n options: GenerateOptions\n): Promise<GenerateResult> {\n const catalog = await loadCatalog(projectDir);\n\n if (!catalog) {\n return {\n success: false,\n error: 'catalog.json not found. Run `yamchart sync-dbt` first.',\n modelsProcessed: 0,\n filesCreated: 0,\n filesSkipped: 0,\n };\n }\n\n let models = catalog.models;\n\n if (options.model) {\n models = models.filter(m => m.name === options.model);\n if (models.length === 0) {\n return {\n success: false,\n error: `Model '${options.model}' not found in catalog`,\n modelsProcessed: 0,\n filesCreated: 0,\n filesSkipped: 0,\n };\n }\n }\n\n let totalCreated = 0;\n let totalSkipped = 0;\n\n for (const model of models) {\n const { created, skipped } = await processModel(\n projectDir,\n model,\n options.yolo ?? false\n );\n totalCreated += created;\n totalSkipped += skipped;\n }\n\n return {\n success: true,\n modelsProcessed: models.length,\n filesCreated: totalCreated,\n filesSkipped: totalSkipped,\n };\n}\n","import type { DbtColumn } from '../dbt/types.js';\n\nexport interface DetectedColumns {\n dateColumns: string[];\n metricColumns: string[];\n dimensionColumns: string[];\n primaryKeys: string[];\n foreignKeys: string[];\n}\n\nconst DATE_TYPES = ['date', 'timestamp', 'datetime', 'timestamptz', 'timestamp_ntz'];\nconst NUMERIC_TYPES = ['int', 'integer', 'bigint', 'smallint', 'numeric', 'decimal', 'float', 'double', 'real', 'number'];\nconst STRING_TYPES = ['string', 'varchar', 'char', 'text'];\nconst BOOLEAN_TYPES = ['boolean', 'bool', 'bit'];\n\nfunction isDateColumn(col: DbtColumn): boolean {\n const typeLower = (col.data_type || '').toLowerCase();\n if (DATE_TYPES.some(t => typeLower.includes(t))) return true;\n\n const nameLower = col.name.toLowerCase();\n return nameLower.endsWith('_at') || nameLower.endsWith('_date') || nameLower.endsWith('_time');\n}\n\nfunction isNumericColumn(col: DbtColumn): boolean {\n const typeLower = (col.data_type || '').toLowerCase();\n return NUMERIC_TYPES.some(t => typeLower.includes(t));\n}\n\nfunction isStringColumn(col: DbtColumn): boolean {\n const typeLower = (col.data_type || '').toLowerCase();\n return STRING_TYPES.some(t => typeLower.includes(t));\n}\n\nfunction isBooleanColumn(col: DbtColumn): boolean {\n const typeLower = (col.data_type || '').toLowerCase();\n return BOOLEAN_TYPES.some(t => typeLower.includes(t));\n}\n\nfunction isPrimaryKey(col: DbtColumn): boolean {\n if (col.hints.includes('primary_key') || col.hints.includes('unique')) return true;\n return col.name === 'id';\n}\n\nfunction isForeignKey(col: DbtColumn): boolean {\n return col.hints.some(h => h.startsWith('fk:'));\n}\n\nexport function detectColumnTypes(columns: DbtColumn[]): DetectedColumns {\n const dateColumns: string[] = [];\n const metricColumns: string[] = [];\n const dimensionColumns: string[] = [];\n const primaryKeys: string[] = [];\n const foreignKeys: string[] = [];\n\n for (const col of columns) {\n if (isPrimaryKey(col)) {\n primaryKeys.push(col.name);\n continue;\n }\n\n if (isForeignKey(col)) {\n foreignKeys.push(col.name);\n continue;\n }\n\n if (isDateColumn(col)) {\n dateColumns.push(col.name);\n } else if (isNumericColumn(col)) {\n metricColumns.push(col.name);\n } else {\n // String, boolean, or unknown types all become dimensions\n dimensionColumns.push(col.name);\n }\n }\n\n return { dateColumns, metricColumns, dimensionColumns, primaryKeys, foreignKeys };\n}\n","// apps/cli/src/generate/variants.ts\n\nexport interface MetricColumn {\n name: string;\n aggregation: 'sum' | 'avg' | 'count' | 'min' | 'max';\n}\n\nexport interface VariantConfig {\n modelName: string;\n tableName: string;\n dateColumn: string | null;\n metricColumns: MetricColumn[];\n dimensionColumns: string[];\n}\n\nexport interface GeneratedVariant {\n name: string;\n filename: string;\n description: string;\n sql: string;\n}\n\nfunction formatDate(): string {\n return new Date().toISOString().split('T')[0];\n}\n\nfunction quoteIdentifier(name: string): string {\n // Double quotes for ANSI SQL standard\n // Escape any existing double quotes by doubling them\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\nfunction generateHeader(modelName: string, variantName: string, description: string, tableName: string): string {\n return `-- @generated: from dbt model '${modelName}' on ${formatDate()}\n-- @name: ${variantName}\n-- @description: ${description}\n-- @source: ${tableName}\n\n`;\n}\n\nfunction generateMetricSelects(metrics: MetricColumn[]): string {\n return metrics\n .map(m => ` ${m.aggregation.toUpperCase()}(${quoteIdentifier(m.name)}) AS ${quoteIdentifier(m.aggregation + '_' + m.name)}`)\n .join(',\\n');\n}\n\nexport function generateVariants(config: VariantConfig): GeneratedVariant[] {\n const variants: GeneratedVariant[] = [];\n const { modelName, tableName, dateColumn, metricColumns, dimensionColumns } = config;\n\n // Time series variant\n if (dateColumn && metricColumns.length > 0) {\n const name = `${modelName}_over_time`;\n const description = `${modelName} aggregated over time`;\n const sql = `${generateHeader(modelName, name, description, tableName)}SELECT\n date_trunc('{{ granularity }}', ${quoteIdentifier(dateColumn)}) AS period,\n${generateMetricSelects(metricColumns)}\nFROM ${tableName}\nWHERE ${quoteIdentifier(dateColumn)} >= '{{ start_date }}'\n AND ${quoteIdentifier(dateColumn)} <= '{{ end_date }}'\nGROUP BY 1\nORDER BY 1\n`;\n variants.push({ name, filename: `${name}.sql`, description, sql });\n }\n\n // Dimension variants\n for (const dim of dimensionColumns) {\n const name = `${modelName}_by_${dim}`;\n const description = `${modelName} grouped by ${dim}`;\n let sql = generateHeader(modelName, name, description, tableName);\n sql += `SELECT\n ${quoteIdentifier(dim)},\n${generateMetricSelects(metricColumns)}\nFROM ${tableName}\n`;\n if (dateColumn) {\n sql += `WHERE ${quoteIdentifier(dateColumn)} >= '{{ start_date }}'\n AND ${quoteIdentifier(dateColumn)} <= '{{ end_date }}'\n`;\n }\n sql += `GROUP BY 1\nORDER BY 2 DESC\n`;\n variants.push({ name, filename: `${name}.sql`, description, sql });\n }\n\n // KPI variant\n if (metricColumns.length > 0) {\n const name = `${modelName}_kpi`;\n const description = `${modelName} summary metrics`;\n let sql = generateHeader(modelName, name, description, tableName);\n sql += `SELECT\n${generateMetricSelects(metricColumns)}\nFROM ${tableName}\n`;\n if (dateColumn) {\n sql += `WHERE ${quoteIdentifier(dateColumn)} >= '{{ start_date }}'\n AND ${quoteIdentifier(dateColumn)} <= '{{ end_date }}'\n`;\n }\n variants.push({ name, filename: `${name}.sql`, description, sql });\n }\n\n return variants;\n}\n","// apps/cli/src/generate/writer.ts\nimport { writeFile, mkdir } from 'fs/promises';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\n\nexport async function writeStub(projectDir: string, filename: string, content: string): Promise<void> {\n const modelsDir = join(projectDir, 'models');\n await mkdir(modelsDir, { recursive: true });\n await writeFile(join(modelsDir, filename), content, 'utf-8');\n}\n\nexport async function stubExists(projectDir: string, filename: string): Promise<boolean> {\n return existsSync(join(projectDir, 'models', filename));\n}\n","// apps/cli/src/generate/prompts.ts\nimport { confirm, select, checkbox } from '@inquirer/prompts';\nimport type { DetectedColumns } from './detector.js';\nimport type { MetricColumn } from './variants.js';\n\nexport interface DateColumnChoice {\n name: string;\n value: string | null;\n checked: boolean;\n}\n\nexport interface MetricChoice {\n name: string;\n value: MetricColumn;\n checked: boolean;\n}\n\nexport interface DimensionChoice {\n name: string;\n value: string;\n checked: boolean;\n}\n\nexport function buildDateColumnChoices(detected: DetectedColumns): DateColumnChoice[] {\n const choices: DateColumnChoice[] = detected.dateColumns.map((col, i) => ({\n name: col,\n value: col,\n checked: i === 0,\n }));\n choices.push({ name: 'Skip time series', value: null, checked: false });\n return choices;\n}\n\nexport function buildMetricChoices(detected: DetectedColumns): MetricChoice[] {\n return detected.metricColumns.map(col => ({\n name: `${col} (sum)`,\n value: { name: col, aggregation: 'sum' as const },\n checked: true,\n }));\n}\n\nexport function buildDimensionChoices(detected: DetectedColumns): DimensionChoice[] {\n return detected.dimensionColumns.map(col => ({\n name: col,\n value: col,\n checked: true,\n }));\n}\n\nexport async function promptDateColumn(modelName: string, detected: DetectedColumns): Promise<string | null> {\n if (detected.dateColumns.length === 0) return null;\n\n const defaultCol = detected.dateColumns[0];\n const confirmed = await confirm({\n message: `${modelName}: Use '${defaultCol}' for time series?`,\n default: true,\n });\n\n if (confirmed) return defaultCol;\n\n if (detected.dateColumns.length === 1) return null;\n\n return select({\n message: 'Select date column:',\n choices: buildDateColumnChoices(detected).map(c => ({ name: c.name, value: c.value })),\n });\n}\n\nexport async function promptMetrics(modelName: string, detected: DetectedColumns): Promise<MetricColumn[]> {\n if (detected.metricColumns.length === 0) return [];\n\n const choices = buildMetricChoices(detected);\n const selected = await checkbox({\n message: `${modelName}: Select metrics to aggregate:`,\n choices: choices.map(c => ({ name: c.name, value: c.value, checked: c.checked })),\n });\n\n return selected;\n}\n\nexport async function promptDimensions(modelName: string, detected: DetectedColumns): Promise<string[]> {\n if (detected.dimensionColumns.length === 0) return [];\n\n const choices = buildDimensionChoices(detected);\n const selected = await checkbox({\n message: `${modelName}: Select dimensions for grouping:`,\n choices: choices.map(c => ({ name: c.name, value: c.value, checked: c.checked })),\n });\n\n return selected;\n}\n\nexport async function promptConfirmVariants(modelName: string, variantNames: string[]): Promise<string[]> {\n const choices = variantNames.map(name => ({ name, value: name, checked: true }));\n\n return checkbox({\n message: `${modelName}: Generate these stubs?`,\n choices,\n });\n}\n\nexport async function promptOverwrite(filename: string): Promise<'overwrite' | 'skip' | 'rename'> {\n return select({\n message: `${filename} already exists:`,\n choices: [\n { name: 'Overwrite', value: 'overwrite' as const },\n { name: 'Skip', value: 'skip' as const },\n { name: 'Rename (add suffix)', value: 'rename' as const },\n ],\n });\n}\n"],"mappings":"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","names":["join","existsSync","join","existsSync"]}
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ checkForUpdate
4
+ } from "./chunk-3CLMQNNR.js";
2
5
  import {
3
6
  findProjectRoot,
4
7
  loadEnvFile,
5
8
  validateProject
6
- } from "./chunk-6GDL3DH4.js";
7
- import {
8
- checkForUpdate
9
- } from "./chunk-3CLMQNNR.js";
9
+ } from "./chunk-A24KVXJQ.js";
10
10
  import {
11
11
  detail,
12
12
  error,
@@ -17,6 +17,8 @@ import {
17
17
  success,
18
18
  warning
19
19
  } from "./chunk-HJVVHYVN.js";
20
+ import "./chunk-LL3VKMZM.js";
21
+ import "./chunk-DGUM43GV.js";
20
22
 
21
23
  // src/index.ts
22
24
  import { Command } from "commander";
@@ -93,7 +95,7 @@ program.command("dev").description("Start development server with hot reload").a
93
95
  detail("Run this command from a yamchart project directory");
94
96
  process.exit(2);
95
97
  }
96
- const { runDevServer } = await import("./dev-HMLMSTA7.js");
98
+ const { runDevServer } = await import("./dev-PTVNJI7G.js");
97
99
  await runDevServer(projectDir, {
98
100
  port: parseInt(options.port, 10),
99
101
  apiOnly: options.apiOnly ?? false,
@@ -101,7 +103,7 @@ program.command("dev").description("Start development server with hot reload").a
101
103
  });
102
104
  });
103
105
  program.command("init").description("Create a new yamchart project").argument("[directory]", "Target directory", ".").option("--example", "Create full example project with sample database").option("--empty", "Create only yamchart.yaml (no connections, models, or charts)").option("--force", "Overwrite existing files").action(async (directory, options) => {
104
- const { initProject } = await import("./init-6D5VNGSP.js");
106
+ const { initProject } = await import("./init-FTSEOTAD.js");
105
107
  const targetDir = resolve(directory);
106
108
  const result = await initProject(targetDir, options);
107
109
  if (!result.success) {
@@ -120,7 +122,7 @@ program.command("init").description("Create a new yamchart project").argument("[
120
122
  info(`Run \`cd ${directory === "." ? basename(targetDir) : directory} && yamchart dev\` to start.`);
121
123
  });
122
124
  program.command("sync-dbt").description("Sync dbt project metadata into AI-readable catalog").option("-s, --source <type>", "Source type: local, github, dbt-cloud", "local").option("-p, --path <dir>", "Path to dbt project (for local source)").option("--repo <repo>", "GitHub repository (for github source)").option("--branch <branch>", "Git branch (for github source)", "main").option("-i, --include <patterns...>", "Include glob patterns").option("-e, --exclude <patterns...>", "Exclude glob patterns").option("-t, --tag <tags...>", "Filter by dbt tags").option("--refresh", "Re-sync using saved configuration").action(async (options) => {
123
- const { syncDbt, loadSyncConfig } = await import("./sync-dbt-IDDD4X2Z.js");
125
+ const { syncDbt, loadSyncConfig } = await import("./sync-dbt-6WY7HKP7.js");
124
126
  const projectDir = await findProjectRoot(process.cwd());
125
127
  if (!projectDir) {
126
128
  error("yamchart.yaml not found");
@@ -158,7 +160,7 @@ program.command("sync-dbt").description("Sync dbt project metadata into AI-reada
158
160
  }
159
161
  });
160
162
  program.command("generate").description("Generate SQL model stubs from dbt catalog").argument("[model]", "Specific model to generate (optional)").option("--yolo", "Skip all prompts, use defaults for everything").action(async (model, options) => {
161
- const { generate } = await import("./generate-RD3LCS73.js");
163
+ const { generate } = await import("./generate-KNER36CB.js");
162
164
  const projectDir = await findProjectRoot(process.cwd());
163
165
  if (!projectDir) {
164
166
  error("yamchart.yaml not found");
@@ -192,7 +194,7 @@ program.command("test").description("Run model tests (@returns schema checks and
192
194
  }
193
195
  loadEnvFile(projectDir);
194
196
  try {
195
- const { testProject, formatTestOutput } = await import("./test-N4KIIKQN.js");
197
+ const { testProject, formatTestOutput } = await import("./test-WYNX4RYZ.js");
196
198
  const result = await testProject(projectDir, model, {
197
199
  connection: options.connection,
198
200
  json: options.json
@@ -215,7 +217,7 @@ program.command("test").description("Run model tests (@returns schema checks and
215
217
  }
216
218
  });
217
219
  program.command("update").description("Check for yamchart updates").action(async () => {
218
- const { runUpdate } = await import("./update-QHLCWS56.js");
220
+ const { runUpdate } = await import("./update-GWPF5AS6.js");
219
221
  await runUpdate(pkg.version);
220
222
  });
221
223
  program.command("reset-password").description("Reset a user password (requires auth to be enabled)").requiredOption("-e, --email <email>", "Email address of the user").action(async (options) => {
@@ -227,7 +229,7 @@ program.command("reset-password").description("Reset a user password (requires a
227
229
  process.exit(2);
228
230
  }
229
231
  loadEnvFile(projectDir);
230
- const { resetPassword } = await import("./reset-password-MJ54ICGP.js");
232
+ const { resetPassword } = await import("./reset-password-IZQTDTU7.js");
231
233
  await resetPassword(projectDir, options.email);
232
234
  });
233
235
  program.parse();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { resolve, basename, dirname, join } from 'path';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { validateProject } from './commands/validate.js';\nimport { findProjectRoot, loadEnvFile } from './utils/config.js';\nimport pc from 'picocolors';\nimport * as output from './utils/output.js';\nimport { checkForUpdate } from './utils/update-check.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));\n\nconst program = new Command();\n\nprogram\n .name('yamchart')\n .description('Git-native business intelligence dashboards')\n .version(pkg.version);\n\nprogram\n .command('validate')\n .description('Validate configuration files')\n .argument('[path]', 'Path to yamchart project', '.')\n .option('--dry-run', 'Connect to database and test queries with EXPLAIN')\n .option('-c, --connection <name>', 'Connection to use for dry-run')\n .option('--json', 'Output as JSON')\n .action(async (path: string, options: { dryRun?: boolean; connection?: string; json?: boolean }) => {\n const startPath = resolve(path);\n const projectDir = await findProjectRoot(startPath);\n\n if (!projectDir) {\n if (options.json) {\n console.log(JSON.stringify({ success: false, error: 'yamchart.yaml not found' }));\n } else {\n output.error('yamchart.yaml not found');\n output.detail('Run this command from a yamchart project directory');\n }\n process.exit(2);\n }\n\n // Load .env file\n loadEnvFile(projectDir);\n\n if (!options.json) {\n output.header('Validating yamchart project...');\n }\n\n const result = await validateProject(projectDir, {\n dryRun: options.dryRun ?? false,\n connection: options.connection,\n });\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n // Print results\n for (const error of result.errors) {\n output.error(error.file);\n output.detail(error.message);\n if (error.suggestion) {\n output.detail(error.suggestion);\n }\n }\n\n for (const warning of result.warnings) {\n output.warning(warning.file);\n output.detail(warning.message);\n }\n\n output.newline();\n\n if (result.success) {\n output.success(`Schema: ${result.stats.passed} passed`);\n } else {\n output.error(`Schema: ${result.stats.passed} passed, ${result.stats.failed} failed`);\n }\n\n if (result.dryRunStats) {\n output.newline();\n if (result.dryRunStats.failed === 0) {\n output.success(`Queries: ${result.dryRunStats.passed} passed (EXPLAIN OK)`);\n } else {\n output.error(`Queries: ${result.dryRunStats.passed} passed, ${result.dryRunStats.failed} failed`);\n }\n }\n\n output.newline();\n\n if (result.success) {\n output.success('Validation passed');\n } else {\n output.error(`Validation failed with ${result.errors.length} error(s)`);\n }\n }\n\n process.exit(result.success ? 0 : 1);\n });\n\nprogram\n .command('dev')\n .description('Start development server with hot reload')\n .argument('[path]', 'Path to yamchart project', '.')\n .option('-p, --port <number>', 'Port to listen on', '3001')\n .option('--api-only', 'Only serve API, no web UI')\n .option('--no-open', 'Do not open browser automatically')\n .action(async (path: string, options: { port: string; apiOnly?: boolean; open: boolean }) => {\n const startPath = resolve(path);\n const projectDir = await findProjectRoot(startPath);\n\n if (!projectDir) {\n output.error('yamchart.yaml not found');\n output.detail('Run this command from a yamchart project directory');\n process.exit(2);\n }\n\n const { runDevServer } = await import('./commands/dev.js');\n\n await runDevServer(projectDir, {\n port: parseInt(options.port, 10),\n apiOnly: options.apiOnly ?? false,\n open: options.open,\n });\n });\n\nprogram\n .command('init')\n .description('Create a new yamchart project')\n .argument('[directory]', 'Target directory', '.')\n .option('--example', 'Create full example project with sample database')\n .option('--empty', 'Create only yamchart.yaml (no connections, models, or charts)')\n .option('--force', 'Overwrite existing files')\n .action(async (directory: string, options: { example?: boolean; empty?: boolean; force?: boolean }) => {\n const { initProject } = await import('./commands/init.js');\n const targetDir = resolve(directory);\n\n const result = await initProject(targetDir, options);\n\n if (!result.success) {\n output.error(result.error || 'Failed to create project');\n process.exit(1);\n }\n\n output.newline();\n output.success(`Created ${directory === '.' ? basename(targetDir) : directory}/`);\n for (const file of result.files.slice(0, 10)) {\n output.detail(file);\n }\n if (result.files.length > 10) {\n output.detail(`... and ${result.files.length - 10} more files`);\n }\n output.newline();\n output.info(`Run \\`cd ${directory === '.' ? basename(targetDir) : directory} && yamchart dev\\` to start.`);\n });\n\nprogram\n .command('sync-dbt')\n .description('Sync dbt project metadata into AI-readable catalog')\n .option('-s, --source <type>', 'Source type: local, github, dbt-cloud', 'local')\n .option('-p, --path <dir>', 'Path to dbt project (for local source)')\n .option('--repo <repo>', 'GitHub repository (for github source)')\n .option('--branch <branch>', 'Git branch (for github source)', 'main')\n .option('-i, --include <patterns...>', 'Include glob patterns')\n .option('-e, --exclude <patterns...>', 'Exclude glob patterns')\n .option('-t, --tag <tags...>', 'Filter by dbt tags')\n .option('--refresh', 'Re-sync using saved configuration')\n .action(async (options: {\n source: 'local' | 'github' | 'dbt-cloud';\n path?: string;\n repo?: string;\n branch?: string;\n include?: string[];\n exclude?: string[];\n tag?: string[];\n refresh?: boolean;\n }) => {\n const { syncDbt, loadSyncConfig } = await import('./commands/sync-dbt.js');\n\n // Find project root\n const projectDir = await findProjectRoot(process.cwd());\n\n if (!projectDir) {\n output.error('yamchart.yaml not found');\n output.detail('Run this command from a yamchart project directory');\n process.exit(2);\n }\n\n // Handle refresh mode\n if (options.refresh) {\n const savedConfig = await loadSyncConfig(projectDir);\n if (!savedConfig) {\n output.error('No saved sync config found');\n output.detail('Run sync-dbt without --refresh first');\n process.exit(1);\n }\n output.info(`Re-syncing from ${savedConfig.source}:${savedConfig.path || savedConfig.repo}`);\n }\n\n const spin = output.spinner('Syncing dbt metadata...');\n\n const result = await syncDbt(projectDir, {\n source: options.source,\n path: options.path,\n repo: options.repo,\n branch: options.branch,\n include: options.include || [],\n exclude: options.exclude || [],\n tags: options.tag || [],\n refresh: options.refresh,\n });\n\n spin.stop();\n\n if (!result.success) {\n output.error(result.error || 'Sync failed');\n process.exit(1);\n }\n\n output.success(`Synced ${result.modelsIncluded} models to .yamchart/catalog.md`);\n if (result.modelsExcluded > 0) {\n output.detail(`${result.modelsExcluded} models filtered out`);\n }\n });\n\nprogram\n .command('generate')\n .description('Generate SQL model stubs from dbt catalog')\n .argument('[model]', 'Specific model to generate (optional)')\n .option('--yolo', 'Skip all prompts, use defaults for everything')\n .action(async (model: string | undefined, options: { yolo?: boolean }) => {\n const { generate } = await import('./commands/generate.js');\n\n const projectDir = await findProjectRoot(process.cwd());\n\n if (!projectDir) {\n output.error('yamchart.yaml not found');\n output.detail('Run this command from a yamchart project directory');\n process.exit(2);\n }\n\n const result = await generate(projectDir, {\n model,\n yolo: options.yolo,\n });\n\n if (!result.success) {\n output.error(result.error || 'Generate failed');\n process.exit(1);\n }\n\n output.success(`Generated ${result.filesCreated} model stubs`);\n if (result.filesSkipped > 0) {\n output.detail(`${result.filesSkipped} files skipped`);\n }\n });\n\nprogram\n .command('test')\n .description('Run model tests (@returns schema checks and @tests data assertions)')\n .argument('[model]', 'Specific model to test (optional, tests all if omitted)')\n .option('-c, --connection <name>', 'Connection to use (overrides default)')\n .option('--json', 'Output as JSON')\n .action(async (model: string | undefined, options: { connection?: string; json?: boolean }) => {\n const startPath = resolve('.');\n const projectDir = await findProjectRoot(startPath);\n\n if (!projectDir) {\n if (options.json) {\n console.log(JSON.stringify({ success: false, error: 'yamchart.yaml not found' }));\n } else {\n output.error('yamchart.yaml not found');\n output.detail('Run this command from a yamchart project directory');\n }\n process.exit(2);\n }\n\n loadEnvFile(projectDir);\n\n try {\n const { testProject, formatTestOutput } = await import('./commands/test.js');\n const result = await testProject(projectDir, model, {\n connection: options.connection,\n json: options.json,\n });\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n formatTestOutput(result, result.connectionName);\n }\n\n process.exit(result.success ? 0 : 1);\n } catch (err) {\n if (options.json) {\n console.log(\n JSON.stringify({ success: false, error: err instanceof Error ? err.message : String(err) }),\n );\n } else {\n output.error(err instanceof Error ? err.message : String(err));\n }\n process.exit(2);\n }\n });\n\nprogram\n .command('update')\n .description('Check for yamchart updates')\n .action(async () => {\n const { runUpdate } = await import('./commands/update.js');\n await runUpdate(pkg.version);\n });\n\nprogram\n .command('reset-password')\n .description('Reset a user password (requires auth to be enabled)')\n .requiredOption('-e, --email <email>', 'Email address of the user')\n .action(async (options: { email: string }) => {\n const startPath = resolve('.');\n const projectDir = await findProjectRoot(startPath);\n\n if (!projectDir) {\n output.error('yamchart.yaml not found');\n output.detail('Run this command from a yamchart project directory');\n process.exit(2);\n }\n\n loadEnvFile(projectDir);\n\n const { resetPassword } = await import('./commands/reset-password.js');\n await resetPassword(projectDir, options.email);\n });\n\nprogram.parse();\n\n// Passive update check — runs in background, prints on exit if outdated\nlet updateNotification: string | null = null;\n\ncheckForUpdate(pkg.version).then((update) => {\n if (update) {\n updateNotification = `\\n Update available: ${update.current} → ${update.latest}\\n Run: yamchart update\\n`;\n }\n});\n\nprocess.on('exit', () => {\n if (updateNotification) {\n // Use dim styling so it doesn't compete with command output\n console.error(`\\n${pc.dim(updateNotification)}`);\n }\n});\n"],"mappings":"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","names":["error","warning"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { resolve, basename, dirname, join } from 'path';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { validateProject } from './commands/validate.js';\nimport { findProjectRoot, loadEnvFile } from './utils/config.js';\nimport pc from 'picocolors';\nimport * as output from './utils/output.js';\nimport { checkForUpdate } from './utils/update-check.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));\n\nconst program = new Command();\n\nprogram\n .name('yamchart')\n .description('Git-native business intelligence dashboards')\n .version(pkg.version);\n\nprogram\n .command('validate')\n .description('Validate configuration files')\n .argument('[path]', 'Path to yamchart project', '.')\n .option('--dry-run', 'Connect to database and test queries with EXPLAIN')\n .option('-c, --connection <name>', 'Connection to use for dry-run')\n .option('--json', 'Output as JSON')\n .action(async (path: string, options: { dryRun?: boolean; connection?: string; json?: boolean }) => {\n const startPath = resolve(path);\n const projectDir = await findProjectRoot(startPath);\n\n if (!projectDir) {\n if (options.json) {\n console.log(JSON.stringify({ success: false, error: 'yamchart.yaml not found' }));\n } else {\n output.error('yamchart.yaml not found');\n output.detail('Run this command from a yamchart project directory');\n }\n process.exit(2);\n }\n\n // Load .env file\n loadEnvFile(projectDir);\n\n if (!options.json) {\n output.header('Validating yamchart project...');\n }\n\n const result = await validateProject(projectDir, {\n dryRun: options.dryRun ?? false,\n connection: options.connection,\n });\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n // Print results\n for (const error of result.errors) {\n output.error(error.file);\n output.detail(error.message);\n if (error.suggestion) {\n output.detail(error.suggestion);\n }\n }\n\n for (const warning of result.warnings) {\n output.warning(warning.file);\n output.detail(warning.message);\n }\n\n output.newline();\n\n if (result.success) {\n output.success(`Schema: ${result.stats.passed} passed`);\n } else {\n output.error(`Schema: ${result.stats.passed} passed, ${result.stats.failed} failed`);\n }\n\n if (result.dryRunStats) {\n output.newline();\n if (result.dryRunStats.failed === 0) {\n output.success(`Queries: ${result.dryRunStats.passed} passed (EXPLAIN OK)`);\n } else {\n output.error(`Queries: ${result.dryRunStats.passed} passed, ${result.dryRunStats.failed} failed`);\n }\n }\n\n output.newline();\n\n if (result.success) {\n output.success('Validation passed');\n } else {\n output.error(`Validation failed with ${result.errors.length} error(s)`);\n }\n }\n\n process.exit(result.success ? 0 : 1);\n });\n\nprogram\n .command('dev')\n .description('Start development server with hot reload')\n .argument('[path]', 'Path to yamchart project', '.')\n .option('-p, --port <number>', 'Port to listen on', '3001')\n .option('--api-only', 'Only serve API, no web UI')\n .option('--no-open', 'Do not open browser automatically')\n .action(async (path: string, options: { port: string; apiOnly?: boolean; open: boolean }) => {\n const startPath = resolve(path);\n const projectDir = await findProjectRoot(startPath);\n\n if (!projectDir) {\n output.error('yamchart.yaml not found');\n output.detail('Run this command from a yamchart project directory');\n process.exit(2);\n }\n\n const { runDevServer } = await import('./commands/dev.js');\n\n await runDevServer(projectDir, {\n port: parseInt(options.port, 10),\n apiOnly: options.apiOnly ?? false,\n open: options.open,\n });\n });\n\nprogram\n .command('init')\n .description('Create a new yamchart project')\n .argument('[directory]', 'Target directory', '.')\n .option('--example', 'Create full example project with sample database')\n .option('--empty', 'Create only yamchart.yaml (no connections, models, or charts)')\n .option('--force', 'Overwrite existing files')\n .action(async (directory: string, options: { example?: boolean; empty?: boolean; force?: boolean }) => {\n const { initProject } = await import('./commands/init.js');\n const targetDir = resolve(directory);\n\n const result = await initProject(targetDir, options);\n\n if (!result.success) {\n output.error(result.error || 'Failed to create project');\n process.exit(1);\n }\n\n output.newline();\n output.success(`Created ${directory === '.' ? basename(targetDir) : directory}/`);\n for (const file of result.files.slice(0, 10)) {\n output.detail(file);\n }\n if (result.files.length > 10) {\n output.detail(`... and ${result.files.length - 10} more files`);\n }\n output.newline();\n output.info(`Run \\`cd ${directory === '.' ? basename(targetDir) : directory} && yamchart dev\\` to start.`);\n });\n\nprogram\n .command('sync-dbt')\n .description('Sync dbt project metadata into AI-readable catalog')\n .option('-s, --source <type>', 'Source type: local, github, dbt-cloud', 'local')\n .option('-p, --path <dir>', 'Path to dbt project (for local source)')\n .option('--repo <repo>', 'GitHub repository (for github source)')\n .option('--branch <branch>', 'Git branch (for github source)', 'main')\n .option('-i, --include <patterns...>', 'Include glob patterns')\n .option('-e, --exclude <patterns...>', 'Exclude glob patterns')\n .option('-t, --tag <tags...>', 'Filter by dbt tags')\n .option('--refresh', 'Re-sync using saved configuration')\n .action(async (options: {\n source: 'local' | 'github' | 'dbt-cloud';\n path?: string;\n repo?: string;\n branch?: string;\n include?: string[];\n exclude?: string[];\n tag?: string[];\n refresh?: boolean;\n }) => {\n const { syncDbt, loadSyncConfig } = await import('./commands/sync-dbt.js');\n\n // Find project root\n const projectDir = await findProjectRoot(process.cwd());\n\n if (!projectDir) {\n output.error('yamchart.yaml not found');\n output.detail('Run this command from a yamchart project directory');\n process.exit(2);\n }\n\n // Handle refresh mode\n if (options.refresh) {\n const savedConfig = await loadSyncConfig(projectDir);\n if (!savedConfig) {\n output.error('No saved sync config found');\n output.detail('Run sync-dbt without --refresh first');\n process.exit(1);\n }\n output.info(`Re-syncing from ${savedConfig.source}:${savedConfig.path || savedConfig.repo}`);\n }\n\n const spin = output.spinner('Syncing dbt metadata...');\n\n const result = await syncDbt(projectDir, {\n source: options.source,\n path: options.path,\n repo: options.repo,\n branch: options.branch,\n include: options.include || [],\n exclude: options.exclude || [],\n tags: options.tag || [],\n refresh: options.refresh,\n });\n\n spin.stop();\n\n if (!result.success) {\n output.error(result.error || 'Sync failed');\n process.exit(1);\n }\n\n output.success(`Synced ${result.modelsIncluded} models to .yamchart/catalog.md`);\n if (result.modelsExcluded > 0) {\n output.detail(`${result.modelsExcluded} models filtered out`);\n }\n });\n\nprogram\n .command('generate')\n .description('Generate SQL model stubs from dbt catalog')\n .argument('[model]', 'Specific model to generate (optional)')\n .option('--yolo', 'Skip all prompts, use defaults for everything')\n .action(async (model: string | undefined, options: { yolo?: boolean }) => {\n const { generate } = await import('./commands/generate.js');\n\n const projectDir = await findProjectRoot(process.cwd());\n\n if (!projectDir) {\n output.error('yamchart.yaml not found');\n output.detail('Run this command from a yamchart project directory');\n process.exit(2);\n }\n\n const result = await generate(projectDir, {\n model,\n yolo: options.yolo,\n });\n\n if (!result.success) {\n output.error(result.error || 'Generate failed');\n process.exit(1);\n }\n\n output.success(`Generated ${result.filesCreated} model stubs`);\n if (result.filesSkipped > 0) {\n output.detail(`${result.filesSkipped} files skipped`);\n }\n });\n\nprogram\n .command('test')\n .description('Run model tests (@returns schema checks and @tests data assertions)')\n .argument('[model]', 'Specific model to test (optional, tests all if omitted)')\n .option('-c, --connection <name>', 'Connection to use (overrides default)')\n .option('--json', 'Output as JSON')\n .action(async (model: string | undefined, options: { connection?: string; json?: boolean }) => {\n const startPath = resolve('.');\n const projectDir = await findProjectRoot(startPath);\n\n if (!projectDir) {\n if (options.json) {\n console.log(JSON.stringify({ success: false, error: 'yamchart.yaml not found' }));\n } else {\n output.error('yamchart.yaml not found');\n output.detail('Run this command from a yamchart project directory');\n }\n process.exit(2);\n }\n\n loadEnvFile(projectDir);\n\n try {\n const { testProject, formatTestOutput } = await import('./commands/test.js');\n const result = await testProject(projectDir, model, {\n connection: options.connection,\n json: options.json,\n });\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n formatTestOutput(result, result.connectionName);\n }\n\n process.exit(result.success ? 0 : 1);\n } catch (err) {\n if (options.json) {\n console.log(\n JSON.stringify({ success: false, error: err instanceof Error ? err.message : String(err) }),\n );\n } else {\n output.error(err instanceof Error ? err.message : String(err));\n }\n process.exit(2);\n }\n });\n\nprogram\n .command('update')\n .description('Check for yamchart updates')\n .action(async () => {\n const { runUpdate } = await import('./commands/update.js');\n await runUpdate(pkg.version);\n });\n\nprogram\n .command('reset-password')\n .description('Reset a user password (requires auth to be enabled)')\n .requiredOption('-e, --email <email>', 'Email address of the user')\n .action(async (options: { email: string }) => {\n const startPath = resolve('.');\n const projectDir = await findProjectRoot(startPath);\n\n if (!projectDir) {\n output.error('yamchart.yaml not found');\n output.detail('Run this command from a yamchart project directory');\n process.exit(2);\n }\n\n loadEnvFile(projectDir);\n\n const { resetPassword } = await import('./commands/reset-password.js');\n await resetPassword(projectDir, options.email);\n });\n\nprogram.parse();\n\n// Passive update check — runs in background, prints on exit if outdated\nlet updateNotification: string | null = null;\n\ncheckForUpdate(pkg.version).then((update) => {\n if (update) {\n updateNotification = `\\n Update available: ${update.current} → ${update.latest}\\n Run: yamchart update\\n`;\n }\n});\n\nprocess.on('exit', () => {\n if (updateNotification) {\n // Use dim styling so it doesn't compete with command output\n console.error(`\\n${pc.dim(updateNotification)}`);\n }\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AACA,SAAS,eAAe;AACxB,SAAS,SAAS,UAAU,SAAS,YAAY;AACjD,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAG9B,OAAO,QAAQ;AAIf,IAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AACxD,IAAM,MAAM,KAAK,MAAM,aAAa,KAAK,WAAW,iBAAiB,GAAG,OAAO,CAAC;AAEhF,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,UAAU,EACf,YAAY,6CAA6C,EACzD,QAAQ,IAAI,OAAO;AAEtB,QACG,QAAQ,UAAU,EAClB,YAAY,8BAA8B,EAC1C,SAAS,UAAU,4BAA4B,GAAG,EAClD,OAAO,aAAa,mDAAmD,EACvE,OAAO,2BAA2B,+BAA+B,EACjE,OAAO,UAAU,gBAAgB,EACjC,OAAO,OAAO,MAAc,YAAuE;AAClG,QAAM,YAAY,QAAQ,IAAI;AAC9B,QAAM,aAAa,MAAM,gBAAgB,SAAS;AAElD,MAAI,CAAC,YAAY;AACf,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,0BAA0B,CAAC,CAAC;AAAA,IAClF,OAAO;AACL,MAAO,MAAM,yBAAyB;AACtC,MAAO,OAAO,oDAAoD;AAAA,IACpE;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,cAAY,UAAU;AAEtB,MAAI,CAAC,QAAQ,MAAM;AACjB,IAAO,OAAO,gCAAgC;AAAA,EAChD;AAEA,QAAM,SAAS,MAAM,gBAAgB,YAAY;AAAA,IAC/C,QAAQ,QAAQ,UAAU;AAAA,IAC1B,YAAY,QAAQ;AAAA,EACtB,CAAC;AAED,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,EAC7C,OAAO;AAEL,eAAWA,UAAS,OAAO,QAAQ;AACjC,MAAO,MAAMA,OAAM,IAAI;AACvB,MAAO,OAAOA,OAAM,OAAO;AAC3B,UAAIA,OAAM,YAAY;AACpB,QAAO,OAAOA,OAAM,UAAU;AAAA,MAChC;AAAA,IACF;AAEA,eAAWC,YAAW,OAAO,UAAU;AACrC,MAAO,QAAQA,SAAQ,IAAI;AAC3B,MAAO,OAAOA,SAAQ,OAAO;AAAA,IAC/B;AAEA,IAAO,QAAQ;AAEf,QAAI,OAAO,SAAS;AAClB,MAAO,QAAQ,WAAW,OAAO,MAAM,MAAM,SAAS;AAAA,IACxD,OAAO;AACL,MAAO,MAAM,WAAW,OAAO,MAAM,MAAM,YAAY,OAAO,MAAM,MAAM,SAAS;AAAA,IACrF;AAEA,QAAI,OAAO,aAAa;AACtB,MAAO,QAAQ;AACf,UAAI,OAAO,YAAY,WAAW,GAAG;AACnC,QAAO,QAAQ,YAAY,OAAO,YAAY,MAAM,sBAAsB;AAAA,MAC5E,OAAO;AACL,QAAO,MAAM,YAAY,OAAO,YAAY,MAAM,YAAY,OAAO,YAAY,MAAM,SAAS;AAAA,MAClG;AAAA,IACF;AAEA,IAAO,QAAQ;AAEf,QAAI,OAAO,SAAS;AAClB,MAAO,QAAQ,mBAAmB;AAAA,IACpC,OAAO;AACL,MAAO,MAAM,0BAA0B,OAAO,OAAO,MAAM,WAAW;AAAA,IACxE;AAAA,EACF;AAEA,UAAQ,KAAK,OAAO,UAAU,IAAI,CAAC;AACrC,CAAC;AAEH,QACG,QAAQ,KAAK,EACb,YAAY,0CAA0C,EACtD,SAAS,UAAU,4BAA4B,GAAG,EAClD,OAAO,uBAAuB,qBAAqB,MAAM,EACzD,OAAO,cAAc,2BAA2B,EAChD,OAAO,aAAa,mCAAmC,EACvD,OAAO,OAAO,MAAc,YAAgE;AAC3F,QAAM,YAAY,QAAQ,IAAI;AAC9B,QAAM,aAAa,MAAM,gBAAgB,SAAS;AAElD,MAAI,CAAC,YAAY;AACf,IAAO,MAAM,yBAAyB;AACtC,IAAO,OAAO,oDAAoD;AAClE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,EAAE,aAAa,IAAI,MAAM,OAAO,mBAAmB;AAEzD,QAAM,aAAa,YAAY;AAAA,IAC7B,MAAM,SAAS,QAAQ,MAAM,EAAE;AAAA,IAC/B,SAAS,QAAQ,WAAW;AAAA,IAC5B,MAAM,QAAQ;AAAA,EAChB,CAAC;AACH,CAAC;AAEH,QACG,QAAQ,MAAM,EACd,YAAY,+BAA+B,EAC3C,SAAS,eAAe,oBAAoB,GAAG,EAC/C,OAAO,aAAa,kDAAkD,EACtE,OAAO,WAAW,+DAA+D,EACjF,OAAO,WAAW,0BAA0B,EAC5C,OAAO,OAAO,WAAmB,YAAqE;AACrG,QAAM,EAAE,YAAY,IAAI,MAAM,OAAO,oBAAoB;AACzD,QAAM,YAAY,QAAQ,SAAS;AAEnC,QAAM,SAAS,MAAM,YAAY,WAAW,OAAO;AAEnD,MAAI,CAAC,OAAO,SAAS;AACnB,IAAO,MAAM,OAAO,SAAS,0BAA0B;AACvD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,EAAO,QAAQ;AACf,EAAO,QAAQ,WAAW,cAAc,MAAM,SAAS,SAAS,IAAI,SAAS,GAAG;AAChF,aAAW,QAAQ,OAAO,MAAM,MAAM,GAAG,EAAE,GAAG;AAC5C,IAAO,OAAO,IAAI;AAAA,EACpB;AACA,MAAI,OAAO,MAAM,SAAS,IAAI;AAC5B,IAAO,OAAO,WAAW,OAAO,MAAM,SAAS,EAAE,aAAa;AAAA,EAChE;AACA,EAAO,QAAQ;AACf,EAAO,KAAK,YAAY,cAAc,MAAM,SAAS,SAAS,IAAI,SAAS,8BAA8B;AAC3G,CAAC;AAEH,QACG,QAAQ,UAAU,EAClB,YAAY,oDAAoD,EAChE,OAAO,uBAAuB,yCAAyC,OAAO,EAC9E,OAAO,oBAAoB,wCAAwC,EACnE,OAAO,iBAAiB,uCAAuC,EAC/D,OAAO,qBAAqB,kCAAkC,MAAM,EACpE,OAAO,+BAA+B,uBAAuB,EAC7D,OAAO,+BAA+B,uBAAuB,EAC7D,OAAO,uBAAuB,oBAAoB,EAClD,OAAO,aAAa,mCAAmC,EACvD,OAAO,OAAO,YAST;AACJ,QAAM,EAAE,SAAS,eAAe,IAAI,MAAM,OAAO,wBAAwB;AAGzE,QAAM,aAAa,MAAM,gBAAgB,QAAQ,IAAI,CAAC;AAEtD,MAAI,CAAC,YAAY;AACf,IAAO,MAAM,yBAAyB;AACtC,IAAO,OAAO,oDAAoD;AAClE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,QAAQ,SAAS;AACnB,UAAM,cAAc,MAAM,eAAe,UAAU;AACnD,QAAI,CAAC,aAAa;AAChB,MAAO,MAAM,4BAA4B;AACzC,MAAO,OAAO,sCAAsC;AACpD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,IAAO,KAAK,mBAAmB,YAAY,MAAM,IAAI,YAAY,QAAQ,YAAY,IAAI,EAAE;AAAA,EAC7F;AAEA,QAAM,OAAc,QAAQ,yBAAyB;AAErD,QAAM,SAAS,MAAM,QAAQ,YAAY;AAAA,IACvC,QAAQ,QAAQ;AAAA,IAChB,MAAM,QAAQ;AAAA,IACd,MAAM,QAAQ;AAAA,IACd,QAAQ,QAAQ;AAAA,IAChB,SAAS,QAAQ,WAAW,CAAC;AAAA,IAC7B,SAAS,QAAQ,WAAW,CAAC;AAAA,IAC7B,MAAM,QAAQ,OAAO,CAAC;AAAA,IACtB,SAAS,QAAQ;AAAA,EACnB,CAAC;AAED,OAAK,KAAK;AAEV,MAAI,CAAC,OAAO,SAAS;AACnB,IAAO,MAAM,OAAO,SAAS,aAAa;AAC1C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,EAAO,QAAQ,UAAU,OAAO,cAAc,iCAAiC;AAC/E,MAAI,OAAO,iBAAiB,GAAG;AAC7B,IAAO,OAAO,GAAG,OAAO,cAAc,sBAAsB;AAAA,EAC9D;AACF,CAAC;AAEH,QACG,QAAQ,UAAU,EAClB,YAAY,2CAA2C,EACvD,SAAS,WAAW,uCAAuC,EAC3D,OAAO,UAAU,+CAA+C,EAChE,OAAO,OAAO,OAA2B,YAAgC;AACxE,QAAM,EAAE,SAAS,IAAI,MAAM,OAAO,wBAAwB;AAE1D,QAAM,aAAa,MAAM,gBAAgB,QAAQ,IAAI,CAAC;AAEtD,MAAI,CAAC,YAAY;AACf,IAAO,MAAM,yBAAyB;AACtC,IAAO,OAAO,oDAAoD;AAClE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,MAAM,SAAS,YAAY;AAAA,IACxC;AAAA,IACA,MAAM,QAAQ;AAAA,EAChB,CAAC;AAED,MAAI,CAAC,OAAO,SAAS;AACnB,IAAO,MAAM,OAAO,SAAS,iBAAiB;AAC9C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,EAAO,QAAQ,aAAa,OAAO,YAAY,cAAc;AAC7D,MAAI,OAAO,eAAe,GAAG;AAC3B,IAAO,OAAO,GAAG,OAAO,YAAY,gBAAgB;AAAA,EACtD;AACF,CAAC;AAEH,QACG,QAAQ,MAAM,EACd,YAAY,qEAAqE,EACjF,SAAS,WAAW,yDAAyD,EAC7E,OAAO,2BAA2B,uCAAuC,EACzE,OAAO,UAAU,gBAAgB,EACjC,OAAO,OAAO,OAA2B,YAAqD;AAC7F,QAAM,YAAY,QAAQ,GAAG;AAC7B,QAAM,aAAa,MAAM,gBAAgB,SAAS;AAElD,MAAI,CAAC,YAAY;AACf,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,0BAA0B,CAAC,CAAC;AAAA,IAClF,OAAO;AACL,MAAO,MAAM,yBAAyB;AACtC,MAAO,OAAO,oDAAoD;AAAA,IACpE;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,cAAY,UAAU;AAEtB,MAAI;AACF,UAAM,EAAE,aAAa,iBAAiB,IAAI,MAAM,OAAO,oBAAoB;AAC3E,UAAM,SAAS,MAAM,YAAY,YAAY,OAAO;AAAA,MAClD,YAAY,QAAQ;AAAA,MACpB,MAAM,QAAQ;AAAA,IAChB,CAAC;AAED,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,IAC7C,OAAO;AACL,uBAAiB,QAAQ,OAAO,cAAc;AAAA,IAChD;AAEA,YAAQ,KAAK,OAAO,UAAU,IAAI,CAAC;AAAA,EACrC,SAAS,KAAK;AACZ,QAAI,QAAQ,MAAM;AAChB,cAAQ;AAAA,QACN,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,MAC5F;AAAA,IACF,OAAO;AACL,MAAO,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC/D;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,QACG,QAAQ,QAAQ,EAChB,YAAY,4BAA4B,EACxC,OAAO,YAAY;AAClB,QAAM,EAAE,UAAU,IAAI,MAAM,OAAO,sBAAsB;AACzD,QAAM,UAAU,IAAI,OAAO;AAC7B,CAAC;AAEH,QACG,QAAQ,gBAAgB,EACxB,YAAY,qDAAqD,EACjE,eAAe,uBAAuB,2BAA2B,EACjE,OAAO,OAAO,YAA+B;AAC5C,QAAM,YAAY,QAAQ,GAAG;AAC7B,QAAM,aAAa,MAAM,gBAAgB,SAAS;AAElD,MAAI,CAAC,YAAY;AACf,IAAO,MAAM,yBAAyB;AACtC,IAAO,OAAO,oDAAoD;AAClE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,cAAY,UAAU;AAEtB,QAAM,EAAE,cAAc,IAAI,MAAM,OAAO,8BAA8B;AACrE,QAAM,cAAc,YAAY,QAAQ,KAAK;AAC/C,CAAC;AAEH,QAAQ,MAAM;AAGd,IAAI,qBAAoC;AAExC,eAAe,IAAI,OAAO,EAAE,KAAK,CAAC,WAAW;AAC3C,MAAI,QAAQ;AACV,yBAAqB;AAAA,sBAAyB,OAAO,OAAO,WAAM,OAAO,MAAM;AAAA;AAAA;AAAA,EACjF;AACF,CAAC;AAED,QAAQ,GAAG,QAAQ,MAAM;AACvB,MAAI,oBAAoB;AAEtB,YAAQ,MAAM;AAAA,EAAK,GAAG,IAAI,kBAAkB,CAAC,EAAE;AAAA,EACjD;AACF,CAAC;","names":["error","warning"]}
@@ -1,3 +1,5 @@
1
+ import "./chunk-DGUM43GV.js";
2
+
1
3
  // src/commands/init.ts
2
4
  import { mkdir, readFile, writeFile, access, readdir, copyFile } from "fs/promises";
3
5
  import { join, dirname, basename } from "path";
@@ -115,4 +117,4 @@ async function copyDirectory(srcDir, destDir, files, projectName, basePath = "")
115
117
  export {
116
118
  initProject
117
119
  };
118
- //# sourceMappingURL=init-6D5VNGSP.js.map
120
+ //# sourceMappingURL=init-FTSEOTAD.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/init.ts"],"sourcesContent":["import { mkdir, readFile, writeFile, access, readdir, copyFile } from 'fs/promises';\nimport { join, dirname, basename } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport interface InitOptions {\n empty?: boolean;\n example?: boolean;\n force?: boolean;\n}\n\nexport interface InitResult {\n success: boolean;\n files: string[];\n error?: string;\n}\n\n/**\n * Check if a directory exists and is accessible.\n */\nasync function directoryExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the templates directory path.\n * Handles both development (src/commands) and production (dist/) contexts.\n */\nasync function getTemplatesDir(): Promise<string> {\n // In production (dist/), templates are at dist/templates\n const distTemplates = join(__dirname, 'templates');\n if (await directoryExists(distTemplates)) {\n return distTemplates;\n }\n\n // In development (src/commands), templates are at src/templates\n const srcTemplates = join(__dirname, '../templates');\n if (await directoryExists(srcTemplates)) {\n return srcTemplates;\n }\n\n throw new Error('Templates not found. Reinstall yamchart or check installation.');\n}\n\n/**\n * Get the examples directory path.\n * Handles both development and production contexts.\n */\nasync function getExamplesDir(): Promise<string> {\n // In production (dist/): dist -> cli -> apps -> yamchart -> examples\n const distExamples = join(__dirname, '../../../examples');\n if (await directoryExists(distExamples)) {\n return distExamples;\n }\n\n // In development (src/commands): src/commands -> src -> cli -> apps -> yamchart -> examples\n const srcExamples = join(__dirname, '../../../../examples');\n if (await directoryExists(srcExamples)) {\n return srcExamples;\n }\n\n throw new Error('Example assets not found. Reinstall yamchart or use default mode.');\n}\n\nexport async function initProject(projectDir: string, options: InitOptions): Promise<InitResult> {\n const projectName = basename(projectDir);\n const files: string[] = [];\n\n // Check if yamchart.yaml already exists\n const yamchartYamlPath = join(projectDir, 'yamchart.yaml');\n try {\n await access(yamchartYamlPath);\n if (!options.force) {\n return {\n success: false,\n files: [],\n error: `${yamchartYamlPath} already exists. Use --force to overwrite.`,\n };\n }\n } catch {\n // File doesn't exist, continue\n }\n\n // Create project directory\n await mkdir(projectDir, { recursive: true });\n\n try {\n if (options.example) {\n // Copy example project\n const examplesDir = await getExamplesDir();\n await copyDirectory(examplesDir, projectDir, files, projectName);\n } else if (options.empty) {\n // Empty mode - only yamchart.yaml\n const templateDir = join(await getTemplatesDir(), 'empty');\n await copyTemplate(templateDir, projectDir, files, projectName);\n } else {\n // Default mode - minimal working project\n const templateDir = join(await getTemplatesDir(), 'default');\n await copyTemplate(templateDir, projectDir, files, projectName);\n }\n } catch (err) {\n return {\n success: false,\n files: [],\n error: err instanceof Error ? err.message : 'Failed to create project',\n };\n }\n\n return { success: true, files };\n}\n\nasync function copyTemplate(\n templateDir: string,\n targetDir: string,\n files: string[],\n projectName: string,\n basePath: string = ''\n): Promise<void> {\n const entries = await readdir(templateDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = join(templateDir, entry.name);\n const destPath = join(targetDir, entry.name);\n const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;\n\n if (entry.isDirectory()) {\n await mkdir(destPath, { recursive: true });\n await copyTemplate(srcPath, destPath, files, projectName, relativePath);\n } else {\n let content = await readFile(srcPath, 'utf-8');\n content = content.replace(/\\{\\{name\\}\\}/g, projectName);\n await writeFile(destPath, content, 'utf-8');\n files.push(relativePath);\n }\n }\n}\n\nasync function copyDirectory(\n srcDir: string,\n destDir: string,\n files: string[],\n projectName: string,\n basePath: string = ''\n): Promise<void> {\n const entries = await readdir(srcDir, { withFileTypes: true });\n\n for (const entry of entries) {\n // Skip node_modules, lock files, and hidden files\n if (\n entry.name === 'node_modules' ||\n entry.name === 'pnpm-lock.yaml' ||\n entry.name === 'package-lock.json' ||\n entry.name === 'yarn.lock' ||\n entry.name === 'package.json' ||\n entry.name.startsWith('.')\n ) {\n continue;\n }\n\n const srcPath = join(srcDir, entry.name);\n const destPath = join(destDir, entry.name);\n const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;\n\n if (entry.isDirectory()) {\n await mkdir(destPath, { recursive: true });\n await copyDirectory(srcPath, destPath, files, projectName, relativePath);\n } else {\n // For binary files (like .duckdb), copy directly\n if (entry.name.endsWith('.duckdb')) {\n await copyFile(srcPath, destPath);\n } else {\n // For text files, replace project name in yamchart.yaml\n let content = await readFile(srcPath, 'utf-8');\n if (entry.name === 'yamchart.yaml') {\n content = content.replace(/^name:\\s*\\S+/m, `name: ${projectName}`);\n }\n await writeFile(destPath, content, 'utf-8');\n }\n files.push(relativePath);\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/init.ts"],"sourcesContent":["import { mkdir, readFile, writeFile, access, readdir, copyFile } from 'fs/promises';\nimport { join, dirname, basename } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport interface InitOptions {\n empty?: boolean;\n example?: boolean;\n force?: boolean;\n}\n\nexport interface InitResult {\n success: boolean;\n files: string[];\n error?: string;\n}\n\n/**\n * Check if a directory exists and is accessible.\n */\nasync function directoryExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the templates directory path.\n * Handles both development (src/commands) and production (dist/) contexts.\n */\nasync function getTemplatesDir(): Promise<string> {\n // In production (dist/), templates are at dist/templates\n const distTemplates = join(__dirname, 'templates');\n if (await directoryExists(distTemplates)) {\n return distTemplates;\n }\n\n // In development (src/commands), templates are at src/templates\n const srcTemplates = join(__dirname, '../templates');\n if (await directoryExists(srcTemplates)) {\n return srcTemplates;\n }\n\n throw new Error('Templates not found. Reinstall yamchart or check installation.');\n}\n\n/**\n * Get the examples directory path.\n * Handles both development and production contexts.\n */\nasync function getExamplesDir(): Promise<string> {\n // In production (dist/): dist -> cli -> apps -> yamchart -> examples\n const distExamples = join(__dirname, '../../../examples');\n if (await directoryExists(distExamples)) {\n return distExamples;\n }\n\n // In development (src/commands): src/commands -> src -> cli -> apps -> yamchart -> examples\n const srcExamples = join(__dirname, '../../../../examples');\n if (await directoryExists(srcExamples)) {\n return srcExamples;\n }\n\n throw new Error('Example assets not found. Reinstall yamchart or use default mode.');\n}\n\nexport async function initProject(projectDir: string, options: InitOptions): Promise<InitResult> {\n const projectName = basename(projectDir);\n const files: string[] = [];\n\n // Check if yamchart.yaml already exists\n const yamchartYamlPath = join(projectDir, 'yamchart.yaml');\n try {\n await access(yamchartYamlPath);\n if (!options.force) {\n return {\n success: false,\n files: [],\n error: `${yamchartYamlPath} already exists. Use --force to overwrite.`,\n };\n }\n } catch {\n // File doesn't exist, continue\n }\n\n // Create project directory\n await mkdir(projectDir, { recursive: true });\n\n try {\n if (options.example) {\n // Copy example project\n const examplesDir = await getExamplesDir();\n await copyDirectory(examplesDir, projectDir, files, projectName);\n } else if (options.empty) {\n // Empty mode - only yamchart.yaml\n const templateDir = join(await getTemplatesDir(), 'empty');\n await copyTemplate(templateDir, projectDir, files, projectName);\n } else {\n // Default mode - minimal working project\n const templateDir = join(await getTemplatesDir(), 'default');\n await copyTemplate(templateDir, projectDir, files, projectName);\n }\n } catch (err) {\n return {\n success: false,\n files: [],\n error: err instanceof Error ? err.message : 'Failed to create project',\n };\n }\n\n return { success: true, files };\n}\n\nasync function copyTemplate(\n templateDir: string,\n targetDir: string,\n files: string[],\n projectName: string,\n basePath: string = ''\n): Promise<void> {\n const entries = await readdir(templateDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = join(templateDir, entry.name);\n const destPath = join(targetDir, entry.name);\n const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;\n\n if (entry.isDirectory()) {\n await mkdir(destPath, { recursive: true });\n await copyTemplate(srcPath, destPath, files, projectName, relativePath);\n } else {\n let content = await readFile(srcPath, 'utf-8');\n content = content.replace(/\\{\\{name\\}\\}/g, projectName);\n await writeFile(destPath, content, 'utf-8');\n files.push(relativePath);\n }\n }\n}\n\nasync function copyDirectory(\n srcDir: string,\n destDir: string,\n files: string[],\n projectName: string,\n basePath: string = ''\n): Promise<void> {\n const entries = await readdir(srcDir, { withFileTypes: true });\n\n for (const entry of entries) {\n // Skip node_modules, lock files, and hidden files\n if (\n entry.name === 'node_modules' ||\n entry.name === 'pnpm-lock.yaml' ||\n entry.name === 'package-lock.json' ||\n entry.name === 'yarn.lock' ||\n entry.name === 'package.json' ||\n entry.name.startsWith('.')\n ) {\n continue;\n }\n\n const srcPath = join(srcDir, entry.name);\n const destPath = join(destDir, entry.name);\n const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;\n\n if (entry.isDirectory()) {\n await mkdir(destPath, { recursive: true });\n await copyDirectory(srcPath, destPath, files, projectName, relativePath);\n } else {\n // For binary files (like .duckdb), copy directly\n if (entry.name.endsWith('.duckdb')) {\n await copyFile(srcPath, destPath);\n } else {\n // For text files, replace project name in yamchart.yaml\n let content = await readFile(srcPath, 'utf-8');\n if (entry.name === 'yamchart.yaml') {\n content = content.replace(/^name:\\s*\\S+/m, `name: ${projectName}`);\n }\n await writeFile(destPath, content, 'utf-8');\n }\n files.push(relativePath);\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -5,13 +5,14 @@ import {
5
5
  newline,
6
6
  success
7
7
  } from "./chunk-HJVVHYVN.js";
8
+ import "./chunk-DGUM43GV.js";
8
9
 
9
10
  // src/commands/reset-password.ts
10
11
  import { resolve } from "path";
11
12
  import { homedir } from "os";
12
13
  import { randomBytes } from "crypto";
13
14
  async function resetPassword(projectDir, email) {
14
- const { AuthDatabase, hashPassword } = await import("@yamchart/auth-local");
15
+ const { AuthDatabase, hashPassword } = await import("./dist-JH7OL7U4.js");
15
16
  const { readFileSync } = await import("fs");
16
17
  const { parse } = await import("yaml");
17
18
  const projectPath = resolve(projectDir, "yamchart.yaml");
@@ -56,4 +57,4 @@ async function resetPassword(projectDir, email) {
56
57
  export {
57
58
  resetPassword
58
59
  };
59
- //# sourceMappingURL=reset-password-MJ54ICGP.js.map
60
+ //# sourceMappingURL=reset-password-IZQTDTU7.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/reset-password.ts"],"sourcesContent":["import { resolve } from 'path';\nimport { homedir } from 'os';\nimport { randomBytes } from 'crypto';\nimport * as output from '../utils/output.js';\n\nexport async function resetPassword(projectDir: string, email: string): Promise<void> {\n // Dynamic import to avoid loading better-sqlite3 unless needed\n const { AuthDatabase, hashPassword } = await import('@yamchart/auth-local');\n\n // Read project config to find auth db path\n const { readFileSync } = await import('fs');\n const { parse } = await import('yaml');\n\n const projectPath = resolve(projectDir, 'yamchart.yaml');\n let dbPath: string;\n\n try {\n const raw = readFileSync(projectPath, 'utf-8');\n const project = parse(raw);\n if (!project.auth?.enabled) {\n output.error('Auth is not enabled in this project');\n output.detail('Add \"auth: { enabled: true }\" to yamchart.yaml');\n process.exit(1);\n }\n dbPath = project.auth.db_path\n ? resolve(project.auth.db_path.replace(/^~/, homedir()))\n : resolve(homedir(), '.yamchart', 'auth.db');\n } catch {\n output.error('Could not read yamchart.yaml');\n process.exit(1);\n }\n\n let db: InstanceType<typeof AuthDatabase>;\n try {\n db = new AuthDatabase(dbPath);\n } catch {\n output.error(`Could not open auth database at ${dbPath}`);\n process.exit(1);\n }\n\n const user = db.getUserByEmail(email);\n if (!user) {\n db.close();\n output.error(`No user found with email: ${email}`);\n process.exit(1);\n }\n\n const tempPassword = randomBytes(12).toString('base64url');\n const hash = await hashPassword(tempPassword);\n db.updateUser(user.id, { password_hash: hash });\n db.close();\n\n output.newline();\n output.success(`Password reset for ${email}`);\n output.newline();\n output.info(`Temporary password: ${tempPassword}`);\n output.detail('The user should change this password after logging in.');\n output.newline();\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,eAAe;AACxB,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAG5B,eAAsB,cAAc,YAAoB,OAA8B;AAEpF,QAAM,EAAE,cAAc,aAAa,IAAI,MAAM,OAAO,sBAAsB;AAG1E,QAAM,EAAE,aAAa,IAAI,MAAM,OAAO,IAAI;AAC1C,QAAM,EAAE,MAAM,IAAI,MAAM,OAAO,MAAM;AAErC,QAAM,cAAc,QAAQ,YAAY,eAAe;AACvD,MAAI;AAEJ,MAAI;AACF,UAAM,MAAM,aAAa,aAAa,OAAO;AAC7C,UAAM,UAAU,MAAM,GAAG;AACzB,QAAI,CAAC,QAAQ,MAAM,SAAS;AAC1B,MAAO,MAAM,qCAAqC;AAClD,MAAO,OAAO,gDAAgD;AAC9D,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,aAAS,QAAQ,KAAK,UAClB,QAAQ,QAAQ,KAAK,QAAQ,QAAQ,MAAM,QAAQ,CAAC,CAAC,IACrD,QAAQ,QAAQ,GAAG,aAAa,SAAS;AAAA,EAC/C,QAAQ;AACN,IAAO,MAAM,8BAA8B;AAC3C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI;AACJ,MAAI;AACF,SAAK,IAAI,aAAa,MAAM;AAAA,EAC9B,QAAQ;AACN,IAAO,MAAM,mCAAmC,MAAM,EAAE;AACxD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,OAAO,GAAG,eAAe,KAAK;AACpC,MAAI,CAAC,MAAM;AACT,OAAG,MAAM;AACT,IAAO,MAAM,6BAA6B,KAAK,EAAE;AACjD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,eAAe,YAAY,EAAE,EAAE,SAAS,WAAW;AACzD,QAAM,OAAO,MAAM,aAAa,YAAY;AAC5C,KAAG,WAAW,KAAK,IAAI,EAAE,eAAe,KAAK,CAAC;AAC9C,KAAG,MAAM;AAET,EAAO,QAAQ;AACf,EAAO,QAAQ,sBAAsB,KAAK,EAAE;AAC5C,EAAO,QAAQ;AACf,EAAO,KAAK,uBAAuB,YAAY,EAAE;AACjD,EAAO,OAAO,wDAAwD;AACtE,EAAO,QAAQ;AACjB;","names":[]}
1
+ {"version":3,"sources":["../src/commands/reset-password.ts"],"sourcesContent":["import { resolve } from 'path';\nimport { homedir } from 'os';\nimport { randomBytes } from 'crypto';\nimport * as output from '../utils/output.js';\n\nexport async function resetPassword(projectDir: string, email: string): Promise<void> {\n // Dynamic import to avoid loading better-sqlite3 unless needed\n const { AuthDatabase, hashPassword } = await import('@yamchart/auth-local');\n\n // Read project config to find auth db path\n const { readFileSync } = await import('fs');\n const { parse } = await import('yaml');\n\n const projectPath = resolve(projectDir, 'yamchart.yaml');\n let dbPath: string;\n\n try {\n const raw = readFileSync(projectPath, 'utf-8');\n const project = parse(raw);\n if (!project.auth?.enabled) {\n output.error('Auth is not enabled in this project');\n output.detail('Add \"auth: { enabled: true }\" to yamchart.yaml');\n process.exit(1);\n }\n dbPath = project.auth.db_path\n ? resolve(project.auth.db_path.replace(/^~/, homedir()))\n : resolve(homedir(), '.yamchart', 'auth.db');\n } catch {\n output.error('Could not read yamchart.yaml');\n process.exit(1);\n }\n\n let db: InstanceType<typeof AuthDatabase>;\n try {\n db = new AuthDatabase(dbPath);\n } catch {\n output.error(`Could not open auth database at ${dbPath}`);\n process.exit(1);\n }\n\n const user = db.getUserByEmail(email);\n if (!user) {\n db.close();\n output.error(`No user found with email: ${email}`);\n process.exit(1);\n }\n\n const tempPassword = randomBytes(12).toString('base64url');\n const hash = await hashPassword(tempPassword);\n db.updateUser(user.id, { password_hash: hash });\n db.close();\n\n output.newline();\n output.success(`Password reset for ${email}`);\n output.newline();\n output.info(`Temporary password: ${tempPassword}`);\n output.detail('The user should change this password after logging in.');\n output.newline();\n}\n"],"mappings":";;;;;;;;;;AAAA,SAAS,eAAe;AACxB,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAG5B,eAAsB,cAAc,YAAoB,OAA8B;AAEpF,QAAM,EAAE,cAAc,aAAa,IAAI,MAAM,OAAO,oBAAsB;AAG1E,QAAM,EAAE,aAAa,IAAI,MAAM,OAAO,IAAI;AAC1C,QAAM,EAAE,MAAM,IAAI,MAAM,OAAO,MAAM;AAErC,QAAM,cAAc,QAAQ,YAAY,eAAe;AACvD,MAAI;AAEJ,MAAI;AACF,UAAM,MAAM,aAAa,aAAa,OAAO;AAC7C,UAAM,UAAU,MAAM,GAAG;AACzB,QAAI,CAAC,QAAQ,MAAM,SAAS;AAC1B,MAAO,MAAM,qCAAqC;AAClD,MAAO,OAAO,gDAAgD;AAC9D,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,aAAS,QAAQ,KAAK,UAClB,QAAQ,QAAQ,KAAK,QAAQ,QAAQ,MAAM,QAAQ,CAAC,CAAC,IACrD,QAAQ,QAAQ,GAAG,aAAa,SAAS;AAAA,EAC/C,QAAQ;AACN,IAAO,MAAM,8BAA8B;AAC3C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI;AACJ,MAAI;AACF,SAAK,IAAI,aAAa,MAAM;AAAA,EAC9B,QAAQ;AACN,IAAO,MAAM,mCAAmC,MAAM,EAAE;AACxD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,OAAO,GAAG,eAAe,KAAK;AACpC,MAAI,CAAC,MAAM;AACT,OAAG,MAAM;AACT,IAAO,MAAM,6BAA6B,KAAK,EAAE;AACjD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,eAAe,YAAY,EAAE,EAAE,SAAS,WAAW;AACzD,QAAM,OAAO,MAAM,aAAa,YAAY;AAC5C,KAAG,WAAW,KAAK,IAAI,EAAE,eAAe,KAAK,CAAC;AAC9C,KAAG,MAAM;AAET,EAAO,QAAQ;AACf,EAAO,QAAQ,sBAAsB,KAAK,EAAE;AAC5C,EAAO,QAAQ;AACf,EAAO,KAAK,uBAAuB,YAAY,EAAE;AACjD,EAAO,OAAO,wDAAwD;AACtE,EAAO,QAAQ;AACjB;","names":[]}
@@ -1,3 +1,5 @@
1
+ import "./chunk-DGUM43GV.js";
2
+
1
3
  // src/commands/sync-dbt.ts
2
4
  import { mkdir, writeFile, readFile as readFile3, access as access2 } from "fs/promises";
3
5
  import { join as join4 } from "path";
@@ -463,4 +465,4 @@ export {
463
465
  loadSyncConfig,
464
466
  syncDbt
465
467
  };
466
- //# sourceMappingURL=sync-dbt-IDDD4X2Z.js.map
468
+ //# sourceMappingURL=sync-dbt-6WY7HKP7.js.map