yamchart 0.8.1 → 0.8.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.
- package/dist/{advisor-57BOMUUF.js → advisor-JMWAAWJO.js} +10 -10
- package/dist/chunk-4W6IVOKO.js +362 -0
- package/dist/chunk-4W6IVOKO.js.map +1 -0
- package/dist/{chunk-JYQKDWLG.js → chunk-5N3FYFBV.js} +72 -1
- package/dist/chunk-5N3FYFBV.js.map +1 -0
- package/dist/{chunk-OTAUP5RC.js → chunk-7AVPKKYY.js} +5 -5
- package/dist/chunk-7AVPKKYY.js.map +1 -0
- package/dist/{chunk-X6LQGWUX.js → chunk-KP4CYPBL.js} +9 -2
- package/dist/chunk-KP4CYPBL.js.map +1 -0
- package/dist/{chunk-E2UZXDF6.js → chunk-N6PUISAQ.js} +4 -4
- package/dist/compare-ZN6RUOOQ.js +87 -0
- package/dist/compare-ZN6RUOOQ.js.map +1 -0
- package/dist/{connection-utils-FTSZU2VF.js → connection-utils-VEKXRCOM.js} +4 -4
- package/dist/describe-X55JPLES.js +29 -0
- package/dist/describe-X55JPLES.js.map +1 -0
- package/dist/{dev-MRZ76V74.js → dev-NZLS72PG.js} +9 -7
- package/dist/dev-NZLS72PG.js.map +1 -0
- package/dist/{dist-PVHFUYP2.js → dist-E2PVGIPT.js} +4 -2
- package/dist/{dist-WDTDQDTX.js → dist-GVNWQXFR.js} +2 -2
- package/dist/index.js +314 -32
- package/dist/index.js.map +1 -1
- package/dist/{lineage-XSITWW2O.js → lineage-T5NRHHZN.js} +32 -5
- package/dist/{lineage-XSITWW2O.js.map → lineage-T5NRHHZN.js.map} +1 -1
- package/dist/public/assets/{EventManagement-BlxJ2TFw.js → EventManagement-7MyQq5KD.js} +1 -1
- package/dist/public/assets/{LoginPage-BT8ikmPn.js → LoginPage-BypxvDY2.js} +1 -1
- package/dist/public/assets/{PublicViewer-B4uFxgbt.js → PublicViewer-CdDaYqTc.js} +1 -1
- package/dist/public/assets/{SetupWizard-njrOhCzw.js → SetupWizard-CEGLuSGr.js} +1 -1
- package/dist/public/assets/{ShareManagement-Bg16oJhW.js → ShareManagement-DcPZNRdx.js} +1 -1
- package/dist/public/assets/{UserManagement-tiCIT4UY.js → UserManagement-VZ9Qvds0.js} +1 -1
- package/dist/public/assets/{index-BZ25r23j.css → index-B_fusLA_.css} +1 -1
- package/dist/public/assets/index-Cxn1i3jV.js +187 -0
- package/dist/public/assets/{index.es-BuktD_R2.js → index.es-06ls9Fpg.js} +1 -1
- package/dist/public/assets/{jspdf.es.min-DFRl2hZQ.js → jspdf.es.min-DER4Hnpt.js} +3 -3
- package/dist/public/index.html +3 -3
- package/dist/{query-JRMMNXX6.js → query-3F5V5CZH.js} +4 -4
- package/dist/{sample-VGIY4U4J.js → sample-SWYXGWOM.js} +4 -4
- package/dist/search-ARIDL6DA.js +28 -0
- package/dist/search-ARIDL6DA.js.map +1 -0
- package/dist/source-resolver-UHKZVOOC.js +18 -0
- package/dist/source-resolver-UHKZVOOC.js.map +1 -0
- package/dist/{sync-warehouse-XHTBZH25.js → sync-warehouse-J4E2R2PW.js} +4 -4
- package/dist/tables-VAR2ZKUA.js +30 -0
- package/dist/tables-VAR2ZKUA.js.map +1 -0
- package/dist/templates/default/docs/yamchart-reference.md +23 -4
- package/dist/templates/default/yamchart.yaml +1 -1
- package/dist/templates/empty/yamchart.yaml +1 -1
- package/dist/{test-TXRZWNXK.js → test-SV5SLSLM.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-JYQKDWLG.js.map +0 -1
- package/dist/chunk-OTAUP5RC.js.map +0 -1
- package/dist/chunk-X6LQGWUX.js.map +0 -1
- package/dist/describe-TGIOBNJB.js +0 -44
- package/dist/describe-TGIOBNJB.js.map +0 -1
- package/dist/dev-MRZ76V74.js.map +0 -1
- package/dist/public/assets/index-B41yj3io.js +0 -187
- package/dist/search-QSYNG4SR.js +0 -39
- package/dist/search-QSYNG4SR.js.map +0 -1
- package/dist/tables-UOO342TA.js +0 -40
- package/dist/tables-UOO342TA.js.map +0 -1
- /package/dist/{advisor-57BOMUUF.js.map → advisor-JMWAAWJO.js.map} +0 -0
- /package/dist/{chunk-E2UZXDF6.js.map → chunk-N6PUISAQ.js.map} +0 -0
- /package/dist/{connection-utils-FTSZU2VF.js.map → connection-utils-VEKXRCOM.js.map} +0 -0
- /package/dist/{dist-PVHFUYP2.js.map → dist-E2PVGIPT.js.map} +0 -0
- /package/dist/{dist-WDTDQDTX.js.map → dist-GVNWQXFR.js.map} +0 -0
- /package/dist/{query-JRMMNXX6.js.map → query-3F5V5CZH.js.map} +0 -0
- /package/dist/{sample-VGIY4U4J.js.map → sample-SWYXGWOM.js.map} +0 -0
- /package/dist/{sync-warehouse-XHTBZH25.js.map → sync-warehouse-J4E2R2PW.js.map} +0 -0
- /package/dist/{test-TXRZWNXK.js.map → test-SV5SLSLM.js.map} +0 -0
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
MySQLConnector,
|
|
5
5
|
PostgresConnector,
|
|
6
6
|
QueryCompiler,
|
|
7
|
+
ReconnectingConnector,
|
|
7
8
|
SQLiteConnector,
|
|
8
9
|
SnowflakeConnector,
|
|
9
10
|
SqlList,
|
|
@@ -30,7 +31,7 @@ import {
|
|
|
30
31
|
runModel,
|
|
31
32
|
serializeDateValue,
|
|
32
33
|
templateHasVariable
|
|
33
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-5N3FYFBV.js";
|
|
34
35
|
import {
|
|
35
36
|
SemanticModelBuilder,
|
|
36
37
|
SemanticQueryCompiler,
|
|
@@ -47,6 +48,7 @@ export {
|
|
|
47
48
|
MySQLConnector,
|
|
48
49
|
PostgresConnector,
|
|
49
50
|
QueryCompiler,
|
|
51
|
+
ReconnectingConnector,
|
|
50
52
|
SQLiteConnector,
|
|
51
53
|
SemanticModelBuilder,
|
|
52
54
|
SemanticQueryCompiler,
|
|
@@ -81,4 +83,4 @@ export {
|
|
|
81
83
|
templateHasVariable,
|
|
82
84
|
validateSemanticQuery
|
|
83
85
|
};
|
|
84
|
-
//# sourceMappingURL=dist-
|
|
86
|
+
//# sourceMappingURL=dist-E2PVGIPT.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-5N3FYFBV.js";
|
|
2
2
|
import {
|
|
3
3
|
SemanticModelBuilder,
|
|
4
4
|
SemanticQueryCompiler
|
|
@@ -787,4 +787,4 @@ export {
|
|
|
787
787
|
updateSchemaYml,
|
|
788
788
|
writeDbtModel
|
|
789
789
|
};
|
|
790
|
-
//# sourceMappingURL=dist-
|
|
790
|
+
//# sourceMappingURL=dist-GVNWQXFR.js.map
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
findProjectRoot,
|
|
7
7
|
loadEnvFile,
|
|
8
8
|
validateProject
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-N6PUISAQ.js";
|
|
10
10
|
import {
|
|
11
11
|
detail,
|
|
12
12
|
error,
|
|
@@ -17,8 +17,8 @@ import {
|
|
|
17
17
|
success,
|
|
18
18
|
warning
|
|
19
19
|
} from "./chunk-HJVVHYVN.js";
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-KP4CYPBL.js";
|
|
21
|
+
import "./chunk-5N3FYFBV.js";
|
|
22
22
|
import "./chunk-UND73EOB.js";
|
|
23
23
|
import "./chunk-DGUM43GV.js";
|
|
24
24
|
|
|
@@ -97,11 +97,12 @@ program.command("dev").description("Start development server with hot reload").a
|
|
|
97
97
|
detail("Run this command from a yamchart project directory");
|
|
98
98
|
process.exit(2);
|
|
99
99
|
}
|
|
100
|
-
const { runDevServer } = await import("./dev-
|
|
100
|
+
const { runDevServer } = await import("./dev-NZLS72PG.js");
|
|
101
101
|
await runDevServer(projectDir, {
|
|
102
102
|
port: parseInt(options.port, 10),
|
|
103
103
|
apiOnly: options.apiOnly ?? false,
|
|
104
|
-
open: options.open
|
|
104
|
+
open: options.open,
|
|
105
|
+
version: pkg.version
|
|
105
106
|
});
|
|
106
107
|
});
|
|
107
108
|
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) => {
|
|
@@ -169,7 +170,7 @@ program.command("sync-dbt").description("Sync dbt project metadata into AI-reada
|
|
|
169
170
|
if (!options.targetDatabase) {
|
|
170
171
|
try {
|
|
171
172
|
const { readFile } = await import("fs/promises");
|
|
172
|
-
const { resolveConnection } = await import("./connection-utils-
|
|
173
|
+
const { resolveConnection } = await import("./connection-utils-VEKXRCOM.js");
|
|
173
174
|
const { detectDatabaseMismatch } = await import("./rewrite-database-FDJIXKZ2.js");
|
|
174
175
|
const catalogJsonStr = await readFile(join(projectDir, ".yamchart", "catalog.json"), "utf-8");
|
|
175
176
|
const catalogData = JSON.parse(catalogJsonStr);
|
|
@@ -223,7 +224,7 @@ program.command("test").description("Run model tests (@returns schema checks and
|
|
|
223
224
|
}
|
|
224
225
|
loadEnvFile(projectDir);
|
|
225
226
|
try {
|
|
226
|
-
const { testProject, formatTestOutput } = await import("./test-
|
|
227
|
+
const { testProject, formatTestOutput } = await import("./test-SV5SLSLM.js");
|
|
227
228
|
const result = await testProject(projectDir, model, {
|
|
228
229
|
connection: options.connection,
|
|
229
230
|
json: options.json
|
|
@@ -261,7 +262,7 @@ program.command("reset-password").description("Reset a user password (requires a
|
|
|
261
262
|
const { resetPassword } = await import("./reset-password-IZQTDTU7.js");
|
|
262
263
|
await resetPassword(projectDir, options.email);
|
|
263
264
|
});
|
|
264
|
-
program.command("tables").description("List tables and views in the connected database").option("-c, --connection <name>", "Connection to use (overrides default)").option("-s, --schema <name>", "Filter to schema").option("-d, --database <name>", "Filter to database (Snowflake/Databricks)").option("--json", "Output as JSON").action(async (options) => {
|
|
265
|
+
program.command("tables").description("List tables and views in the connected database").option("-c, --connection <name>", "Connection to use (overrides default)").option("-s, --schema <name>", "Filter to schema").option("-d, --database <name>", "Filter to database (Snowflake/Databricks)").option("--json", "Output as JSON").option("--source <type>", "Data source: auto, catalog, model, or db (default: auto)").option("--compare", "Compare local metadata against live database").action(async (options) => {
|
|
265
266
|
const startPath = resolve(".");
|
|
266
267
|
const projectDir = await findProjectRoot(startPath);
|
|
267
268
|
if (!projectDir) {
|
|
@@ -271,12 +272,48 @@ program.command("tables").description("List tables and views in the connected da
|
|
|
271
272
|
}
|
|
272
273
|
loadEnvFile(projectDir);
|
|
273
274
|
try {
|
|
274
|
-
|
|
275
|
-
|
|
275
|
+
if (options.compare) {
|
|
276
|
+
const { resolveTablesSource } = await import("./source-resolver-UHKZVOOC.js");
|
|
277
|
+
const { compareTables, formatCompareTables } = await import("./compare-ZN6RUOOQ.js");
|
|
278
|
+
let localResult;
|
|
279
|
+
try {
|
|
280
|
+
localResult = await resolveTablesSource(projectDir, "catalog", options.connection, {
|
|
281
|
+
schema: options.schema,
|
|
282
|
+
database: options.database
|
|
283
|
+
});
|
|
284
|
+
} catch {
|
|
285
|
+
try {
|
|
286
|
+
localResult = await resolveTablesSource(projectDir, "model", options.connection, {
|
|
287
|
+
schema: options.schema,
|
|
288
|
+
database: options.database
|
|
289
|
+
});
|
|
290
|
+
} catch {
|
|
291
|
+
error("Cannot compare \u2014 no local metadata found. Run `yamchart sync-dbt` or `yamchart sync-warehouse` first.");
|
|
292
|
+
process.exit(1);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const dbResult = await resolveTablesSource(projectDir, "db", options.connection, {
|
|
296
|
+
schema: options.schema,
|
|
297
|
+
database: options.database
|
|
298
|
+
});
|
|
299
|
+
const diffs = compareTables(localResult.tables, dbResult.tables);
|
|
300
|
+
if (options.json) {
|
|
301
|
+
console.log(JSON.stringify(diffs, null, 2));
|
|
302
|
+
} else {
|
|
303
|
+
console.log(formatCompareTables(localResult.source, diffs));
|
|
304
|
+
}
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const { listTables } = await import("./tables-VAR2ZKUA.js");
|
|
308
|
+
const result = await listTables(projectDir, {
|
|
309
|
+
...options,
|
|
310
|
+
source: options.source || "auto"
|
|
311
|
+
});
|
|
276
312
|
if (options.json) {
|
|
277
313
|
console.log(JSON.stringify(result.tables, null, 2));
|
|
278
314
|
} else {
|
|
279
|
-
|
|
315
|
+
const sourceLabel = result.source === "db" ? `${result.connectionName} (${result.connectionType})` : `Source: ${result.source}`;
|
|
316
|
+
header(`Tables in ${sourceLabel}`);
|
|
280
317
|
if (result.tables.length === 0) {
|
|
281
318
|
info("No tables found");
|
|
282
319
|
} else {
|
|
@@ -286,7 +323,7 @@ program.command("tables").description("List tables and views in the connected da
|
|
|
286
323
|
console.log(` ${schema}${table.name}${typeLabel}`);
|
|
287
324
|
}
|
|
288
325
|
newline();
|
|
289
|
-
info(`${result.tables.length} table(s) found (${result.durationMs.toFixed(0)}ms)`);
|
|
326
|
+
info(`${result.tables.length} table(s) found${result.durationMs > 0 ? ` (${result.durationMs.toFixed(0)}ms)` : ""}`);
|
|
290
327
|
}
|
|
291
328
|
}
|
|
292
329
|
} catch (err) {
|
|
@@ -294,7 +331,7 @@ program.command("tables").description("List tables and views in the connected da
|
|
|
294
331
|
process.exit(1);
|
|
295
332
|
}
|
|
296
333
|
});
|
|
297
|
-
program.command("describe").description("Show columns and types for a table").argument("<table>", "Table name (can be fully qualified, e.g. schema.table)").option("-c, --connection <name>", "Connection to use (overrides default)").option("--json", "Output as JSON").action(async (table, options) => {
|
|
334
|
+
program.command("describe").description("Show columns and types for a table").argument("<table>", "Table name (can be fully qualified, e.g. schema.table)").option("-c, --connection <name>", "Connection to use (overrides default)").option("--json", "Output as JSON").option("--source <type>", "Data source: auto, catalog, model, or db (default: auto)").option("--compare", "Compare local metadata against live database").action(async (table, options) => {
|
|
298
335
|
const startPath = resolve(".");
|
|
299
336
|
const projectDir = await findProjectRoot(startPath);
|
|
300
337
|
if (!projectDir) {
|
|
@@ -304,15 +341,42 @@ program.command("describe").description("Show columns and types for a table").ar
|
|
|
304
341
|
}
|
|
305
342
|
loadEnvFile(projectDir);
|
|
306
343
|
try {
|
|
307
|
-
|
|
308
|
-
|
|
344
|
+
if (options.compare) {
|
|
345
|
+
const { resolveDescribeSource } = await import("./source-resolver-UHKZVOOC.js");
|
|
346
|
+
const { compareColumns, formatCompareColumns } = await import("./compare-ZN6RUOOQ.js");
|
|
347
|
+
let localResult;
|
|
348
|
+
try {
|
|
349
|
+
localResult = await resolveDescribeSource(projectDir, table, "catalog", options.connection);
|
|
350
|
+
} catch {
|
|
351
|
+
try {
|
|
352
|
+
localResult = await resolveDescribeSource(projectDir, table, "model", options.connection);
|
|
353
|
+
} catch {
|
|
354
|
+
error("Cannot compare \u2014 no local metadata found. Run `yamchart sync-dbt` or `yamchart sync-warehouse` first.");
|
|
355
|
+
process.exit(1);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
const dbResult = await resolveDescribeSource(projectDir, table, "db", options.connection);
|
|
359
|
+
const diffs = compareColumns(localResult.columns, dbResult.columns);
|
|
360
|
+
if (options.json) {
|
|
361
|
+
console.log(JSON.stringify(diffs, null, 2));
|
|
362
|
+
} else {
|
|
363
|
+
console.log(formatCompareColumns(localResult.table, localResult.source, diffs));
|
|
364
|
+
}
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
const { describeTable } = await import("./describe-X55JPLES.js");
|
|
368
|
+
const result = await describeTable(projectDir, table, {
|
|
369
|
+
...options,
|
|
370
|
+
source: options.source || "auto"
|
|
371
|
+
});
|
|
309
372
|
if (options.json) {
|
|
310
373
|
console.log(JSON.stringify(result.columns, null, 2));
|
|
311
374
|
} else {
|
|
312
375
|
if (result.resolvedFrom) {
|
|
313
376
|
detail(`Resolved "${result.resolvedFrom}" \u2192 ${result.table}`);
|
|
314
377
|
}
|
|
315
|
-
|
|
378
|
+
const sourceLabel = result.source === "db" ? `${result.connectionName} (${result.connectionType})` : `Source: ${result.source}`;
|
|
379
|
+
header(`${result.table} (${sourceLabel})`);
|
|
316
380
|
const nameWidth = Math.max(4, ...result.columns.map((c) => c.name.length));
|
|
317
381
|
const typeWidth = Math.max(4, ...result.columns.map((c) => c.type.length));
|
|
318
382
|
console.log(` ${"name".padEnd(nameWidth)} ${"type".padEnd(typeWidth)} nullable`);
|
|
@@ -322,7 +386,7 @@ program.command("describe").description("Show columns and types for a table").ar
|
|
|
322
386
|
console.log(` ${col.name.padEnd(nameWidth)} ${pc.dim(col.type.padEnd(typeWidth))} ${nullable}`);
|
|
323
387
|
}
|
|
324
388
|
newline();
|
|
325
|
-
info(`${result.columns.length} column(s) (${result.durationMs.toFixed(0)}ms)`);
|
|
389
|
+
info(`${result.columns.length} column(s)${result.durationMs > 0 ? ` (${result.durationMs.toFixed(0)}ms)` : ""}`);
|
|
326
390
|
}
|
|
327
391
|
} catch (err) {
|
|
328
392
|
error(err instanceof Error ? err.message : String(err));
|
|
@@ -339,8 +403,8 @@ program.command("query").description("Execute SQL against a connection").argumen
|
|
|
339
403
|
}
|
|
340
404
|
loadEnvFile(projectDir);
|
|
341
405
|
try {
|
|
342
|
-
const { executeQuery } = await import("./query-
|
|
343
|
-
const { formatTable, formatJSON } = await import("./connection-utils-
|
|
406
|
+
const { executeQuery } = await import("./query-3F5V5CZH.js");
|
|
407
|
+
const { formatTable, formatJSON } = await import("./connection-utils-VEKXRCOM.js");
|
|
344
408
|
const limit = options.limit ? parseInt(options.limit, 10) : void 0;
|
|
345
409
|
const result = await executeQuery(projectDir, sql, {
|
|
346
410
|
connection: options.connection,
|
|
@@ -367,8 +431,8 @@ program.command("sample").description("Show sample rows from a table or dbt mode
|
|
|
367
431
|
}
|
|
368
432
|
loadEnvFile(projectDir);
|
|
369
433
|
try {
|
|
370
|
-
const { sampleTable } = await import("./sample-
|
|
371
|
-
const { formatTable, formatJSON } = await import("./connection-utils-
|
|
434
|
+
const { sampleTable } = await import("./sample-SWYXGWOM.js");
|
|
435
|
+
const { formatTable, formatJSON } = await import("./connection-utils-VEKXRCOM.js");
|
|
372
436
|
const limit = options.limit ? parseInt(options.limit, 10) : void 0;
|
|
373
437
|
const result = await sampleTable(projectDir, table, {
|
|
374
438
|
connection: options.connection,
|
|
@@ -388,7 +452,7 @@ program.command("sample").description("Show sample rows from a table or dbt mode
|
|
|
388
452
|
process.exit(1);
|
|
389
453
|
}
|
|
390
454
|
});
|
|
391
|
-
program.command("search").description("Search for tables and columns by keyword").argument("<keyword>", "Keyword to search for").option("-c, --connection <name>", "Connection to use (overrides default)").option("--json", "Output as JSON").action(async (keyword, options) => {
|
|
455
|
+
program.command("search").description("Search for tables and columns by keyword").argument("<keyword>", "Keyword to search for").option("-c, --connection <name>", "Connection to use (overrides default)").option("--json", "Output as JSON").option("--source <type>", "Data source: auto, catalog, model, or db (default: auto)").action(async (keyword, options) => {
|
|
392
456
|
const startPath = resolve(".");
|
|
393
457
|
const projectDir = await findProjectRoot(startPath);
|
|
394
458
|
if (!projectDir) {
|
|
@@ -398,12 +462,16 @@ program.command("search").description("Search for tables and columns by keyword"
|
|
|
398
462
|
}
|
|
399
463
|
loadEnvFile(projectDir);
|
|
400
464
|
try {
|
|
401
|
-
const { searchDatabase } = await import("./search-
|
|
402
|
-
const result = await searchDatabase(projectDir, keyword,
|
|
465
|
+
const { searchDatabase } = await import("./search-ARIDL6DA.js");
|
|
466
|
+
const result = await searchDatabase(projectDir, keyword, {
|
|
467
|
+
...options,
|
|
468
|
+
source: options.source || "auto"
|
|
469
|
+
});
|
|
403
470
|
if (options.json) {
|
|
404
471
|
console.log(JSON.stringify(result.results, null, 2));
|
|
405
472
|
} else {
|
|
406
|
-
|
|
473
|
+
const sourceLabel = result.source === "db" ? `${result.connectionName} (${result.connectionType})` : `Source: ${result.source}`;
|
|
474
|
+
header(`Search results for "${result.keyword}" in ${sourceLabel}`);
|
|
407
475
|
const tables = result.results.filter((r) => r.type === "table");
|
|
408
476
|
const columns = result.results.filter((r) => r.type === "column");
|
|
409
477
|
if (tables.length > 0) {
|
|
@@ -431,7 +499,216 @@ program.command("search").description("Search for tables and columns by keyword"
|
|
|
431
499
|
detail("No matches found");
|
|
432
500
|
}
|
|
433
501
|
newline();
|
|
434
|
-
info(`${result.results.length} result(s) (${result.durationMs.toFixed(0)}ms)`);
|
|
502
|
+
info(`${result.results.length} result(s)${result.durationMs > 0 ? ` (${result.durationMs.toFixed(0)}ms)` : ""}`);
|
|
503
|
+
}
|
|
504
|
+
} catch (err) {
|
|
505
|
+
error(err instanceof Error ? err.message : String(err));
|
|
506
|
+
process.exit(1);
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
var catalogCmd = program.command("catalog").description("Explore cached local metadata (no database connection needed)");
|
|
510
|
+
catalogCmd.command("tables").description("List tables from cached catalog").option("-s, --schema <name>", "Filter to schema").option("--json", "Output as JSON").action(async (options) => {
|
|
511
|
+
const startPath = resolve(".");
|
|
512
|
+
const projectDir = await findProjectRoot(startPath);
|
|
513
|
+
if (!projectDir) {
|
|
514
|
+
error("yamchart.yaml not found");
|
|
515
|
+
detail("Run this command from a yamchart project directory");
|
|
516
|
+
process.exit(2);
|
|
517
|
+
}
|
|
518
|
+
try {
|
|
519
|
+
const { listTables } = await import("./tables-VAR2ZKUA.js");
|
|
520
|
+
const result = await listTables(projectDir, {
|
|
521
|
+
source: "catalog",
|
|
522
|
+
schema: options.schema
|
|
523
|
+
});
|
|
524
|
+
if (options.json) {
|
|
525
|
+
console.log(JSON.stringify(result.tables, null, 2));
|
|
526
|
+
} else {
|
|
527
|
+
header("Tables (from catalog)");
|
|
528
|
+
if (result.tables.length === 0) {
|
|
529
|
+
info("No tables found in catalog");
|
|
530
|
+
detail("Run `yamchart sync-warehouse` or `yamchart sync-dbt` to populate");
|
|
531
|
+
} else {
|
|
532
|
+
const filtered = options.schema ? result.tables.filter((t) => t.schema.toLowerCase().includes(options.schema.toLowerCase())) : result.tables;
|
|
533
|
+
for (const table of filtered) {
|
|
534
|
+
const schema = table.schema ? `${table.schema}.` : "";
|
|
535
|
+
const typeLabel = table.type === "VIEW" ? pc.dim(" (view)") : table.type === "SOURCE" ? pc.dim(" (source)") : "";
|
|
536
|
+
console.log(` ${schema}${table.name}${typeLabel}`);
|
|
537
|
+
}
|
|
538
|
+
newline();
|
|
539
|
+
info(`${filtered.length} table(s) from catalog`);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
} catch (err) {
|
|
543
|
+
if (err instanceof Error && err.message.includes("No catalog found")) {
|
|
544
|
+
error("No catalog found");
|
|
545
|
+
detail("Run `yamchart sync-warehouse` or `yamchart sync-dbt` to populate");
|
|
546
|
+
} else {
|
|
547
|
+
error(err instanceof Error ? err.message : String(err));
|
|
548
|
+
}
|
|
549
|
+
process.exit(1);
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
catalogCmd.command("describe").description("Show cached columns and types for a table").argument("<table>", "Table name or model name").option("--json", "Output as JSON").action(async (table, options) => {
|
|
553
|
+
const startPath = resolve(".");
|
|
554
|
+
const projectDir = await findProjectRoot(startPath);
|
|
555
|
+
if (!projectDir) {
|
|
556
|
+
error("yamchart.yaml not found");
|
|
557
|
+
detail("Run this command from a yamchart project directory");
|
|
558
|
+
process.exit(2);
|
|
559
|
+
}
|
|
560
|
+
try {
|
|
561
|
+
const { describeTable } = await import("./describe-X55JPLES.js");
|
|
562
|
+
const result = await describeTable(projectDir, table, { source: "catalog" });
|
|
563
|
+
if (options.json) {
|
|
564
|
+
console.log(JSON.stringify(result.columns, null, 2));
|
|
565
|
+
} else {
|
|
566
|
+
if (result.resolvedFrom) {
|
|
567
|
+
detail(`Resolved "${result.resolvedFrom}" \u2192 ${result.table}`);
|
|
568
|
+
}
|
|
569
|
+
header(`${result.table} (from catalog)`);
|
|
570
|
+
const nameWidth = Math.max(4, ...result.columns.map((c) => c.name.length));
|
|
571
|
+
const typeWidth = Math.max(4, ...result.columns.map((c) => c.type.length));
|
|
572
|
+
console.log(` ${"name".padEnd(nameWidth)} ${"type".padEnd(typeWidth)} nullable`);
|
|
573
|
+
console.log(` ${"\u2500".repeat(nameWidth)} ${"\u2500".repeat(typeWidth)} ${"\u2500".repeat(8)}`);
|
|
574
|
+
for (const col of result.columns) {
|
|
575
|
+
const nullable = col.nullable === "YES" ? pc.dim("yes") : "no";
|
|
576
|
+
console.log(` ${col.name.padEnd(nameWidth)} ${pc.dim(col.type.padEnd(typeWidth))} ${nullable}`);
|
|
577
|
+
}
|
|
578
|
+
newline();
|
|
579
|
+
info(`${result.columns.length} column(s)`);
|
|
580
|
+
}
|
|
581
|
+
} catch (err) {
|
|
582
|
+
if (err instanceof Error && err.message.includes("No catalog found")) {
|
|
583
|
+
error("No catalog found");
|
|
584
|
+
detail("Run `yamchart sync-warehouse` or `yamchart sync-dbt` to populate");
|
|
585
|
+
} else if (err instanceof Error && err.message.includes("not found in catalog")) {
|
|
586
|
+
error(err.message);
|
|
587
|
+
detail("Try `yamchart catalog search` to find available tables");
|
|
588
|
+
} else {
|
|
589
|
+
error(err instanceof Error ? err.message : String(err));
|
|
590
|
+
}
|
|
591
|
+
process.exit(1);
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
catalogCmd.command("search").description("Search cached metadata for tables and columns").argument("<keyword>", "Keyword to search for").option("--json", "Output as JSON").action(async (keyword, options) => {
|
|
595
|
+
const startPath = resolve(".");
|
|
596
|
+
const projectDir = await findProjectRoot(startPath);
|
|
597
|
+
if (!projectDir) {
|
|
598
|
+
error("yamchart.yaml not found");
|
|
599
|
+
detail("Run this command from a yamchart project directory");
|
|
600
|
+
process.exit(2);
|
|
601
|
+
}
|
|
602
|
+
try {
|
|
603
|
+
const { searchDatabase } = await import("./search-ARIDL6DA.js");
|
|
604
|
+
const result = await searchDatabase(projectDir, keyword, { source: "catalog" });
|
|
605
|
+
if (options.json) {
|
|
606
|
+
console.log(JSON.stringify(result.results, null, 2));
|
|
607
|
+
} else {
|
|
608
|
+
header(`Search results for "${keyword}" (from catalog)`);
|
|
609
|
+
const tables = result.results.filter((r) => r.type === "table");
|
|
610
|
+
const columns = result.results.filter((r) => r.type === "column");
|
|
611
|
+
if (tables.length > 0) {
|
|
612
|
+
newline();
|
|
613
|
+
console.log(" Tables:");
|
|
614
|
+
for (const t of tables) {
|
|
615
|
+
const qualified = t.schema ? `${t.schema}.${t.table}` : t.table;
|
|
616
|
+
console.log(` ${qualified}`);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
if (columns.length > 0) {
|
|
620
|
+
newline();
|
|
621
|
+
console.log(" Columns:");
|
|
622
|
+
const nameWidth = Math.max(...columns.map((c) => {
|
|
623
|
+
const qualified = c.schema ? `${c.schema}.${c.table}.${c.column}` : `${c.table}.${c.column}`;
|
|
624
|
+
return qualified.length;
|
|
625
|
+
}));
|
|
626
|
+
for (const c of columns) {
|
|
627
|
+
const qualified = c.schema ? `${c.schema}.${c.table}.${c.column}` : `${c.table}.${c.column}`;
|
|
628
|
+
const colType = c.columnType ? pc.dim(c.columnType) : "";
|
|
629
|
+
console.log(` ${qualified.padEnd(nameWidth + 2)}${colType}`);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
if (result.results.length === 0) {
|
|
633
|
+
detail("No matches found in catalog");
|
|
634
|
+
detail("Try `yamchart search <keyword>` to search the live database");
|
|
635
|
+
}
|
|
636
|
+
newline();
|
|
637
|
+
info(`${result.results.length} result(s) from catalog`);
|
|
638
|
+
}
|
|
639
|
+
} catch (err) {
|
|
640
|
+
if (err instanceof Error && err.message.includes("No catalog found")) {
|
|
641
|
+
error("No catalog found");
|
|
642
|
+
detail("Run `yamchart sync-warehouse` or `yamchart sync-dbt` to populate");
|
|
643
|
+
} else {
|
|
644
|
+
error(err instanceof Error ? err.message : String(err));
|
|
645
|
+
}
|
|
646
|
+
process.exit(1);
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
catalogCmd.command("status").description("Show catalog sync status").option("--json", "Output as JSON").action(async (options) => {
|
|
650
|
+
const startPath = resolve(".");
|
|
651
|
+
const projectDir = await findProjectRoot(startPath);
|
|
652
|
+
if (!projectDir) {
|
|
653
|
+
error("yamchart.yaml not found");
|
|
654
|
+
detail("Run this command from a yamchart project directory");
|
|
655
|
+
process.exit(2);
|
|
656
|
+
}
|
|
657
|
+
try {
|
|
658
|
+
const { readFile } = await import("fs/promises");
|
|
659
|
+
const catalogPath = join(projectDir, ".yamchart", "catalog.json");
|
|
660
|
+
let catalogData;
|
|
661
|
+
try {
|
|
662
|
+
catalogData = JSON.parse(await readFile(catalogPath, "utf-8"));
|
|
663
|
+
} catch {
|
|
664
|
+
if (options.json) {
|
|
665
|
+
console.log(JSON.stringify({ exists: false }));
|
|
666
|
+
} else {
|
|
667
|
+
error("No catalog found");
|
|
668
|
+
detail("Run `yamchart sync-warehouse` or `yamchart sync-dbt` to populate");
|
|
669
|
+
}
|
|
670
|
+
process.exit(1);
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
const models = catalogData.models || [];
|
|
674
|
+
const dbtModels = models.filter((m) => m.source === "dbt");
|
|
675
|
+
const warehouseModels = models.filter((m) => m.source === "warehouse");
|
|
676
|
+
const sourceModels = models.filter((m) => m.source === "dbt-source");
|
|
677
|
+
const totalColumns = models.reduce((sum, m) => sum + (m.columns?.length || 0), 0);
|
|
678
|
+
let syncState = null;
|
|
679
|
+
try {
|
|
680
|
+
const syncPath = join(projectDir, ".yamchart", "warehouse-sync.json");
|
|
681
|
+
syncState = JSON.parse(await readFile(syncPath, "utf-8"));
|
|
682
|
+
} catch {
|
|
683
|
+
}
|
|
684
|
+
if (options.json) {
|
|
685
|
+
console.log(JSON.stringify({
|
|
686
|
+
exists: true,
|
|
687
|
+
syncedAt: catalogData.syncedAt,
|
|
688
|
+
source: catalogData.source,
|
|
689
|
+
models: models.length,
|
|
690
|
+
dbtModels: dbtModels.length,
|
|
691
|
+
warehouseModels: warehouseModels.length,
|
|
692
|
+
sourceModels: sourceModels.length,
|
|
693
|
+
totalColumns,
|
|
694
|
+
warehouseSync: syncState ? {
|
|
695
|
+
syncedAt: syncState.syncedAt,
|
|
696
|
+
connection: syncState.connection,
|
|
697
|
+
schemas: syncState.schemas
|
|
698
|
+
} : null
|
|
699
|
+
}, null, 2));
|
|
700
|
+
} else {
|
|
701
|
+
header("Catalog Status");
|
|
702
|
+
console.log(` Last synced: ${catalogData.syncedAt || "unknown"}`);
|
|
703
|
+
console.log(` Models: ${models.length} total (${dbtModels.length} dbt, ${warehouseModels.length} warehouse, ${sourceModels.length} sources)`);
|
|
704
|
+
console.log(` Columns: ${totalColumns}`);
|
|
705
|
+
if (syncState) {
|
|
706
|
+
newline();
|
|
707
|
+
console.log(` Warehouse sync:`);
|
|
708
|
+
console.log(` Connection: ${syncState.connection || "default"}`);
|
|
709
|
+
console.log(` Schemas: ${syncState.schemas?.join(", ") || "all"}`);
|
|
710
|
+
console.log(` Last sync: ${syncState.syncedAt || "unknown"}`);
|
|
711
|
+
}
|
|
435
712
|
}
|
|
436
713
|
} catch (err) {
|
|
437
714
|
error(err instanceof Error ? err.message : String(err));
|
|
@@ -448,14 +725,14 @@ program.command("sync-warehouse").description("Sync warehouse table metadata int
|
|
|
448
725
|
}
|
|
449
726
|
loadEnvFile(projectDir);
|
|
450
727
|
try {
|
|
451
|
-
const { runSyncWarehouse } = await import("./sync-warehouse-
|
|
728
|
+
const { runSyncWarehouse } = await import("./sync-warehouse-J4E2R2PW.js");
|
|
452
729
|
await runSyncWarehouse(projectDir, options);
|
|
453
730
|
} catch (err) {
|
|
454
731
|
error(err instanceof Error ? err.message : String(err));
|
|
455
732
|
process.exit(1);
|
|
456
733
|
}
|
|
457
734
|
});
|
|
458
|
-
program.command("lineage").description("Show upstream dependencies for a model").argument("<model>", "Model name to trace lineage for").option("--depth <n>", "Maximum depth to trace (default: unlimited)").option("--json", "Output as JSON").action(async (model, options) => {
|
|
735
|
+
program.command("lineage").description("Show upstream dependencies for a model").argument("<model>", "Model name to trace lineage for").option("--depth <n>", "Maximum depth to trace (default: unlimited)").option("--json", "Output as JSON").option("--source <type>", "Data source: auto, catalog, model, or db (default: auto)").action(async (model, options) => {
|
|
459
736
|
const startPath = resolve(".");
|
|
460
737
|
const projectDir = await findProjectRoot(startPath);
|
|
461
738
|
if (!projectDir) {
|
|
@@ -463,10 +740,15 @@ program.command("lineage").description("Show upstream dependencies for a model")
|
|
|
463
740
|
detail("Run this command from a yamchart project directory");
|
|
464
741
|
process.exit(2);
|
|
465
742
|
}
|
|
743
|
+
loadEnvFile(projectDir);
|
|
466
744
|
try {
|
|
467
|
-
const { getLineage } = await import("./lineage-
|
|
745
|
+
const { getLineage } = await import("./lineage-T5NRHHZN.js");
|
|
468
746
|
const depth = options.depth ? parseInt(options.depth, 10) : void 0;
|
|
469
|
-
const result = await getLineage(projectDir, model, {
|
|
747
|
+
const result = await getLineage(projectDir, model, {
|
|
748
|
+
depth,
|
|
749
|
+
json: options.json,
|
|
750
|
+
source: options.source || "auto"
|
|
751
|
+
});
|
|
470
752
|
if (options.json) {
|
|
471
753
|
console.log(JSON.stringify(result.tree, null, 2));
|
|
472
754
|
} else {
|
|
@@ -494,7 +776,7 @@ program.command("advisor").description("AI-powered dbt model advisor \u2014 sugg
|
|
|
494
776
|
process.exit(2);
|
|
495
777
|
}
|
|
496
778
|
loadEnvFile(projectDir);
|
|
497
|
-
const { runAdvisor } = await import("./advisor-
|
|
779
|
+
const { runAdvisor } = await import("./advisor-JMWAAWJO.js");
|
|
498
780
|
await runAdvisor(projectDir, question, {
|
|
499
781
|
top: options.top ? parseInt(options.top, 10) : 5,
|
|
500
782
|
json: options.json,
|
|
@@ -584,7 +866,7 @@ semanticCmd.command("query").description("Run a structured query against the sem
|
|
|
584
866
|
console.log(result.sql);
|
|
585
867
|
return;
|
|
586
868
|
}
|
|
587
|
-
const { resolveConnection, createConnector, formatTable, formatJSON } = await import("./connection-utils-
|
|
869
|
+
const { resolveConnection, createConnector, formatTable, formatJSON } = await import("./connection-utils-VEKXRCOM.js");
|
|
588
870
|
const connection = await resolveConnection(projectDir, options.connection);
|
|
589
871
|
const connector = createConnector(connection, projectDir);
|
|
590
872
|
const start = performance.now();
|