dbgraph 0.1.0

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 (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +347 -0
  3. package/dist/bin/dbgraph.d.ts +8 -0
  4. package/dist/bin/dbgraph.d.ts.map +1 -0
  5. package/dist/bin/dbgraph.js +382 -0
  6. package/dist/bin/dbgraph.js.map +1 -0
  7. package/dist/config.d.ts +25 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +158 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/context/formatter.d.ts +94 -0
  12. package/dist/context/formatter.d.ts.map +1 -0
  13. package/dist/context/formatter.js +288 -0
  14. package/dist/context/formatter.js.map +1 -0
  15. package/dist/context/index.d.ts +77 -0
  16. package/dist/context/index.d.ts.map +1 -0
  17. package/dist/context/index.js +458 -0
  18. package/dist/context/index.js.map +1 -0
  19. package/dist/db/index.d.ts +26 -0
  20. package/dist/db/index.d.ts.map +1 -0
  21. package/dist/db/index.js +127 -0
  22. package/dist/db/index.js.map +1 -0
  23. package/dist/db/migrations.d.ts +8 -0
  24. package/dist/db/migrations.d.ts.map +1 -0
  25. package/dist/db/migrations.js +39 -0
  26. package/dist/db/migrations.js.map +1 -0
  27. package/dist/db/queries.d.ts +46 -0
  28. package/dist/db/queries.d.ts.map +1 -0
  29. package/dist/db/queries.js +436 -0
  30. package/dist/db/queries.js.map +1 -0
  31. package/dist/db/schema.sql +113 -0
  32. package/dist/db/sqlite-adapter.d.ts +30 -0
  33. package/dist/db/sqlite-adapter.d.ts.map +1 -0
  34. package/dist/db/sqlite-adapter.js +78 -0
  35. package/dist/db/sqlite-adapter.js.map +1 -0
  36. package/dist/directory.d.ts +37 -0
  37. package/dist/directory.d.ts.map +1 -0
  38. package/dist/directory.js +160 -0
  39. package/dist/directory.js.map +1 -0
  40. package/dist/errors.d.ts +46 -0
  41. package/dist/errors.d.ts.map +1 -0
  42. package/dist/errors.js +90 -0
  43. package/dist/errors.js.map +1 -0
  44. package/dist/graph/traversal.d.ts +157 -0
  45. package/dist/graph/traversal.d.ts.map +1 -0
  46. package/dist/graph/traversal.js +531 -0
  47. package/dist/graph/traversal.js.map +1 -0
  48. package/dist/index.d.ts +183 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +435 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/introspect/base.d.ts +62 -0
  53. package/dist/introspect/base.d.ts.map +1 -0
  54. package/dist/introspect/base.js +107 -0
  55. package/dist/introspect/base.js.map +1 -0
  56. package/dist/introspect/connection.d.ts +30 -0
  57. package/dist/introspect/connection.d.ts.map +1 -0
  58. package/dist/introspect/connection.js +232 -0
  59. package/dist/introspect/connection.js.map +1 -0
  60. package/dist/introspect/index.d.ts +23 -0
  61. package/dist/introspect/index.d.ts.map +1 -0
  62. package/dist/introspect/index.js +46 -0
  63. package/dist/introspect/index.js.map +1 -0
  64. package/dist/introspect/mysql.d.ts +64 -0
  65. package/dist/introspect/mysql.d.ts.map +1 -0
  66. package/dist/introspect/mysql.js +360 -0
  67. package/dist/introspect/mysql.js.map +1 -0
  68. package/dist/introspect/postgres.d.ts +55 -0
  69. package/dist/introspect/postgres.d.ts.map +1 -0
  70. package/dist/introspect/postgres.js +372 -0
  71. package/dist/introspect/postgres.js.map +1 -0
  72. package/dist/introspect/sqlite.d.ts +33 -0
  73. package/dist/introspect/sqlite.d.ts.map +1 -0
  74. package/dist/introspect/sqlite.js +207 -0
  75. package/dist/introspect/sqlite.js.map +1 -0
  76. package/dist/mcp/engine.d.ts +92 -0
  77. package/dist/mcp/engine.d.ts.map +1 -0
  78. package/dist/mcp/engine.js +261 -0
  79. package/dist/mcp/engine.js.map +1 -0
  80. package/dist/mcp/index.d.ts +33 -0
  81. package/dist/mcp/index.d.ts.map +1 -0
  82. package/dist/mcp/index.js +119 -0
  83. package/dist/mcp/index.js.map +1 -0
  84. package/dist/mcp/server-instructions.d.ts +9 -0
  85. package/dist/mcp/server-instructions.d.ts.map +1 -0
  86. package/dist/mcp/server-instructions.js +71 -0
  87. package/dist/mcp/server-instructions.js.map +1 -0
  88. package/dist/mcp/session.d.ts +35 -0
  89. package/dist/mcp/session.d.ts.map +1 -0
  90. package/dist/mcp/session.js +140 -0
  91. package/dist/mcp/session.js.map +1 -0
  92. package/dist/mcp/tools.d.ts +99 -0
  93. package/dist/mcp/tools.d.ts.map +1 -0
  94. package/dist/mcp/tools.js +499 -0
  95. package/dist/mcp/tools.js.map +1 -0
  96. package/dist/mcp/transport.d.ts +78 -0
  97. package/dist/mcp/transport.d.ts.map +1 -0
  98. package/dist/mcp/transport.js +182 -0
  99. package/dist/mcp/transport.js.map +1 -0
  100. package/dist/search/query-parser.d.ts +66 -0
  101. package/dist/search/query-parser.d.ts.map +1 -0
  102. package/dist/search/query-parser.js +163 -0
  103. package/dist/search/query-parser.js.map +1 -0
  104. package/dist/search/query-utils.d.ts +78 -0
  105. package/dist/search/query-utils.d.ts.map +1 -0
  106. package/dist/search/query-utils.js +203 -0
  107. package/dist/search/query-utils.js.map +1 -0
  108. package/dist/types.d.ts +279 -0
  109. package/dist/types.d.ts.map +1 -0
  110. package/dist/types.js +47 -0
  111. package/dist/types.js.map +1 -0
  112. package/dist/utils.d.ts +40 -0
  113. package/dist/utils.d.ts.map +1 -0
  114. package/dist/utils.js +190 -0
  115. package/dist/utils.js.map +1 -0
  116. package/package.json +54 -0
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ /**
3
+ * MCP Transport Layer
4
+ *
5
+ * JSON-RPC over stdin/stdout for direct mode (MCP stdio transport).
6
+ * JSON-RPC over Unix sockets / named pipes for daemon mode.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.SocketTransport = exports.StdioTransport = exports.ErrorCodes = void 0;
43
+ exports.getDaemonSocketPath = getDaemonSocketPath;
44
+ exports.getDaemonPidPath = getDaemonPidPath;
45
+ const path = __importStar(require("path"));
46
+ const os = __importStar(require("os"));
47
+ var ErrorCodes;
48
+ (function (ErrorCodes) {
49
+ ErrorCodes[ErrorCodes["ParseError"] = -32700] = "ParseError";
50
+ ErrorCodes[ErrorCodes["InvalidRequest"] = -32600] = "InvalidRequest";
51
+ ErrorCodes[ErrorCodes["MethodNotFound"] = -32601] = "MethodNotFound";
52
+ ErrorCodes[ErrorCodes["InvalidParams"] = -32602] = "InvalidParams";
53
+ ErrorCodes[ErrorCodes["InternalError"] = -32603] = "InternalError";
54
+ })(ErrorCodes || (exports.ErrorCodes = ErrorCodes = {}));
55
+ // =============================================================================
56
+ // Stdio Transport (direct MCP mode)
57
+ // =============================================================================
58
+ class StdioTransport {
59
+ handler = null;
60
+ buffer = '';
61
+ stopped = false;
62
+ start(handler) {
63
+ this.handler = handler;
64
+ process.stdin.on('data', this.onData);
65
+ process.stdin.on('end', this.onEnd);
66
+ process.stdin.setEncoding('utf-8');
67
+ }
68
+ onData = (chunk) => {
69
+ this.buffer += chunk;
70
+ const lines = this.buffer.split('\n');
71
+ this.buffer = lines.pop() ?? '';
72
+ for (const line of lines) {
73
+ const trimmed = line.trim();
74
+ if (!trimmed)
75
+ continue;
76
+ try {
77
+ const message = JSON.parse(trimmed);
78
+ this.handler?.(message);
79
+ }
80
+ catch {
81
+ this.sendError(0, ErrorCodes.ParseError, 'Failed to parse JSON');
82
+ }
83
+ }
84
+ };
85
+ onEnd = () => {
86
+ this.stopped = true;
87
+ };
88
+ sendResult(id, result) {
89
+ this.write({ jsonrpc: '2.0', id, result });
90
+ }
91
+ sendError(id, code, message, data) {
92
+ this.write({ jsonrpc: '2.0', id, error: { code, message, data } });
93
+ }
94
+ sendNotification(method, params) {
95
+ this.write({ jsonrpc: '2.0', method, params });
96
+ }
97
+ stop() {
98
+ this.stopped = true;
99
+ process.stdin.removeListener('data', this.onData);
100
+ process.stdin.removeListener('end', this.onEnd);
101
+ }
102
+ write(msg) {
103
+ if (this.stopped)
104
+ return;
105
+ const raw = JSON.stringify(msg) + '\n';
106
+ process.stdout.write(raw);
107
+ }
108
+ }
109
+ exports.StdioTransport = StdioTransport;
110
+ // =============================================================================
111
+ // Socket Transport (daemon mode)
112
+ // =============================================================================
113
+ class SocketTransport {
114
+ socket;
115
+ handler = null;
116
+ buffer = '';
117
+ stopped = false;
118
+ constructor(socket) {
119
+ this.socket = socket;
120
+ }
121
+ start(handler) {
122
+ this.handler = handler;
123
+ this.socket.on('data', this.onData);
124
+ this.socket.on('close', this.onClose);
125
+ this.socket.setEncoding('utf-8');
126
+ }
127
+ onData = (chunk) => {
128
+ this.buffer += chunk;
129
+ const lines = this.buffer.split('\n');
130
+ this.buffer = lines.pop() ?? '';
131
+ for (const line of lines) {
132
+ const trimmed = line.trim();
133
+ if (!trimmed)
134
+ continue;
135
+ try {
136
+ const message = JSON.parse(trimmed);
137
+ this.handler?.(message);
138
+ }
139
+ catch {
140
+ this.sendError(0, ErrorCodes.ParseError, 'Failed to parse JSON');
141
+ }
142
+ }
143
+ };
144
+ onClose = () => {
145
+ this.stopped = true;
146
+ };
147
+ sendResult(id, result) {
148
+ if (!this.stopped)
149
+ this.socket.write(JSON.stringify({ jsonrpc: '2.0', id, result }) + '\n');
150
+ }
151
+ sendError(id, code, message, data) {
152
+ if (!this.stopped)
153
+ this.socket.write(JSON.stringify({ jsonrpc: '2.0', id, error: { code, message, data } }) + '\n');
154
+ }
155
+ sendNotification(method, params) {
156
+ if (!this.stopped)
157
+ this.socket.write(JSON.stringify({ jsonrpc: '2.0', method, params }) + '\n');
158
+ }
159
+ stop() {
160
+ this.stopped = true;
161
+ this.socket.removeListener('data', this.onData);
162
+ this.socket.removeListener('close', this.onClose);
163
+ if (!this.socket.destroyed)
164
+ this.socket.destroy();
165
+ }
166
+ }
167
+ exports.SocketTransport = SocketTransport;
168
+ // =============================================================================
169
+ // Daemon path utilities
170
+ // =============================================================================
171
+ function getDaemonSocketPath(projectRoot) {
172
+ const dir = path.join(projectRoot, '.dbgraph');
173
+ // Use a hash to avoid path-length issues on Windows
174
+ const hash = Buffer.from(projectRoot).toString('base64').replace(/[/+=]/g, '_');
175
+ return os.platform() === 'win32'
176
+ ? path.join(dir, `dbgraph-${hash}.pipe`)
177
+ : path.join(dir, `dbgraph-${hash}.sock`);
178
+ }
179
+ function getDaemonPidPath(projectRoot) {
180
+ return path.join(projectRoot, '.dbgraph', 'daemon.pid');
181
+ }
182
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/mcp/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Query Parser
3
+ *
4
+ * Parses search queries for structured field filters. Users can narrow
5
+ * results by prefixing terms with field selectors:
6
+ *
7
+ * kind:table — filter by node kind (table, column, index, …)
8
+ * source:prod — filter by database source alias
9
+ * name:orders — filter by object name
10
+ *
11
+ * Examples:
12
+ * "kind:table name:orders" → text="" kinds=["table"] nameFilters=["orders"]
13
+ * "orders kind:column" → text="orders" kinds=["column"] nameFilters=[]
14
+ * "source:prod kind:table user" → text="user" kinds=["table"] sources=["prod"]
15
+ * "kind:table kind:index name:pk" → text="" kinds=["table","index"] nameFilters=["pk"]
16
+ */
17
+ export interface ParsedQuery {
18
+ /** The remaining query text after all field filters have been extracted */
19
+ text: string;
20
+ /** Values from `kind:` filters (e.g., ["table", "column"]) */
21
+ kinds: string[];
22
+ /** Values from `source:` filters (e.g., ["prod", "analytics"]) */
23
+ sources: string[];
24
+ /** Values from `name:` filters (e.g., ["orders", "users"]) */
25
+ nameFilters: string[];
26
+ }
27
+ /**
28
+ * Parse a search query and extract structured field filters.
29
+ *
30
+ * The parser scans tokens from left to right:
31
+ * 1. Tokens matching `kind:<value>` are collected in `kinds`.
32
+ * 2. Tokens matching `source:<value>` are collected in `sources`.
33
+ * 3. Tokens matching `name:<value>` are collected in `nameFilters`.
34
+ * 4. All remaining tokens (non-field-filter) are joined and returned as `text`.
35
+ *
36
+ * Filters are case-insensitive for the field prefix but preserve the
37
+ * value casing for downstream matching.
38
+ *
39
+ * @param input - Raw search query string (e.g., `kind:table name:orders`)
40
+ * @returns A ParsedQuery with extracted filters and remaining text.
41
+ */
42
+ export declare function parseQuery(input: string): ParsedQuery;
43
+ /**
44
+ * Apply a parsed query to build a concise search string and derived options.
45
+ *
46
+ * @returns A search string (suitable for QueryBuilder.searchNodes) and an
47
+ * optional set of SearchOptions overrides.
48
+ */
49
+ export interface AppliedQuery {
50
+ searchText: string;
51
+ filterKinds?: string[];
52
+ filterSource?: string;
53
+ filterName?: string;
54
+ }
55
+ /**
56
+ * Convert a ParsedQuery into inputs for QueryBuilder.searchNodes.
57
+ *
58
+ * The `source:` filter maps directly to SearchOptions.source.
59
+ * The `kind:` filter maps to SearchOptions.kinds.
60
+ * The `name:` filter, if present, produces additional LIKE clauses.
61
+ *
62
+ * @param parsed - The parsed query from parseQuery()
63
+ * @returns An AppliedQuery with the text and filter overrides.
64
+ */
65
+ export declare function applyParsedQuery(parsed: ParsedQuery): AppliedQuery;
66
+ //# sourceMappingURL=query-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-parser.d.ts","sourceRoot":"","sources":["../../src/search/query-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,MAAM,WAAW,WAAW;IAC1B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IAEb,8DAA8D;IAC9D,KAAK,EAAE,MAAM,EAAE,CAAC;IAEhB,kEAAkE;IAClE,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAgCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAgDrD;AAMD;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAmBlE"}
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ /**
3
+ * Query Parser
4
+ *
5
+ * Parses search queries for structured field filters. Users can narrow
6
+ * results by prefixing terms with field selectors:
7
+ *
8
+ * kind:table — filter by node kind (table, column, index, …)
9
+ * source:prod — filter by database source alias
10
+ * name:orders — filter by object name
11
+ *
12
+ * Examples:
13
+ * "kind:table name:orders" → text="" kinds=["table"] nameFilters=["orders"]
14
+ * "orders kind:column" → text="orders" kinds=["column"] nameFilters=[]
15
+ * "source:prod kind:table user" → text="user" kinds=["table"] sources=["prod"]
16
+ * "kind:table kind:index name:pk" → text="" kinds=["table","index"] nameFilters=["pk"]
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.parseQuery = parseQuery;
20
+ exports.applyParsedQuery = applyParsedQuery;
21
+ // =============================================================================
22
+ // Constants
23
+ // =============================================================================
24
+ /**
25
+ * Known database object kinds that are valid for `kind:` filters.
26
+ * Derived from the NODE_KINDS union in types.ts.
27
+ */
28
+ const VALID_KINDS = new Set([
29
+ 'server',
30
+ 'database',
31
+ 'schema',
32
+ 'table',
33
+ 'view',
34
+ 'column',
35
+ 'index',
36
+ 'trigger',
37
+ 'stored_procedure',
38
+ 'function',
39
+ 'sequence',
40
+ 'constraint',
41
+ 'foreign_key',
42
+ 'module',
43
+ 'namespace',
44
+ ]);
45
+ // =============================================================================
46
+ // parseQuery
47
+ // =============================================================================
48
+ /**
49
+ * Parse a search query and extract structured field filters.
50
+ *
51
+ * The parser scans tokens from left to right:
52
+ * 1. Tokens matching `kind:<value>` are collected in `kinds`.
53
+ * 2. Tokens matching `source:<value>` are collected in `sources`.
54
+ * 3. Tokens matching `name:<value>` are collected in `nameFilters`.
55
+ * 4. All remaining tokens (non-field-filter) are joined and returned as `text`.
56
+ *
57
+ * Filters are case-insensitive for the field prefix but preserve the
58
+ * value casing for downstream matching.
59
+ *
60
+ * @param input - Raw search query string (e.g., `kind:table name:orders`)
61
+ * @returns A ParsedQuery with extracted filters and remaining text.
62
+ */
63
+ function parseQuery(input) {
64
+ const result = {
65
+ text: '',
66
+ kinds: [],
67
+ sources: [],
68
+ nameFilters: [],
69
+ };
70
+ if (!input || input.trim().length === 0) {
71
+ return result;
72
+ }
73
+ // Normalize whitespace and split into tokens.
74
+ // Preserve quoted phrases as single tokens: `"order items"` stays together.
75
+ const tokens = tokenize(input);
76
+ const remainingTokens = [];
77
+ for (const token of tokens) {
78
+ // Try to match `field:value` patterns. Value can be quoted or unquoted.
79
+ const kindMatch = token.match(/^kind:(.+)$/i);
80
+ const sourceMatch = token.match(/^source:(.+)$/i);
81
+ const nameMatch = token.match(/^name:(.+)$/i);
82
+ if (kindMatch) {
83
+ const value = kindMatch[1].replace(/^["']|["']$/g, '').toLowerCase();
84
+ if (VALID_KINDS.has(value) && !result.kinds.includes(value)) {
85
+ result.kinds.push(value);
86
+ }
87
+ // Silently drop invalid kind values (don't add to remaining text)
88
+ }
89
+ else if (sourceMatch) {
90
+ const value = sourceMatch[1].replace(/^["']|["']$/g, '');
91
+ if (value.length > 0 && !result.sources.includes(value)) {
92
+ result.sources.push(value);
93
+ }
94
+ }
95
+ else if (nameMatch) {
96
+ const value = nameMatch[1].replace(/^["']|["']$/g, '');
97
+ if (value.length > 0 && !result.nameFilters.includes(value)) {
98
+ result.nameFilters.push(value);
99
+ }
100
+ }
101
+ else {
102
+ remainingTokens.push(token);
103
+ }
104
+ }
105
+ result.text = remainingTokens.join(' ').trim();
106
+ return result;
107
+ }
108
+ /**
109
+ * Convert a ParsedQuery into inputs for QueryBuilder.searchNodes.
110
+ *
111
+ * The `source:` filter maps directly to SearchOptions.source.
112
+ * The `kind:` filter maps to SearchOptions.kinds.
113
+ * The `name:` filter, if present, produces additional LIKE clauses.
114
+ *
115
+ * @param parsed - The parsed query from parseQuery()
116
+ * @returns An AppliedQuery with the text and filter overrides.
117
+ */
118
+ function applyParsedQuery(parsed) {
119
+ const result = {
120
+ searchText: parsed.text,
121
+ };
122
+ if (parsed.kinds.length > 0) {
123
+ result.filterKinds = parsed.kinds;
124
+ }
125
+ if (parsed.sources.length > 0) {
126
+ // Use the first source filter; multiple sources would need OR logic
127
+ result.filterSource = parsed.sources[0];
128
+ }
129
+ if (parsed.nameFilters.length > 0) {
130
+ result.filterName = parsed.nameFilters.join(' ');
131
+ }
132
+ return result;
133
+ }
134
+ // =============================================================================
135
+ // Tokenizer
136
+ // =============================================================================
137
+ /**
138
+ * Split input into tokens, respecting double-quoted and single-quoted phrases.
139
+ *
140
+ * "order items" → ["order items"]
141
+ * kind:table name:"order items" → ["kind:table", "name:order items"]
142
+ */
143
+ function tokenize(input) {
144
+ const tokens = [];
145
+ const trimmed = input.trim();
146
+ if (trimmed.length === 0)
147
+ return tokens;
148
+ const re = /(?:[^\s"']+|"[^"]*"|'[^']*')+/g;
149
+ let match;
150
+ while ((match = re.exec(trimmed)) !== null) {
151
+ let token = match[0];
152
+ // Strip surrounding quotes from the entire token if it's quoted
153
+ if ((token.startsWith('"') && token.endsWith('"')) ||
154
+ (token.startsWith("'") && token.endsWith("'"))) {
155
+ token = token.slice(1, -1);
156
+ }
157
+ if (token.length > 0) {
158
+ tokens.push(token);
159
+ }
160
+ }
161
+ return tokens;
162
+ }
163
+ //# sourceMappingURL=query-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-parser.js","sourceRoot":"","sources":["../../src/search/query-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Query Utilities
3
+ *
4
+ * Scoring and relevance helpers for search results. These functions provide
5
+ * small numeric boosts that can be composed with FTS5 scores to improve
6
+ * result ranking for database schema objects.
7
+ */
8
+ import { SearchResult } from '../types';
9
+ /**
10
+ * Boost score for certain node kinds.
11
+ *
12
+ * Tables and views get the highest boost (0.15), columns are next (0.12),
13
+ * indexes and constraints get a moderate boost (0.08), and utility objects
14
+ * like triggers / functions / sequences get a smaller boost (0.05–0.06).
15
+ * Schema and database container nodes get a minimal boost (0.03–0.04).
16
+ *
17
+ * @param kind - The node kind string (e.g., "table", "column", "index").
18
+ * @returns A bonus value in [0.02, 0.15] to add to the base score.
19
+ */
20
+ export declare function kindBonus(kind: string): number;
21
+ /**
22
+ * Boost score when the query matches part of the node's source path.
23
+ *
24
+ * The filePath field (stored as `source` in graph terminology) is a URI
25
+ * like `db://@prod/public` or `db://host:5432/dbname/schema`. When a
26
+ * query token matches part of this path, it indicates the user is
27
+ * narrowing their search to a specific database or schema.
28
+ *
29
+ * Matching logic:
30
+ * - Exact match of any path segment → 0.10 boost.
31
+ * - Prefix match of any path segment → 0.05 boost.
32
+ * - Substring match anywhere in path → 0.02 boost.
33
+ * - No match → 0.
34
+ *
35
+ * @param filePath - The node's source path (Node.filePath).
36
+ * @param query - The raw search query text.
37
+ * @returns A bonus value in [0, 0.10].
38
+ */
39
+ export declare function scorePathRelevance(filePath: string, query: string): number;
40
+ /**
41
+ * Boost exact name matches over prefix or substring matches.
42
+ *
43
+ * When a query token matches a node's name with different degrees of
44
+ * specificity, this function returns a higher bonus for closer matches:
45
+ *
46
+ * - Exact match (case-insensitive) → 0.20
47
+ * - Exact match of one token (multi-word) → 0.15
48
+ * - Prefix match (name starts with query) → 0.10
49
+ * - Substring match → 0.05
50
+ * - No match → 0
51
+ *
52
+ * @param name - The node's name (Node.name).
53
+ * @param query - The raw search query text.
54
+ * @returns A bonus value in [0, 0.20].
55
+ */
56
+ export declare function nameMatchBonus(name: string, query: string): number;
57
+ /**
58
+ * Compute an augmented score for a single search result by composing the
59
+ * base relevance score with the kind, path, and name bonuses.
60
+ *
61
+ * This is useful when re-ranking results after retrieving them from
62
+ * QueryBuilder.searchNodes.
63
+ *
64
+ * @param result - A SearchResult from QueryBuilder.
65
+ * @param query - The original query text (for name/path relevance).
66
+ * @returns A new score with all applicable bonuses added.
67
+ */
68
+ export declare function computeAugmentedScore(result: SearchResult, query: string): number;
69
+ /**
70
+ * Re-rank an array of SearchResults by their augmented score in
71
+ * descending order. Mutates the input array in place.
72
+ *
73
+ * @param results - Search results to re-rank.
74
+ * @param query - The original query text.
75
+ * @returns The same array (sorted in place) for chaining.
76
+ */
77
+ export declare function rerankResults(results: SearchResult[], query: string): SearchResult[];
78
+ //# sourceMappingURL=query-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-utils.d.ts","sourceRoot":"","sources":["../../src/search/query-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAmCxC;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAuC1E;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAiClE;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAOjF;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,EAAE,CAMpF"}