@dbt-tools/core 0.3.2

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 (37) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +51 -0
  3. package/dist/analysis/analysis-snapshot.d.ts +145 -0
  4. package/dist/analysis/analysis-snapshot.js +615 -0
  5. package/dist/analysis/dependency-service.d.ts +56 -0
  6. package/dist/analysis/dependency-service.js +75 -0
  7. package/dist/analysis/execution-analyzer.d.ts +85 -0
  8. package/dist/analysis/execution-analyzer.js +245 -0
  9. package/dist/analysis/manifest-graph.d.ts +118 -0
  10. package/dist/analysis/manifest-graph.js +651 -0
  11. package/dist/analysis/run-results-search.d.ts +56 -0
  12. package/dist/analysis/run-results-search.js +127 -0
  13. package/dist/analysis/sql-analyzer.d.ts +30 -0
  14. package/dist/analysis/sql-analyzer.js +218 -0
  15. package/dist/browser.d.ts +11 -0
  16. package/dist/browser.js +17 -0
  17. package/dist/errors/error-handler.d.ts +26 -0
  18. package/dist/errors/error-handler.js +59 -0
  19. package/dist/formatting/field-filter.d.ts +29 -0
  20. package/dist/formatting/field-filter.js +112 -0
  21. package/dist/formatting/graph-export.d.ts +9 -0
  22. package/dist/formatting/graph-export.js +147 -0
  23. package/dist/formatting/output-formatter.d.ts +77 -0
  24. package/dist/formatting/output-formatter.js +160 -0
  25. package/dist/index.d.ts +15 -0
  26. package/dist/index.js +38 -0
  27. package/dist/introspection/schema-generator.d.ts +29 -0
  28. package/dist/introspection/schema-generator.js +275 -0
  29. package/dist/io/artifact-loader.d.ts +27 -0
  30. package/dist/io/artifact-loader.js +142 -0
  31. package/dist/types.d.ts +43 -0
  32. package/dist/types.js +2 -0
  33. package/dist/validation/input-validator.d.ts +39 -0
  34. package/dist/validation/input-validator.js +167 -0
  35. package/dist/version.d.ts +28 -0
  36. package/dist/version.js +60 -0
  37. package/package.json +47 -0
