@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.
- package/LICENSE +201 -0
- package/README.md +51 -0
- package/dist/analysis/analysis-snapshot.d.ts +145 -0
- package/dist/analysis/analysis-snapshot.js +615 -0
- package/dist/analysis/dependency-service.d.ts +56 -0
- package/dist/analysis/dependency-service.js +75 -0
- package/dist/analysis/execution-analyzer.d.ts +85 -0
- package/dist/analysis/execution-analyzer.js +245 -0
- package/dist/analysis/manifest-graph.d.ts +118 -0
- package/dist/analysis/manifest-graph.js +651 -0
- package/dist/analysis/run-results-search.d.ts +56 -0
- package/dist/analysis/run-results-search.js +127 -0
- package/dist/analysis/sql-analyzer.d.ts +30 -0
- package/dist/analysis/sql-analyzer.js +218 -0
- package/dist/browser.d.ts +11 -0
- package/dist/browser.js +17 -0
- package/dist/errors/error-handler.d.ts +26 -0
- package/dist/errors/error-handler.js +59 -0
- package/dist/formatting/field-filter.d.ts +29 -0
- package/dist/formatting/field-filter.js +112 -0
- package/dist/formatting/graph-export.d.ts +9 -0
- package/dist/formatting/graph-export.js +147 -0
- package/dist/formatting/output-formatter.d.ts +77 -0
- package/dist/formatting/output-formatter.js +160 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +38 -0
- package/dist/introspection/schema-generator.d.ts +29 -0
- package/dist/introspection/schema-generator.js +275 -0
- package/dist/io/artifact-loader.d.ts +27 -0
- package/dist/io/artifact-loader.js +142 -0
- package/dist/types.d.ts +43 -0
- package/dist/types.js +2 -0
- package/dist/validation/input-validator.d.ts +39 -0
- package/dist/validation/input-validator.js +167 -0
- package/dist/version.d.ts +28 -0
- package/dist/version.js +60 -0
- package/package.json +47 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FieldFilter = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* FieldFilter provides field selection to reduce context window usage.
|
|
6
|
+
* Supports simple and nested field paths.
|
|
7
|
+
*/
|
|
8
|
+
class FieldFilter {
|
|
9
|
+
/**
|
|
10
|
+
* Filter fields from an object based on a comma-separated field list
|
|
11
|
+
*/
|
|
12
|
+
static filterFields(data, fields) {
|
|
13
|
+
if (!fields || !fields.trim()) {
|
|
14
|
+
return data;
|
|
15
|
+
}
|
|
16
|
+
if (!data || typeof data !== "object") {
|
|
17
|
+
return data;
|
|
18
|
+
}
|
|
19
|
+
const fieldList = fields
|
|
20
|
+
.split(",")
|
|
21
|
+
.map((f) => f.trim())
|
|
22
|
+
.filter((f) => f.length > 0);
|
|
23
|
+
if (fieldList.length === 0) {
|
|
24
|
+
return data;
|
|
25
|
+
}
|
|
26
|
+
return this.filterObjectFields(data, fieldList);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Filter fields from an array of objects
|
|
30
|
+
*/
|
|
31
|
+
static filterArrayFields(data, fields) {
|
|
32
|
+
if (!fields || !fields.trim()) {
|
|
33
|
+
return data;
|
|
34
|
+
}
|
|
35
|
+
if (!Array.isArray(data)) {
|
|
36
|
+
return data;
|
|
37
|
+
}
|
|
38
|
+
return data.map((item) => this.filterFields(item, fields));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Filter fields from an object using field paths
|
|
42
|
+
*/
|
|
43
|
+
static filterObjectFields(obj, fieldPaths) {
|
|
44
|
+
const result = Object.create(null);
|
|
45
|
+
for (const fieldPath of fieldPaths) {
|
|
46
|
+
const value = this.getNestedValue(obj, fieldPath);
|
|
47
|
+
if (value !== undefined) {
|
|
48
|
+
this.setNestedValue(result, fieldPath, value);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
/** Rejects prototype-pollution keys (__proto__, constructor, prototype). */
|
|
54
|
+
static isUnsafeKey(part) {
|
|
55
|
+
return (part === "__proto__" || part === "constructor" || part === "prototype");
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get a nested value from an object using dot notation.
|
|
59
|
+
* Rejects prototype-pollution keys (__proto__, constructor, prototype).
|
|
60
|
+
*/
|
|
61
|
+
static getNestedValue(obj, path) {
|
|
62
|
+
const parts = path.split(".");
|
|
63
|
+
let current = obj;
|
|
64
|
+
for (const part of parts) {
|
|
65
|
+
if (this.isUnsafeKey(part))
|
|
66
|
+
return undefined;
|
|
67
|
+
if (current === null ||
|
|
68
|
+
current === undefined ||
|
|
69
|
+
typeof current !== "object") {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
if (!Object.prototype.hasOwnProperty.call(current, part)) {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
// nosemgrep: javascript.lang.security.audit.prototype-pollution.prototype-pollution-loop
|
|
76
|
+
// Part is validated by isUnsafeKey above; hasOwnProperty ensures we don't read proto chain.
|
|
77
|
+
current = current[part];
|
|
78
|
+
}
|
|
79
|
+
return current;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Set a nested value in an object using dot notation
|
|
83
|
+
*/
|
|
84
|
+
static setNestedValue(obj, path, value) {
|
|
85
|
+
const parts = path.split(".");
|
|
86
|
+
let current = obj;
|
|
87
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
88
|
+
const part = parts[i];
|
|
89
|
+
if (part === "__proto__" ||
|
|
90
|
+
part === "constructor" ||
|
|
91
|
+
part === "prototype") {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (!Object.prototype.hasOwnProperty.call(current, part) ||
|
|
95
|
+
typeof current[part] !== "object" ||
|
|
96
|
+
current[part] === null) {
|
|
97
|
+
current[part] = Object.create(null);
|
|
98
|
+
}
|
|
99
|
+
// nosemgrep: javascript.lang.security.audit.prototype-pollution.prototype-pollution-loop
|
|
100
|
+
// Part is validated by isUnsafeKey check above; assignment creates own property only.
|
|
101
|
+
current = current[part];
|
|
102
|
+
}
|
|
103
|
+
const lastPart = parts[parts.length - 1];
|
|
104
|
+
if (lastPart === "__proto__" ||
|
|
105
|
+
lastPart === "constructor" ||
|
|
106
|
+
lastPart === "prototype") {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
current[lastPart] = value;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
exports.FieldFilter = FieldFilter;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DirectedGraph } from "graphology";
|
|
2
|
+
import type { GraphNodeAttributes, GraphEdgeAttributes } from "../types";
|
|
3
|
+
export interface GraphExportOptions {
|
|
4
|
+
format?: string;
|
|
5
|
+
output?: string;
|
|
6
|
+
fields?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function exportGraphToFormat(graph: DirectedGraph<GraphNodeAttributes, GraphEdgeAttributes>, options: GraphExportOptions): string;
|
|
9
|
+
export declare function writeGraphOutput(output: string, outputPath?: string): void;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.exportGraphToFormat = exportGraphToFormat;
|
|
37
|
+
exports.writeGraphOutput = writeGraphOutput;
|
|
38
|
+
/**
|
|
39
|
+
* Graph export helpers for JSON, DOT, and GEXF formats.
|
|
40
|
+
* Used by the CLI graph command and other graph export consumers.
|
|
41
|
+
*/
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const field_filter_1 = require("./field-filter");
|
|
44
|
+
function exportGraphToFormat(graph, options) {
|
|
45
|
+
var _a;
|
|
46
|
+
const fmt = (_a = options.format) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
47
|
+
if (fmt === "json")
|
|
48
|
+
return exportGraphJson(graph, options);
|
|
49
|
+
if (fmt === "dot")
|
|
50
|
+
return exportGraphDot(graph);
|
|
51
|
+
if (fmt === "gexf")
|
|
52
|
+
return exportGraphGexf(graph);
|
|
53
|
+
throw new Error(`Unsupported format: ${options.format}`);
|
|
54
|
+
}
|
|
55
|
+
function exportGraphJson(graph, options) {
|
|
56
|
+
const nodes = [];
|
|
57
|
+
const edges = [];
|
|
58
|
+
graph.forEachNode((nodeId, attributes) => {
|
|
59
|
+
let filteredAttrs = attributes;
|
|
60
|
+
if (options.fields) {
|
|
61
|
+
filteredAttrs = field_filter_1.FieldFilter.filterFields(attributes, options.fields);
|
|
62
|
+
}
|
|
63
|
+
nodes.push({ id: nodeId, attributes: filteredAttrs });
|
|
64
|
+
});
|
|
65
|
+
graph.forEachEdge((_edgeId, attributes, source, target) => {
|
|
66
|
+
edges.push({ source, target, attributes });
|
|
67
|
+
});
|
|
68
|
+
return JSON.stringify({ nodes, edges }, null, 2);
|
|
69
|
+
}
|
|
70
|
+
function exportGraphDot(graph) {
|
|
71
|
+
const lines = ["digraph DbtGraph {"];
|
|
72
|
+
lines.push(" compound=true;");
|
|
73
|
+
lines.push(" node [shape=box, style=filled, fillcolor=white];");
|
|
74
|
+
const resourceNodes = [];
|
|
75
|
+
const fieldNodesByParent = {};
|
|
76
|
+
graph.forEachNode((nodeId, attributes) => {
|
|
77
|
+
if (attributes.resource_type === "field") {
|
|
78
|
+
const parentId = attributes.parent_id;
|
|
79
|
+
if (!fieldNodesByParent[parentId]) {
|
|
80
|
+
fieldNodesByParent[parentId] = [];
|
|
81
|
+
}
|
|
82
|
+
fieldNodesByParent[parentId].push(nodeId);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
resourceNodes.push(nodeId);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
for (const nodeId of resourceNodes) {
|
|
89
|
+
const attributes = graph.getNodeAttributes(nodeId);
|
|
90
|
+
const name = attributes.name || nodeId;
|
|
91
|
+
const fields = fieldNodesByParent[nodeId];
|
|
92
|
+
if (fields && fields.length > 0) {
|
|
93
|
+
lines.push(` subgraph "cluster_${nodeId}" {`);
|
|
94
|
+
lines.push(` label = "${name}";`);
|
|
95
|
+
lines.push(" style = filled;");
|
|
96
|
+
lines.push(" fillcolor = lightgrey;");
|
|
97
|
+
for (const fieldId of fields) {
|
|
98
|
+
const fieldAttr = graph.getNodeAttributes(fieldId);
|
|
99
|
+
lines.push(` "${fieldId}" [label="${fieldAttr.name}", fillcolor=white];`);
|
|
100
|
+
}
|
|
101
|
+
lines.push(" }");
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
lines.push(` "${nodeId}" [label="${name}"];`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
graph.forEachEdge((_edgeId, attributes, source, target) => {
|
|
108
|
+
if (attributes.dependency_type !== "internal") {
|
|
109
|
+
lines.push(` "${source}" -> "${target}";`);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
lines.push("}");
|
|
113
|
+
return lines.join("\n");
|
|
114
|
+
}
|
|
115
|
+
function exportGraphGexf(graph) {
|
|
116
|
+
const nodes = [];
|
|
117
|
+
const edges = [];
|
|
118
|
+
graph.forEachNode((nodeId, attributes) => {
|
|
119
|
+
nodes.push({
|
|
120
|
+
id: nodeId,
|
|
121
|
+
label: attributes.name || nodeId,
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
graph.forEachEdge((_edgeId, _attributes, source, target) => {
|
|
125
|
+
edges.push({ source, target });
|
|
126
|
+
});
|
|
127
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
128
|
+
<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2">
|
|
129
|
+
<graph mode="static" defaultedgetype="directed">
|
|
130
|
+
<nodes>
|
|
131
|
+
${nodes.map((n) => ` <node id="${n.id}" label="${n.label}"/>`).join("\n")}
|
|
132
|
+
</nodes>
|
|
133
|
+
<edges>
|
|
134
|
+
${edges.map((e, i) => ` <edge id="${i}" source="${e.source}" target="${e.target}"/>`).join("\n")}
|
|
135
|
+
</edges>
|
|
136
|
+
</graph>
|
|
137
|
+
</gexf>`;
|
|
138
|
+
}
|
|
139
|
+
function writeGraphOutput(output, outputPath) {
|
|
140
|
+
if (outputPath) {
|
|
141
|
+
fs.writeFileSync(outputPath, output, "utf-8");
|
|
142
|
+
console.log(`Graph exported to ${outputPath}`);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
console.log(output);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if stdout is a TTY
|
|
3
|
+
*/
|
|
4
|
+
export declare function isTTY(): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Determine if output should be JSON
|
|
7
|
+
*/
|
|
8
|
+
export declare function shouldOutputJSON(forceJson?: boolean, forceNoJson?: boolean): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Format output as JSON or human-readable based on context
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatOutput(data: unknown, forceJson?: boolean, forceNoJson?: boolean): string;
|
|
13
|
+
/**
|
|
14
|
+
* Format summary command output
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatSummary(summary: {
|
|
17
|
+
total_nodes: number;
|
|
18
|
+
total_edges: number;
|
|
19
|
+
has_cycles: boolean;
|
|
20
|
+
nodes_by_type: Record<string, number>;
|
|
21
|
+
}): string;
|
|
22
|
+
/**
|
|
23
|
+
* Format deps command output (flat or tree)
|
|
24
|
+
*/
|
|
25
|
+
export declare function formatDeps(result: {
|
|
26
|
+
resource_id: string;
|
|
27
|
+
direction: "upstream" | "downstream";
|
|
28
|
+
dependencies: Array<{
|
|
29
|
+
unique_id: string;
|
|
30
|
+
resource_type: string;
|
|
31
|
+
name: string;
|
|
32
|
+
package_name: string;
|
|
33
|
+
depth?: number;
|
|
34
|
+
dependencies?: unknown[];
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}>;
|
|
37
|
+
count: number;
|
|
38
|
+
}, format?: "flat" | "tree"): string;
|
|
39
|
+
/**
|
|
40
|
+
* Bottleneck node for formatting
|
|
41
|
+
*/
|
|
42
|
+
export interface BottleneckNodeForFormat {
|
|
43
|
+
unique_id: string;
|
|
44
|
+
name?: string;
|
|
45
|
+
execution_time: number;
|
|
46
|
+
rank: number;
|
|
47
|
+
pct_of_total: number;
|
|
48
|
+
status: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Format bottleneck section for human-readable output
|
|
52
|
+
*/
|
|
53
|
+
export declare function formatBottlenecks(bottlenecks: {
|
|
54
|
+
nodes: BottleneckNodeForFormat[];
|
|
55
|
+
total_execution_time: number;
|
|
56
|
+
criteria_used: "top_n" | "threshold";
|
|
57
|
+
}, topLabel?: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Format run-report command output
|
|
60
|
+
*/
|
|
61
|
+
export declare function formatRunReport(summary: {
|
|
62
|
+
total_execution_time: number;
|
|
63
|
+
total_nodes: number;
|
|
64
|
+
nodes_by_status: Record<string, number>;
|
|
65
|
+
critical_path?: {
|
|
66
|
+
path: string[];
|
|
67
|
+
total_time: number;
|
|
68
|
+
};
|
|
69
|
+
}, bottlenecks?: {
|
|
70
|
+
nodes: BottleneckNodeForFormat[];
|
|
71
|
+
total_execution_time: number;
|
|
72
|
+
criteria_used: "top_n" | "threshold";
|
|
73
|
+
}, bottlenecksTopLabel?: string): string;
|
|
74
|
+
/**
|
|
75
|
+
* Format human-readable output for a specific command type
|
|
76
|
+
*/
|
|
77
|
+
export declare function formatHumanReadable(data: unknown, format: "summary" | "deps" | "run-report"): string;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isTTY = isTTY;
|
|
4
|
+
exports.shouldOutputJSON = shouldOutputJSON;
|
|
5
|
+
exports.formatOutput = formatOutput;
|
|
6
|
+
exports.formatSummary = formatSummary;
|
|
7
|
+
exports.formatDeps = formatDeps;
|
|
8
|
+
exports.formatBottlenecks = formatBottlenecks;
|
|
9
|
+
exports.formatRunReport = formatRunReport;
|
|
10
|
+
exports.formatHumanReadable = formatHumanReadable;
|
|
11
|
+
function formatDepsTreeNode(node, prefix, isLast, lines) {
|
|
12
|
+
var _a;
|
|
13
|
+
const depthStr = typeof node.depth === "number" ? ` [depth ${node.depth}]` : "";
|
|
14
|
+
const connector = isLast ? "└── " : "├── ";
|
|
15
|
+
lines.push(`${prefix}${connector}${node.unique_id} (${node.resource_type}) - ${node.name}${depthStr}`);
|
|
16
|
+
const children = ((_a = node.dependencies) !== null && _a !== void 0 ? _a : []);
|
|
17
|
+
const childPrefix = prefix + (isLast ? " " : "│ ");
|
|
18
|
+
for (let i = 0; i < children.length; i++) {
|
|
19
|
+
formatDepsTreeNode(children[i], childPrefix, i === children.length - 1, lines);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function formatDepsTree(result) {
|
|
23
|
+
var _a;
|
|
24
|
+
const rootName = (_a = result.resource_id.split(".").pop()) !== null && _a !== void 0 ? _a : result.resource_id;
|
|
25
|
+
const lines = [];
|
|
26
|
+
lines.push(`${rootName} (${result.direction})`);
|
|
27
|
+
lines.push(`Count: ${result.count}`);
|
|
28
|
+
lines.push("");
|
|
29
|
+
for (let i = 0; i < result.dependencies.length; i++) {
|
|
30
|
+
formatDepsTreeNode(result.dependencies[i], "", i === result.dependencies.length - 1, lines);
|
|
31
|
+
}
|
|
32
|
+
return lines.join("\n");
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check if stdout is a TTY
|
|
36
|
+
*/
|
|
37
|
+
function isTTY() {
|
|
38
|
+
return process.stdout.isTTY === true;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Determine if output should be JSON
|
|
42
|
+
*/
|
|
43
|
+
function shouldOutputJSON(forceJson, forceNoJson) {
|
|
44
|
+
if (forceNoJson === true) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
if (forceJson === true) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return !isTTY();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Format output as JSON or human-readable based on context
|
|
54
|
+
*/
|
|
55
|
+
function formatOutput(data, forceJson, forceNoJson) {
|
|
56
|
+
const useJson = shouldOutputJSON(forceJson, forceNoJson);
|
|
57
|
+
if (useJson) {
|
|
58
|
+
return JSON.stringify(data, null, 2);
|
|
59
|
+
}
|
|
60
|
+
return String(data);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Format summary command output
|
|
64
|
+
*/
|
|
65
|
+
function formatSummary(summary) {
|
|
66
|
+
const lines = [];
|
|
67
|
+
lines.push("dbt Project Summary");
|
|
68
|
+
lines.push("===================");
|
|
69
|
+
lines.push(`Total Nodes: ${summary.total_nodes}`);
|
|
70
|
+
lines.push(`Total Edges: ${summary.total_edges}`);
|
|
71
|
+
lines.push(`Has Cycles: ${summary.has_cycles ? "Yes" : "No"}`);
|
|
72
|
+
lines.push("\nNodes by Type:");
|
|
73
|
+
for (const [type, count] of Object.entries(summary.nodes_by_type)) {
|
|
74
|
+
lines.push(` ${type}: ${count}`);
|
|
75
|
+
}
|
|
76
|
+
return lines.join("\n");
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Format deps command output (flat or tree)
|
|
80
|
+
*/
|
|
81
|
+
function formatDeps(result, format) {
|
|
82
|
+
if (format === "tree") {
|
|
83
|
+
return formatDepsTree(result);
|
|
84
|
+
}
|
|
85
|
+
const lines = [];
|
|
86
|
+
lines.push(`Dependencies for ${result.resource_id}`);
|
|
87
|
+
lines.push(`Direction: ${result.direction}`);
|
|
88
|
+
lines.push(`Count: ${result.count}`);
|
|
89
|
+
lines.push("\nDependencies:");
|
|
90
|
+
if (result.dependencies.length === 0) {
|
|
91
|
+
lines.push(" (none)");
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
for (const dep of result.dependencies) {
|
|
95
|
+
const depthStr = typeof dep.depth === "number" ? ` [depth ${dep.depth}]` : "";
|
|
96
|
+
lines.push(` - ${dep.unique_id} (${dep.resource_type}) - ${dep.name}${depthStr}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return lines.join("\n");
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Format bottleneck section for human-readable output
|
|
103
|
+
*/
|
|
104
|
+
function formatBottlenecks(bottlenecks, topLabel) {
|
|
105
|
+
var _a;
|
|
106
|
+
if (bottlenecks.nodes.length === 0) {
|
|
107
|
+
return "\nBottlenecks: (none)\n";
|
|
108
|
+
}
|
|
109
|
+
const criteriaLabel = topLabel !== null && topLabel !== void 0 ? topLabel : (bottlenecks.criteria_used === "top_n" ? "top N" : "threshold");
|
|
110
|
+
const lines = [];
|
|
111
|
+
lines.push(`\nBottlenecks (${criteriaLabel} by execution time):`);
|
|
112
|
+
lines.push(" Rank Node Time (s) % of Total");
|
|
113
|
+
const maxIdLen = 34;
|
|
114
|
+
for (const node of bottlenecks.nodes) {
|
|
115
|
+
const label = (_a = node.name) !== null && _a !== void 0 ? _a : node.unique_id;
|
|
116
|
+
const idDisplay = label.length > maxIdLen ? label.slice(0, maxIdLen - 3) + "..." : label;
|
|
117
|
+
const padded = idDisplay.padEnd(maxIdLen);
|
|
118
|
+
const timeStr = node.execution_time.toFixed(2).padStart(8);
|
|
119
|
+
lines.push(` ${String(node.rank).padStart(2)} ${padded} ${timeStr} ${node.pct_of_total.toFixed(1)}%`);
|
|
120
|
+
}
|
|
121
|
+
return lines.join("\n") + "\n";
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Format run-report command output
|
|
125
|
+
*/
|
|
126
|
+
function formatRunReport(summary, bottlenecks, bottlenecksTopLabel) {
|
|
127
|
+
const lines = [];
|
|
128
|
+
lines.push("dbt Execution Report");
|
|
129
|
+
lines.push("===================");
|
|
130
|
+
lines.push(`Total Execution Time: ${summary.total_execution_time.toFixed(2)}s`);
|
|
131
|
+
lines.push(`Total Nodes: ${summary.total_nodes}`);
|
|
132
|
+
lines.push("\nNodes by Status:");
|
|
133
|
+
for (const [status, count] of Object.entries(summary.nodes_by_status)) {
|
|
134
|
+
lines.push(` ${status}: ${count}`);
|
|
135
|
+
}
|
|
136
|
+
if (summary.critical_path) {
|
|
137
|
+
lines.push("\nCritical Path:");
|
|
138
|
+
lines.push(` Path: ${summary.critical_path.path.join(" -> ")}`);
|
|
139
|
+
lines.push(` Total Time: ${summary.critical_path.total_time.toFixed(2)}s`);
|
|
140
|
+
}
|
|
141
|
+
if (bottlenecks) {
|
|
142
|
+
lines.push(formatBottlenecks(bottlenecks, bottlenecksTopLabel));
|
|
143
|
+
}
|
|
144
|
+
return lines.join("\n");
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Format human-readable output for a specific command type
|
|
148
|
+
*/
|
|
149
|
+
function formatHumanReadable(data, format) {
|
|
150
|
+
switch (format) {
|
|
151
|
+
case "summary":
|
|
152
|
+
return formatSummary(data);
|
|
153
|
+
case "deps":
|
|
154
|
+
return formatDeps(data);
|
|
155
|
+
case "run-report":
|
|
156
|
+
return formatRunReport(data);
|
|
157
|
+
default:
|
|
158
|
+
return String(data);
|
|
159
|
+
}
|
|
160
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./analysis/manifest-graph";
|
|
2
|
+
export * from "./analysis/execution-analyzer";
|
|
3
|
+
export * from "./analysis/dependency-service";
|
|
4
|
+
export * from "./analysis/sql-analyzer";
|
|
5
|
+
export * from "./analysis/run-results-search";
|
|
6
|
+
export * from "./analysis/analysis-snapshot";
|
|
7
|
+
export * from "./io/artifact-loader";
|
|
8
|
+
export * from "./validation/input-validator";
|
|
9
|
+
export * from "./formatting/output-formatter";
|
|
10
|
+
export * from "./formatting/field-filter";
|
|
11
|
+
export * from "./formatting/graph-export";
|
|
12
|
+
export * from "./errors/error-handler";
|
|
13
|
+
export * from "./introspection/schema-generator";
|
|
14
|
+
export * from "./types";
|
|
15
|
+
export * from "./version";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// Analysis exports
|
|
18
|
+
__exportStar(require("./analysis/manifest-graph"), exports);
|
|
19
|
+
__exportStar(require("./analysis/execution-analyzer"), exports);
|
|
20
|
+
__exportStar(require("./analysis/dependency-service"), exports);
|
|
21
|
+
__exportStar(require("./analysis/sql-analyzer"), exports);
|
|
22
|
+
__exportStar(require("./analysis/run-results-search"), exports);
|
|
23
|
+
__exportStar(require("./analysis/analysis-snapshot"), exports);
|
|
24
|
+
// I/O exports
|
|
25
|
+
__exportStar(require("./io/artifact-loader"), exports);
|
|
26
|
+
// Validation exports
|
|
27
|
+
__exportStar(require("./validation/input-validator"), exports);
|
|
28
|
+
// Formatting exports
|
|
29
|
+
__exportStar(require("./formatting/output-formatter"), exports);
|
|
30
|
+
__exportStar(require("./formatting/field-filter"), exports);
|
|
31
|
+
__exportStar(require("./formatting/graph-export"), exports);
|
|
32
|
+
// Error handling exports
|
|
33
|
+
__exportStar(require("./errors/error-handler"), exports);
|
|
34
|
+
// Introspection exports
|
|
35
|
+
__exportStar(require("./introspection/schema-generator"), exports);
|
|
36
|
+
// Shared types and utilities
|
|
37
|
+
__exportStar(require("./types"), exports);
|
|
38
|
+
__exportStar(require("./version"), exports);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command schema definition for runtime introspection
|
|
3
|
+
*/
|
|
4
|
+
export interface CommandSchema {
|
|
5
|
+
command: string;
|
|
6
|
+
description: string;
|
|
7
|
+
arguments: Array<{
|
|
8
|
+
name: string;
|
|
9
|
+
required: boolean;
|
|
10
|
+
description: string;
|
|
11
|
+
}>;
|
|
12
|
+
options: Array<{
|
|
13
|
+
name: string;
|
|
14
|
+
type: string;
|
|
15
|
+
values?: string[];
|
|
16
|
+
default?: string;
|
|
17
|
+
description: string;
|
|
18
|
+
}>;
|
|
19
|
+
output_format: string;
|
|
20
|
+
example: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get schema for a specific command
|
|
24
|
+
*/
|
|
25
|
+
export declare function getCommandSchema(command: string): CommandSchema | null;
|
|
26
|
+
/**
|
|
27
|
+
* Get all command schemas
|
|
28
|
+
*/
|
|
29
|
+
export declare function getAllSchemas(): Record<string, CommandSchema>;
|