@duckcodeailabs/dql-core 0.8.8 → 0.8.10

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.
@@ -1,60 +0,0 @@
1
- /**
2
- * Lineage Query Engine — focused, searchable lineage views.
3
- *
4
- * Replaces the "show everything" approach with targeted subgraph queries:
5
- * - Focus on a specific node and get its upstream/downstream chain
6
- * - Search nodes by name across all types
7
- * - Filter by type, domain, depth
8
- */
9
- import { LineageGraph, type LineageNode, type LineageNodeType, type LineageGraphJSON } from './lineage-graph.js';
10
- export interface LineageQuery {
11
- /** Node name or ID to center the query on */
12
- focus?: string;
13
- /** Search by name (case-insensitive substring match) */
14
- search?: string;
15
- /** Filter by node types */
16
- types?: LineageNodeType[];
17
- /** Filter by domain */
18
- domain?: string;
19
- /** Max hops upstream from focal node (default: Infinity) */
20
- upstreamDepth?: number;
21
- /** Max hops downstream from focal node (default: Infinity) */
22
- downstreamDepth?: number;
23
- }
24
- export interface LineageQueryResult {
25
- /** Focused subgraph containing only relevant nodes and edges */
26
- graph: LineageGraphJSON;
27
- /** The focal node (if focus was specified and resolved) */
28
- focalNode?: LineageNode;
29
- /** Search matches with relevance scores (if search was specified) */
30
- matches?: Array<{
31
- node: LineageNode;
32
- score: number;
33
- }>;
34
- }
35
- /**
36
- * Execute a lineage query against the graph.
37
- *
38
- * Examples:
39
- * queryLineage(graph, { focus: 'total_revenue' })
40
- * → subgraph centered on metric:total_revenue with full upstream/downstream
41
- *
42
- * queryLineage(graph, { search: 'revenue' })
43
- * → all nodes matching "revenue" with relevance scores
44
- *
45
- * queryLineage(graph, { focus: 'fct_orders', upstreamDepth: 2, downstreamDepth: 1 })
46
- * → 2 hops upstream, 1 hop downstream from dbt_model:fct_orders
47
- *
48
- * queryLineage(graph, { domain: 'finance', types: ['metric', 'block'] })
49
- * → all finance metrics and blocks with their immediate connections
50
- */
51
- export declare function queryLineage(graph: LineageGraph, query: LineageQuery): LineageQueryResult;
52
- /**
53
- * Lightweight search — returns matching nodes without building a subgraph.
54
- * Suitable for autocomplete / search-as-you-type.
55
- */
56
- export declare function searchNodes(graph: LineageGraph, searchTerm: string, limit?: number): Array<{
57
- node: LineageNode;
58
- score: number;
59
- }>;
60
- //# sourceMappingURL=query.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/lineage/query.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAIjH,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;IAC1B,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,KAAK,EAAE,gBAAgB,CAAC;IACxB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,qEAAqE;IACrE,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvD;AA2FD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,kBAAkB,CAkBzF;AA0FD;;;GAGG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,YAAY,EACnB,UAAU,EAAE,MAAM,EAClB,KAAK,SAAK,GACT,KAAK,CAAC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAY7C"}
@@ -1,211 +0,0 @@
1
- /**
2
- * Lineage Query Engine — focused, searchable lineage views.
3
- *
4
- * Replaces the "show everything" approach with targeted subgraph queries:
5
- * - Focus on a specific node and get its upstream/downstream chain
6
- * - Search nodes by name across all types
7
- * - Filter by type, domain, depth
8
- */
9
- // ---- Node ID Resolution ----
10
- /** Type prefixes to try when resolving a name to a node ID */
11
- const NODE_PREFIXES = [
12
- 'block:',
13
- 'metric:',
14
- 'table:',
15
- 'dbt_model:',
16
- 'dbt_source:',
17
- 'dashboard:',
18
- 'dimension:',
19
- 'chart:',
20
- 'domain:',
21
- ];
22
- /**
23
- * Resolve a name or ID to a node in the graph.
24
- * Tries exact match first, then prefixed matches.
25
- */
26
- function resolveNode(graph, nameOrId) {
27
- // Exact match (already prefixed)
28
- const exact = graph.getNode(nameOrId);
29
- if (exact)
30
- return exact;
31
- // Try each prefix
32
- for (const prefix of NODE_PREFIXES) {
33
- const node = graph.getNode(`${prefix}${nameOrId}`);
34
- if (node)
35
- return node;
36
- }
37
- // Fuzzy: find first node whose name matches (case-insensitive)
38
- const lower = nameOrId.toLowerCase();
39
- for (const node of graph.getAllNodes()) {
40
- if (node.name.toLowerCase() === lower)
41
- return node;
42
- }
43
- return undefined;
44
- }
45
- // ---- Search Scoring ----
46
- function scoreMatch(nodeName, query) {
47
- const name = nodeName.toLowerCase();
48
- const q = query.toLowerCase();
49
- if (name === q)
50
- return 100; // exact match
51
- if (name.startsWith(q))
52
- return 80; // starts with
53
- if (name.endsWith(q))
54
- return 60; // ends with
55
- if (name.includes(q))
56
- return 40; // substring
57
- return 0; // no match
58
- }
59
- // ---- Depth-Limited BFS ----
60
- /**
61
- * BFS traversal with depth limiting.
62
- * direction='upstream' follows incoming edges, 'downstream' follows outgoing.
63
- */
64
- function depthLimitedBFS(graph, startId, direction, maxDepth) {
65
- const visited = new Set();
66
- const queue = [{ id: startId, depth: 0 }];
67
- while (queue.length > 0) {
68
- const { id, depth } = queue.shift();
69
- if (depth > maxDepth)
70
- continue;
71
- const edges = direction === 'upstream'
72
- ? graph.getIncomingEdges(id)
73
- : graph.getOutgoingEdges(id);
74
- for (const edge of edges) {
75
- const nextId = direction === 'upstream' ? edge.source : edge.target;
76
- if (!visited.has(nextId)) {
77
- visited.add(nextId);
78
- queue.push({ id: nextId, depth: depth + 1 });
79
- }
80
- }
81
- }
82
- return visited;
83
- }
84
- // ---- Query Execution ----
85
- /**
86
- * Execute a lineage query against the graph.
87
- *
88
- * Examples:
89
- * queryLineage(graph, { focus: 'total_revenue' })
90
- * → subgraph centered on metric:total_revenue with full upstream/downstream
91
- *
92
- * queryLineage(graph, { search: 'revenue' })
93
- * → all nodes matching "revenue" with relevance scores
94
- *
95
- * queryLineage(graph, { focus: 'fct_orders', upstreamDepth: 2, downstreamDepth: 1 })
96
- * → 2 hops upstream, 1 hop downstream from dbt_model:fct_orders
97
- *
98
- * queryLineage(graph, { domain: 'finance', types: ['metric', 'block'] })
99
- * → all finance metrics and blocks with their immediate connections
100
- */
101
- export function queryLineage(graph, query) {
102
- // Search mode: return matching nodes with scores
103
- if (query.search && !query.focus) {
104
- return executeSearch(graph, query);
105
- }
106
- // Focus mode: return subgraph centered on a node
107
- if (query.focus) {
108
- return executeFocus(graph, query);
109
- }
110
- // Filter mode: domain and/or type filter
111
- if (query.domain || query.types) {
112
- return executeFilter(graph, query);
113
- }
114
- // Default: return the full graph
115
- return { graph: graph.toJSON() };
116
- }
117
- function executeSearch(graph, query) {
118
- const searchTerm = query.search;
119
- const matches = [];
120
- for (const node of graph.getAllNodes()) {
121
- // Apply type filter
122
- if (query.types && !query.types.includes(node.type))
123
- continue;
124
- // Apply domain filter
125
- if (query.domain && node.domain !== query.domain)
126
- continue;
127
- const score = scoreMatch(node.name, searchTerm);
128
- if (score > 0) {
129
- matches.push({ node, score });
130
- }
131
- }
132
- // Sort by score descending, then alphabetically
133
- matches.sort((a, b) => b.score - a.score || a.node.name.localeCompare(b.node.name));
134
- // Build a subgraph of matched nodes with their immediate edges
135
- const matchedIds = new Set(matches.map((m) => m.node.id));
136
- const sub = graph.subgraph((n) => matchedIds.has(n.id));
137
- return {
138
- graph: sub.toJSON(),
139
- matches,
140
- };
141
- }
142
- function executeFocus(graph, query) {
143
- const focalNode = resolveNode(graph, query.focus);
144
- if (!focalNode) {
145
- return { graph: { nodes: [], edges: [] }, matches: [] };
146
- }
147
- const upstreamDepth = query.upstreamDepth ?? Infinity;
148
- const downstreamDepth = query.downstreamDepth ?? Infinity;
149
- // Collect all nodes in the focused subgraph
150
- const nodeIds = new Set([focalNode.id]);
151
- // Upstream BFS
152
- const upstreamIds = depthLimitedBFS(graph, focalNode.id, 'upstream', upstreamDepth);
153
- for (const id of upstreamIds)
154
- nodeIds.add(id);
155
- // Downstream BFS
156
- const downstreamIds = depthLimitedBFS(graph, focalNode.id, 'downstream', downstreamDepth);
157
- for (const id of downstreamIds)
158
- nodeIds.add(id);
159
- // Apply type/domain filters if specified
160
- const sub = graph.subgraph((n) => {
161
- if (!nodeIds.has(n.id))
162
- return false;
163
- if (query.types && !query.types.includes(n.type) && n.id !== focalNode.id)
164
- return false;
165
- if (query.domain && n.domain !== query.domain && n.id !== focalNode.id)
166
- return false;
167
- return true;
168
- });
169
- return {
170
- graph: sub.toJSON(),
171
- focalNode,
172
- };
173
- }
174
- function executeFilter(graph, query) {
175
- // Get matching nodes
176
- const matchedNodes = graph.getAllNodes().filter((n) => {
177
- if (query.types && !query.types.includes(n.type))
178
- return false;
179
- if (query.domain && n.domain !== query.domain)
180
- return false;
181
- return true;
182
- });
183
- const matchedIds = new Set(matchedNodes.map((n) => n.id));
184
- // Also include immediate neighbors to show connections
185
- for (const node of matchedNodes) {
186
- for (const edge of graph.getIncomingEdges(node.id)) {
187
- matchedIds.add(edge.source);
188
- }
189
- for (const edge of graph.getOutgoingEdges(node.id)) {
190
- matchedIds.add(edge.target);
191
- }
192
- }
193
- const sub = graph.subgraph((n) => matchedIds.has(n.id));
194
- return { graph: sub.toJSON() };
195
- }
196
- /**
197
- * Lightweight search — returns matching nodes without building a subgraph.
198
- * Suitable for autocomplete / search-as-you-type.
199
- */
200
- export function searchNodes(graph, searchTerm, limit = 20) {
201
- const matches = [];
202
- for (const node of graph.getAllNodes()) {
203
- const score = scoreMatch(node.name, searchTerm);
204
- if (score > 0) {
205
- matches.push({ node, score });
206
- }
207
- }
208
- matches.sort((a, b) => b.score - a.score || a.node.name.localeCompare(b.node.name));
209
- return matches.slice(0, limit);
210
- }
211
- //# sourceMappingURL=query.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/lineage/query.ts"],"names":[],"mappings":"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"}