@@ -0,0 +1,56 @@
1
+ import type { NodeExecution } from "./execution-analyzer";
2
+ import type { ManifestGraph } from "./manifest-graph";
3
+ /**
4
+ * Criteria for filtering run results executions
5
+ */
6
+ export interface RunResultsSearchCriteria {
7
+ /** Min execution time in seconds */
8
+ min_execution_time?: number;
9
+ /** Max execution time in seconds */
10
+ max_execution_time?: number;
11
+ /** Filter by status: success, error, skipped, etc. */
12
+ status?: string | string[];
13
+ /** Glob or regex pattern for unique_id */
14
+ unique_id_pattern?: string | RegExp;
15
+ /** Limit number of results (for top-N queries) */
16
+ limit?: number;
17
+ /** Sort by: execution_time_asc | execution_time_desc | unique_id */
18
+ sort?: "execution_time_asc" | "execution_time_desc" | "unique_id";
19
+ }
20
+ /**
21
+ * Single bottleneck node in the result
22
+ */
23
+ export interface BottleneckNode {
24
+ unique_id: string;
25
+ name?: string;
26
+ execution_time: number;
27
+ rank: number;
28
+ pct_of_total: number;
29
+ status: string;
30
+ }
31
+ /**
32
+ * Result of bottleneck detection
33
+ */
34
+ export interface BottleneckResult {
35
+ nodes: BottleneckNode[];
36
+ total_execution_time: number;
37
+ criteria_used: "top_n" | "threshold";
38
+ }
39
+ /**
40
+ * Search and filter NodeExecution array by criteria.
41
+ * Pure function: returns new array, no side effects.
42
+ */
43
+ export declare function searchRunResults(executions: NodeExecution[], criteria: RunResultsSearchCriteria): NodeExecution[];
44
+ /**
45
+ * Detect bottlenecks in execution results.
46
+ * Uses searchRunResults internally for filtering.
47
+ */
48
+ export declare function detectBottlenecks(executions: NodeExecution[], options: {
49
+ mode: "top_n";
50
+ top: number;
51
+ graph?: ManifestGraph;
52
+ } | {
53
+ mode: "threshold";
54
+ min_seconds: number;
55
+ graph?: ManifestGraph;
56
+ }): BottleneckResult;
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.searchRunResults = searchRunResults;
4
+ exports.detectBottlenecks = detectBottlenecks;
5
+ /**
6
+ * Simple glob match: * matches any chars. Avoids ReDoS from dynamic RegExp.
7
+ */
8
+ function matchesGlob(text, pattern) {
9
+ const parts = pattern.split("*");
10
+ if (parts.length === 1)
11
+ return text === pattern;
12
+ let pos = 0;
13
+ for (let i = 0; i < parts.length; i++) {
14
+ const part = parts[i];
15
+ const idx = text.indexOf(part, pos);
16
+ if (idx === -1)
17
+ return false;
18
+ if (i === 0 && idx !== 0)
19
+ return false;
20
+ pos = idx + part.length;
21
+ }
22
+ return (parts[parts.length - 1] === "" || text.endsWith(parts[parts.length - 1]));
23
+ }
24
+ /**
25
+ * Filter executions by unique_id pattern (glob or RegExp)
26
+ */
27
+ function matchesUniqueId(uniqueId, pattern) {
28
+ if (pattern instanceof RegExp) {
29
+ return pattern.test(uniqueId);
30
+ }
31
+ return matchesGlob(uniqueId, pattern);
32
+ }
33
+ /**
34
+ * Search and filter NodeExecution array by criteria.
35
+ * Pure function: returns new array, no side effects.
36
+ */
37
+ function searchRunResults(executions, criteria) {
38
+ let result = [...executions];
39
+ // Filter by status
40
+ if (criteria.status !== undefined) {
41
+ const statuses = typeof criteria.status === "string" ? [criteria.status] : criteria.status;
42
+ const set = new Set(statuses.map((s) => s.toLowerCase()));
43
+ result = result.filter((e) => set.has((e.status || "unknown").toLowerCase()));
44
+ }
45
+ // Filter by execution time range
46
+ if (criteria.min_execution_time !== undefined) {
47
+ result = result.filter((e) => { var _a; return ((_a = e.execution_time) !== null && _a !== void 0 ? _a : 0) >= criteria.min_execution_time; });
48
+ }
49
+ if (criteria.max_execution_time !== undefined) {
50
+ result = result.filter((e) => { var _a; return ((_a = e.execution_time) !== null && _a !== void 0 ? _a : 0) <= criteria.max_execution_time; });
51
+ }
52
+ // Filter by unique_id pattern
53
+ if (criteria.unique_id_pattern !== undefined) {
54
+ result = result.filter((e) => matchesUniqueId(e.unique_id, criteria.unique_id_pattern));
55
+ }
56
+ // Sort
57
+ if (criteria.sort) {
58
+ result = [...result].sort((a, b) => {
59
+ var _a, _b, _c, _d;
60
+ switch (criteria.sort) {
61
+ case "execution_time_asc":
62
+ return ((_a = a.execution_time) !== null && _a !== void 0 ? _a : 0) - ((_b = b.execution_time) !== null && _b !== void 0 ? _b : 0);
63
+ case "execution_time_desc":
64
+ return ((_c = b.execution_time) !== null && _c !== void 0 ? _c : 0) - ((_d = a.execution_time) !== null && _d !== void 0 ? _d : 0);
65
+ case "unique_id":
66
+ return a.unique_id.localeCompare(b.unique_id);
67
+ default:
68
+ return 0;
69
+ }
70
+ });
71
+ }
72
+ // Limit
73
+ if (criteria.limit !== undefined && criteria.limit >= 0) {
74
+ result = result.slice(0, criteria.limit);
75
+ }
76
+ return result;
77
+ }
78
+ /**
79
+ * Get display name for a node from the graph, or fallback to unique_id
80
+ */
81
+ function getNodeName(uniqueId, graph) {
82
+ if (!graph)
83
+ return undefined;
84
+ const g = graph.getGraph();
85
+ if (!g.hasNode(uniqueId))
86
+ return undefined;
87
+ const attrs = g.getNodeAttributes(uniqueId);
88
+ return (attrs === null || attrs === void 0 ? void 0 : attrs.name) || undefined;
89
+ }
90
+ /**
91
+ * Detect bottlenecks in execution results.
92
+ * Uses searchRunResults internally for filtering.
93
+ */
94
+ function detectBottlenecks(executions, options) {
95
+ const totalExecutionTime = executions.reduce((sum, e) => { var _a; return sum + ((_a = e.execution_time) !== null && _a !== void 0 ? _a : 0); }, 0);
96
+ let filtered;
97
+ if (options.mode === "top_n") {
98
+ filtered = searchRunResults(executions, {
99
+ sort: "execution_time_desc",
100
+ limit: options.top,
101
+ });
102
+ }
103
+ else {
104
+ filtered = searchRunResults(executions, {
105
+ min_execution_time: options.min_seconds,
106
+ sort: "execution_time_desc",
107
+ });
108
+ }
109
+ const nodes = filtered.map((e, i) => {
110
+ var _a;
111
+ const time = (_a = e.execution_time) !== null && _a !== void 0 ? _a : 0;
112
+ const pct = totalExecutionTime > 0 ? (time / totalExecutionTime) * 100 : 0;
113
+ return {
114
+ unique_id: e.unique_id,
115
+ name: getNodeName(e.unique_id, options.graph),
116
+ execution_time: time,
117
+ rank: i + 1,
118
+ pct_of_total: Math.round(pct * 10) / 10,
119
+ status: e.status || "unknown",
120
+ };
121
+ });
122
+ return {
123
+ nodes,
124
+ total_execution_time: totalExecutionTime,
125
+ criteria_used: options.mode === "top_n" ? "top_n" : "threshold",
126
+ };
127
+ }
@@ -0,0 +1,30 @@
1
+ export interface ColumnDependency {
2
+ sourceTable: string;
3
+ sourceColumn: string;
4
+ }
5
+ export type ColumnDependencyMap = Record<string, ColumnDependency[]>;
6
+ /**
7
+ * SQLAnalyzer performs AST analysis on SQL to infer column-level lineage.
8
+ */
9
+ export declare class SQLAnalyzer {
10
+ private parser;
11
+ constructor();
12
+ /**
13
+ * Analyze SQL to extract column-level dependencies.
14
+ * @param sql The compiled SQL code.
15
+ * @param dialect The SQL dialect (e.g., 'mysql', 'postgresql', 'snowflake').
16
+ * @returns A map of target column names to their source dependencies.
17
+ */
18
+ analyze(sql: string, dialect?: string): ColumnDependencyMap;
19
+ private analyzeSelect;
20
+ private buildCteMap;
21
+ private getColumnTargetName;
22
+ private processSelectColumns;
23
+ private extractColumnName;
24
+ private buildTableMap;
25
+ private resolveExpressionDependencies;
26
+ private traverseAst;
27
+ private collectColumnRefDeps;
28
+ private pushColumnDeps;
29
+ private uniqueDependencies;
30
+ }
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SQLAnalyzer = void 0;
4
+ const node_sql_parser_1 = require("node-sql-parser");
5
+ /**
6
+ * SQLAnalyzer performs AST analysis on SQL to infer column-level lineage.
7
+ */
8
+ class SQLAnalyzer {
9
+ constructor() {
10
+ this.parser = new node_sql_parser_1.Parser();
11
+ }
12
+ /**
13
+ * Analyze SQL to extract column-level dependencies.
14
+ * @param sql The compiled SQL code.
15
+ * @param dialect The SQL dialect (e.g., 'mysql', 'postgresql', 'snowflake').
16
+ * @returns A map of target column names to their source dependencies.
17
+ */
18
+ analyze(sql, dialect = "mysql") {
19
+ try {
20
+ let cleanSql = sql.trim();
21
+ while (cleanSql.endsWith(";")) {
22
+ cleanSql = cleanSql.slice(0, -1);
23
+ }
24
+ const ast = this.parser.astify(cleanSql, { database: dialect });
25
+ if (Array.isArray(ast)) {
26
+ const selectAst = ast.find((s) => s.type === "select");
27
+ return selectAst ? this.analyzeSelect(selectAst, dialect) : {};
28
+ }
29
+ return this.analyzeSelect(ast, dialect);
30
+ }
31
+ catch (_a) {
32
+ return {};
33
+ }
34
+ }
35
+ analyzeSelect(select, dialect, parentCteMap = {}) {
36
+ if (!select || select.type !== "select")
37
+ return {};
38
+ const tableMap = this.buildTableMap((Array.isArray(select.from) ? select.from : []));
39
+ const cteMap = this.buildCteMap(select, dialect, parentCteMap);
40
+ if (!select.columns || !Array.isArray(select.columns))
41
+ return {};
42
+ return this.processSelectColumns(select.columns, tableMap, cteMap);
43
+ }
44
+ buildCteMap(select, dialect, parentCteMap) {
45
+ var _a;
46
+ const cteMap = Object.assign({}, parentCteMap);
47
+ if (!select.with || !Array.isArray(select.with))
48
+ return cteMap;
49
+ for (const cte of select.with) {
50
+ if ((_a = cte.stmt) === null || _a === void 0 ? void 0 : _a.ast) {
51
+ cteMap[cte.name.value] = this.analyzeSelect(cte.stmt.ast, dialect, cteMap);
52
+ }
53
+ }
54
+ return cteMap;
55
+ }
56
+ getColumnTargetName(col) {
57
+ const asVal = col.as;
58
+ if (asVal !== undefined && asVal !== null) {
59
+ return typeof asVal === "string"
60
+ ? asVal
61
+ : typeof asVal.value === "string"
62
+ ? asVal.value
63
+ : undefined;
64
+ }
65
+ if (col.expr &&
66
+ typeof col.expr === "object" &&
67
+ col.expr.type === "column_ref") {
68
+ return this.extractColumnName(col.expr.column);
69
+ }
70
+ return undefined;
71
+ }
72
+ processSelectColumns(columns, tableMap, cteMap) {
73
+ const dependencies = {};
74
+ for (const col of columns) {
75
+ const targetName = this.getColumnTargetName(col);
76
+ if (!targetName || targetName === "*") {
77
+ const colColumn = col.expr &&
78
+ typeof col.expr === "object" &&
79
+ col.expr.type === "column_ref"
80
+ ? this.extractColumnName(col.expr.column)
81
+ : undefined;
82
+ if (targetName === "*" || colColumn === "*") {
83
+ const starDeps = this.resolveExpressionDependencies(col.expr, tableMap, cteMap);
84
+ dependencies["*"] = this.uniqueDependencies(starDeps);
85
+ }
86
+ continue;
87
+ }
88
+ const colDeps = this.resolveExpressionDependencies(col.expr, tableMap, cteMap);
89
+ const uniqueDeps = this.uniqueDependencies(colDeps);
90
+ if (uniqueDeps.length > 0) {
91
+ dependencies[targetName] = uniqueDeps;
92
+ }
93
+ }
94
+ return dependencies;
95
+ }
96
+ extractColumnName(column) {
97
+ if (typeof column === "string")
98
+ return column;
99
+ if (column && typeof column === "object") {
100
+ const c = column;
101
+ const expr = c.expr;
102
+ if (expr &&
103
+ typeof expr === "object" &&
104
+ expr.type === "default") {
105
+ return String(expr.value);
106
+ }
107
+ }
108
+ return String(column);
109
+ }
110
+ buildTableMap(from) {
111
+ const map = {};
112
+ if (!from || !Array.isArray(from))
113
+ return map;
114
+ for (const item of from) {
115
+ const f = item;
116
+ if (f.table) {
117
+ const actualTable = f.table;
118
+ const alias = f.as || actualTable;
119
+ map[alias] = actualTable;
120
+ }
121
+ else if (f.expr && f.expr.ast) {
122
+ const subqueryAlias = f.as;
123
+ if (subqueryAlias) {
124
+ map[subqueryAlias] = `__subquery_${subqueryAlias}__`;
125
+ }
126
+ }
127
+ }
128
+ return map;
129
+ }
130
+ resolveExpressionDependencies(expr, tableMap, cteMap) {
131
+ const deps = [];
132
+ this.traverseAst(expr, tableMap, cteMap, deps);
133
+ return deps;
134
+ }
135
+ traverseAst(node, tableMap, cteMap, deps) {
136
+ if (!node || typeof node !== "object")
137
+ return;
138
+ const n = node;
139
+ switch (n.type) {
140
+ case "column_ref":
141
+ this.collectColumnRefDeps(n, tableMap, cteMap, deps);
142
+ break;
143
+ case "binary_expr":
144
+ this.traverseAst(n.left, tableMap, cteMap, deps);
145
+ this.traverseAst(n.right, tableMap, cteMap, deps);
146
+ break;
147
+ case "function": {
148
+ const args = n.args;
149
+ if (args === null || args === void 0 ? void 0 : args.value)
150
+ for (const a of args.value)
151
+ this.traverseAst(a, tableMap, cteMap, deps);
152
+ break;
153
+ }
154
+ case "aggr_func": {
155
+ const args = n.args;
156
+ if (args === null || args === void 0 ? void 0 : args.expr)
157
+ this.traverseAst(args.expr, tableMap, cteMap, deps);
158
+ break;
159
+ }
160
+ case "case": {
161
+ const args = n.args;
162
+ if (args)
163
+ for (const arg of args) {
164
+ this.traverseAst(arg.cond, tableMap, cteMap, deps);
165
+ this.traverseAst(arg.result, tableMap, cteMap, deps);
166
+ }
167
+ this.traverseAst(n.fallback, tableMap, cteMap, deps);
168
+ break;
169
+ }
170
+ case "cast":
171
+ this.traverseAst(n.expr, tableMap, cteMap, deps);
172
+ break;
173
+ }
174
+ }
175
+ collectColumnRefDeps(n, tableMap, cteMap, deps) {
176
+ var _a;
177
+ const tableAlias = n.table;
178
+ const columnName = this.extractColumnName(n.column);
179
+ if (tableAlias) {
180
+ const actualTable = tableMap[tableAlias];
181
+ if (actualTable) {
182
+ this.pushColumnDeps(actualTable, columnName, cteMap, deps);
183
+ }
184
+ return;
185
+ }
186
+ const tables = Object.values(tableMap);
187
+ if (tables.length === 1) {
188
+ this.pushColumnDeps(tables[0], columnName, cteMap, deps);
189
+ return;
190
+ }
191
+ for (const table of tables) {
192
+ const cteCols = (_a = cteMap[table]) === null || _a === void 0 ? void 0 : _a[columnName];
193
+ if (cteCols === null || cteCols === void 0 ? void 0 : cteCols.length)
194
+ deps.push(...cteCols);
195
+ }
196
+ }
197
+ pushColumnDeps(actualTable, columnName, cteMap, deps) {
198
+ var _a, _b;
199
+ const cteDeps = (_b = (_a = cteMap[actualTable]) === null || _a === void 0 ? void 0 : _a[columnName]) !== null && _b !== void 0 ? _b : [];
200
+ if (cteDeps.length > 0) {
201
+ deps.push(...cteDeps);
202
+ }
203
+ else {
204
+ deps.push({ sourceTable: actualTable, sourceColumn: columnName });
205
+ }
206
+ }
207
+ uniqueDependencies(deps) {
208
+ const seen = new Set();
209
+ return deps.filter((d) => {
210
+ const key = `${d.sourceTable}.${d.sourceColumn}`;
211
+ if (seen.has(key))
212
+ return false;
213
+ seen.add(key);
214
+ return true;
215
+ });
216
+ }
217
+ }
218
+ exports.SQLAnalyzer = SQLAnalyzer;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Browser-safe entry point for @dbt-tools/core.
3
+ * Re-exports only APIs that do not depend on Node.js (fs, path).
4
+ */
5
+ export { ManifestGraph } from "./analysis/manifest-graph";
6
+ export { ExecutionAnalyzer } from "./analysis/execution-analyzer";
7
+ export { searchRunResults, detectBottlenecks, } from "./analysis/run-results-search";
8
+ export { buildAnalysisSnapshotFromArtifacts, buildAnalysisSnapshotFromParsedArtifacts, } from "./analysis/analysis-snapshot";
9
+ export type { NodeExecution, ExecutionSummary, CriticalPath, } from "./analysis/execution-analyzer";
10
+ export type { BottleneckNode, BottleneckResult, RunResultsSearchCriteria, } from "./analysis/run-results-search";
11
+ export type { AnalysisSnapshot, AnalysisSnapshotBuildTimings, DependencyPreview, ExecutionRow, GanttItem, GraphSnapshot, MetricDefinition, ResourceConnectionSummary, ResourceDefinition, ResourceGroup, ResourceNode, SemanticModelDefinition, StatusBreakdownItem, StatusTone, ThreadStat, TimelineAdjacencyEntry, } from "./analysis/analysis-snapshot";
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildAnalysisSnapshotFromParsedArtifacts = exports.buildAnalysisSnapshotFromArtifacts = exports.detectBottlenecks = exports.searchRunResults = exports.ExecutionAnalyzer = exports.ManifestGraph = void 0;
4
+ /**
5
+ * Browser-safe entry point for @dbt-tools/core.
6
+ * Re-exports only APIs that do not depend on Node.js (fs, path).
7
+ */
8
+ var manifest_graph_1 = require("./analysis/manifest-graph");
9
+ Object.defineProperty(exports, "ManifestGraph", { enumerable: true, get: function () { return manifest_graph_1.ManifestGraph; } });
10
+ var execution_analyzer_1 = require("./analysis/execution-analyzer");
11
+ Object.defineProperty(exports, "ExecutionAnalyzer", { enumerable: true, get: function () { return execution_analyzer_1.ExecutionAnalyzer; } });
12
+ var run_results_search_1 = require("./analysis/run-results-search");
13
+ Object.defineProperty(exports, "searchRunResults", { enumerable: true, get: function () { return run_results_search_1.searchRunResults; } });
14
+ Object.defineProperty(exports, "detectBottlenecks", { enumerable: true, get: function () { return run_results_search_1.detectBottlenecks; } });
15
+ var analysis_snapshot_1 = require("./analysis/analysis-snapshot");
16
+ Object.defineProperty(exports, "buildAnalysisSnapshotFromArtifacts", { enumerable: true, get: function () { return analysis_snapshot_1.buildAnalysisSnapshotFromArtifacts; } });
17
+ Object.defineProperty(exports, "buildAnalysisSnapshotFromParsedArtifacts", { enumerable: true, get: function () { return analysis_snapshot_1.buildAnalysisSnapshotFromParsedArtifacts; } });
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Structured error format for JSON output
3
+ */
4
+ export interface StructuredError {
5
+ error: string;
6
+ code: string;
7
+ message: string;
8
+ details?: unknown;
9
+ }
10
+ /**
11
+ * ErrorHandler provides structured error formatting for agent consumption
12
+ */
13
+ export declare class ErrorHandler {
14
+ /**
15
+ * Format an error for output (JSON when not TTY, human-readable when TTY)
16
+ */
17
+ static formatError(error: Error, isTTY: boolean): string | StructuredError;
18
+ /**
19
+ * Create a validation error
20
+ */
21
+ static createValidationError(message: string, field?: string): Error;
22
+ /**
23
+ * Get error code from error type
24
+ */
25
+ private static getErrorCode;
26
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ErrorHandler = void 0;
4
+ /**
5
+ * ErrorHandler provides structured error formatting for agent consumption
6
+ */
7
+ class ErrorHandler {
8
+ /**
9
+ * Format an error for output (JSON when not TTY, human-readable when TTY)
10
+ */
11
+ static formatError(error, isTTY) {
12
+ const structured = {
13
+ error: error.name || "Error",
14
+ code: this.getErrorCode(error),
15
+ message: error.message,
16
+ };
17
+ // Add details for validation errors
18
+ if (error.name === "ValidationError" && "field" in error) {
19
+ structured.details = { field: error.field };
20
+ }
21
+ if (isTTY) {
22
+ // Human-readable format
23
+ return `Error [${structured.code}]: ${structured.message}`;
24
+ }
25
+ // JSON format for agents
26
+ return structured;
27
+ }
28
+ /**
29
+ * Create a validation error
30
+ */
31
+ static createValidationError(message, field) {
32
+ const error = new Error(message);
33
+ error.name = "ValidationError";
34
+ if (field) {
35
+ error.field = field;
36
+ }
37
+ return error;
38
+ }
39
+ /**
40
+ * Get error code from error type
41
+ */
42
+ static getErrorCode(error) {
43
+ if (error.name === "ValidationError") {
44
+ return "VALIDATION_ERROR";
45
+ }
46
+ if (error.message.includes("not found") ||
47
+ error.message.includes("File not found")) {
48
+ return "FILE_NOT_FOUND";
49
+ }
50
+ if (error.message.includes("Failed to parse")) {
51
+ return "PARSE_ERROR";
52
+ }
53
+ if (error.message.includes("Unsupported dbt version")) {
54
+ return "UNSUPPORTED_VERSION";
55
+ }
56
+ return "UNKNOWN_ERROR";
57
+ }
58
+ }
59
+ exports.ErrorHandler = ErrorHandler;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * FieldFilter provides field selection to reduce context window usage.
3
+ * Supports simple and nested field paths.
4
+ */
5
+ export declare class FieldFilter {
6
+ /**
7
+ * Filter fields from an object based on a comma-separated field list
8
+ */
9
+ static filterFields<T>(data: T, fields?: string): Partial<T>;
10
+ /**
11
+ * Filter fields from an array of objects
12
+ */
13
+ static filterArrayFields<T>(data: T[], fields?: string): Partial<T>[];
14
+ /**
15
+ * Filter fields from an object using field paths
16
+ */
17
+ private static filterObjectFields;
18
+ /** Rejects prototype-pollution keys (__proto__, constructor, prototype). */
19
+ private static isUnsafeKey;
20
+ /**
21
+ * Get a nested value from an object using dot notation.
22
+ * Rejects prototype-pollution keys (__proto__, constructor, prototype).
23
+ */
24
+ private static getNestedValue;
25
+ /**
26
+ * Set a nested value in an object using dot notation
27
+ */
28
+ private static setNestedValue;
29
+ }