@nifrajs/mcp-db 3.5.0 → 4.0.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.
@@ -0,0 +1,273 @@
1
+ /**
2
+ * A Postgres tokenizer for the parser layer of `@nifrajs/mcp-db/postgres`. It is the SECOND layer: the
3
+ * server already refuses several statements (extended protocol), anything but a query (the cursor),
4
+ * and writes (the read-only transaction). This layer adds what the server allows but a dev agent must
5
+ * not do: call a function that reaches outside the query (server files, locks, other sessions,
6
+ * settings, notifications, another database), or one that runs SQL from a string where the plan check
7
+ * cannot see it (`query_to_xml`).
8
+ *
9
+ * The lexer follows Postgres with `standard_conforming_strings = on`, which the engine sets on every
10
+ * connection so the server reads string boundaries exactly as this lexer does.
11
+ */
12
+ const WORD_START = /[A-Za-z_\u0080-￿]/;
13
+ const WORD_PART = /[A-Za-z0-9_$\u0080-￿]/;
14
+ const DOLLAR_TAG = /^\$(?:[A-Za-z_\u0080-￿][A-Za-z0-9_\u0080-￿]*)?\$/;
15
+ /** Tokenize Postgres SQL far enough to see statements, parentheses and function calls. */
16
+ export function lexPostgres(sql) {
17
+ const tokens = [];
18
+ let unterminated = false;
19
+ let unicodeIdentifier = false;
20
+ let i = 0;
21
+ const skipString = (escapes) => {
22
+ i++; // past the opening quote
23
+ while (i < sql.length) {
24
+ const char = sql[i];
25
+ if (escapes && char === "\\") {
26
+ i += 2;
27
+ continue;
28
+ }
29
+ if (char === "'") {
30
+ if (sql[i + 1] === "'") {
31
+ i += 2;
32
+ continue;
33
+ }
34
+ i++;
35
+ return;
36
+ }
37
+ i++;
38
+ }
39
+ unterminated = true;
40
+ };
41
+ while (i < sql.length) {
42
+ const char = sql.charAt(i);
43
+ const next = sql[i + 1];
44
+ if (/\s/.test(char)) {
45
+ i++;
46
+ }
47
+ else if (char === "-" && next === "-") {
48
+ const end = sql.indexOf("\n", i);
49
+ i = end === -1 ? sql.length : end + 1;
50
+ }
51
+ else if (char === "/" && next === "*") {
52
+ // Postgres block comments nest.
53
+ let depth = 1;
54
+ i += 2;
55
+ while (i < sql.length && depth > 0) {
56
+ if (sql[i] === "/" && sql[i + 1] === "*") {
57
+ depth++;
58
+ i += 2;
59
+ }
60
+ else if (sql[i] === "*" && sql[i + 1] === "/") {
61
+ depth--;
62
+ i += 2;
63
+ }
64
+ else
65
+ i++;
66
+ }
67
+ if (depth > 0)
68
+ unterminated = true;
69
+ }
70
+ else if (char === "'") {
71
+ skipString(false);
72
+ }
73
+ else if ((char === "E" || char === "e") && next === "'") {
74
+ i++;
75
+ skipString(true);
76
+ }
77
+ else if ((char === "U" || char === "u") && next === "&" && sql[i + 2] === "'") {
78
+ i += 2;
79
+ skipString(false);
80
+ }
81
+ else if ((char === "U" || char === "u") && next === "&" && sql[i + 2] === '"') {
82
+ unicodeIdentifier = true;
83
+ i += 2;
84
+ }
85
+ else if ((char === "B" ||
86
+ char === "b" ||
87
+ char === "X" ||
88
+ char === "x" ||
89
+ char === "N" ||
90
+ char === "n") &&
91
+ next === "'") {
92
+ i++;
93
+ skipString(false);
94
+ }
95
+ else if (char === '"') {
96
+ const offset = i;
97
+ let value = "";
98
+ let closed = false;
99
+ i++;
100
+ while (i < sql.length) {
101
+ if (sql[i] === '"') {
102
+ if (sql[i + 1] === '"') {
103
+ value += '"';
104
+ i += 2;
105
+ continue;
106
+ }
107
+ i++;
108
+ closed = true;
109
+ break;
110
+ }
111
+ value += sql[i];
112
+ i++;
113
+ }
114
+ if (!closed)
115
+ unterminated = true;
116
+ tokens.push({ kind: "word", value, bare: false, offset });
117
+ }
118
+ else if (char === "$") {
119
+ const tag = DOLLAR_TAG.exec(sql.slice(i, i + 64))?.[0];
120
+ if (tag !== undefined) {
121
+ const end = sql.indexOf(tag, i + tag.length);
122
+ if (end === -1) {
123
+ unterminated = true;
124
+ i = sql.length;
125
+ }
126
+ else
127
+ i = end + tag.length;
128
+ }
129
+ else if (next !== undefined && next >= "0" && next <= "9") {
130
+ const start = i;
131
+ i++;
132
+ while (i < sql.length && /[0-9]/.test(sql.charAt(i)))
133
+ i++;
134
+ tokens.push({ kind: "param", value: sql.slice(start, i), bare: false, offset: start });
135
+ }
136
+ else {
137
+ tokens.push({ kind: "punct", value: char, bare: false, offset: i });
138
+ i++;
139
+ }
140
+ }
141
+ else if (WORD_START.test(char)) {
142
+ const start = i;
143
+ while (i < sql.length && WORD_PART.test(sql.charAt(i)))
144
+ i++;
145
+ tokens.push({ kind: "word", value: sql.slice(start, i), bare: true, offset: start });
146
+ }
147
+ else if ((char >= "0" && char <= "9") ||
148
+ (char === "." && next !== undefined && /[0-9]/.test(next))) {
149
+ // Digits only: a letter right after a number starts a new word, so `1pg_sleep(` still shows
150
+ // the call (older servers lex it the same way).
151
+ const start = i;
152
+ while (i < sql.length && /[0-9_.]/.test(sql.charAt(i)))
153
+ i++;
154
+ if ((sql[i] === "e" || sql[i] === "E") && /[0-9+-]/.test(sql[i + 1] ?? "")) {
155
+ i += 2;
156
+ while (i < sql.length && /[0-9]/.test(sql.charAt(i)))
157
+ i++;
158
+ }
159
+ tokens.push({ kind: "number", value: sql.slice(start, i), bare: false, offset: start });
160
+ }
161
+ else {
162
+ tokens.push({ kind: "punct", value: char, bare: false, offset: i });
163
+ i++;
164
+ }
165
+ }
166
+ return { tokens, unterminated, unicodeIdentifier };
167
+ }
168
+ /**
169
+ * Function-name prefixes the parser layer refuses. Each reaches outside a read-only query or runs SQL
170
+ * from a string the plan check cannot see; the server lets a read-only transaction call most of them.
171
+ */
172
+ export const DENIED_FUNCTION_PREFIXES = [
173
+ "dblink",
174
+ "lo_",
175
+ "pg_read_",
176
+ "pg_ls_",
177
+ "pg_stat_file",
178
+ "pg_terminate_backend",
179
+ "pg_cancel_backend",
180
+ "pg_reload_conf",
181
+ "set_config",
182
+ "pg_advisory",
183
+ "pg_try_advisory",
184
+ "pg_notify",
185
+ "query_to_xml",
186
+ "table_to_xml",
187
+ "cursor_to_xml",
188
+ "schema_to_xml",
189
+ "database_to_xml",
190
+ "pg_file_",
191
+ "pg_logical_emit_message",
192
+ "pg_stat_reset",
193
+ "pg_stat_get_",
194
+ "pg_switch_wal",
195
+ "pg_create_restore_point",
196
+ "pg_promote",
197
+ "pg_rotate_logfile",
198
+ "nextval",
199
+ "setval",
200
+ ];
201
+ const READ_HEADS = new Set(["select", "with", "values", "table"]);
202
+ const LOCKING_STRENGTHS = new Set(["update", "share", "no", "key"]);
203
+ /**
204
+ * Lint one statement: a single read-only query with balanced parentheses, no unicode-escaped
205
+ * identifier and no denied function call. `undefined` when it passes.
206
+ */
207
+ export function lintPostgres(sql) {
208
+ const { tokens, unterminated, unicodeIdentifier } = lexPostgres(sql);
209
+ if (unterminated) {
210
+ return { kind: "statement", message: "the statement has an unterminated string or comment" };
211
+ }
212
+ if (unicodeIdentifier) {
213
+ return { kind: "statement", message: 'unicode-escaped identifiers (U&"...") are not accepted' };
214
+ }
215
+ const terminator = tokens.findIndex((token) => token.kind === "punct" && token.value === ";");
216
+ if (terminator !== -1 && tokens.slice(terminator + 1).length > 0) {
217
+ return { kind: "statement", message: "only a single statement is allowed" };
218
+ }
219
+ const body = terminator === -1 ? tokens : tokens.slice(0, terminator);
220
+ const head = body.find((token) => !(token.kind === "punct" && token.value === "("));
221
+ if (head === undefined)
222
+ return { kind: "statement", message: "empty query" };
223
+ if (!head.bare || !READ_HEADS.has(head.value.toLowerCase())) {
224
+ return {
225
+ kind: "statement",
226
+ message: `only a read-only query (SELECT, WITH, VALUES or TABLE) is allowed, not ${head.value.toUpperCase()}`,
227
+ };
228
+ }
229
+ let depth = 0;
230
+ for (const [index, token] of body.entries()) {
231
+ if (token.kind !== "punct" && token.kind !== "word")
232
+ continue;
233
+ const next = body[index + 1];
234
+ if (token.bare &&
235
+ token.value.toLowerCase() === "for" &&
236
+ next?.bare === true &&
237
+ LOCKING_STRENGTHS.has(next.value.toLowerCase())) {
238
+ return {
239
+ kind: "statement",
240
+ message: "row-locking clauses (FOR UPDATE, FOR SHARE) are refused: they take locks",
241
+ };
242
+ }
243
+ if (token.value === "(" && token.kind === "punct") {
244
+ depth++;
245
+ const callee = body[index - 1];
246
+ if (callee?.kind === "word") {
247
+ const name = callee.value.toLowerCase();
248
+ if (DENIED_FUNCTION_PREFIXES.some((prefix) => name.startsWith(prefix))) {
249
+ return {
250
+ kind: "function",
251
+ name,
252
+ message: `${name}() is refused: it reaches outside a read-only query`,
253
+ };
254
+ }
255
+ }
256
+ }
257
+ else if (token.value === ")" && token.kind === "punct") {
258
+ depth--;
259
+ if (depth < 0) {
260
+ return { kind: "statement", message: "the statement closes a parenthesis it never opened" };
261
+ }
262
+ }
263
+ }
264
+ if (depth !== 0)
265
+ return { kind: "statement", message: "the statement leaves a parenthesis open" };
266
+ return undefined;
267
+ }
268
+ /** The statement without a final `;` (comments after it included), ready to wrap in a subquery. */
269
+ export function withoutTerminator(sql) {
270
+ const last = lexPostgres(sql).tokens.at(-1);
271
+ return last?.kind === "punct" && last.value === ";" ? sql.slice(0, last.offset) : sql;
272
+ }
273
+ //# sourceMappingURL=pg-lexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg-lexer.js","sourceRoot":"","sources":["../../src/internal/pg-lexer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAqBH,MAAM,UAAU,GAAG,mBAAmB,CAAA;AACtC,MAAM,SAAS,GAAG,uBAAuB,CAAA;AACzC,MAAM,UAAU,GAAG,kDAAkD,CAAA;AAErE,0FAA0F;AAC1F,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,MAAM,GAAc,EAAE,CAAA;IAC5B,IAAI,YAAY,GAAG,KAAK,CAAA;IACxB,IAAI,iBAAiB,GAAG,KAAK,CAAA;IAC7B,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,MAAM,UAAU,GAAG,CAAC,OAAgB,EAAQ,EAAE;QAC5C,CAAC,EAAE,CAAA,CAAC,yBAAyB;QAC7B,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAA;YACnB,IAAI,OAAO,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAC7B,CAAC,IAAI,CAAC,CAAA;gBACN,SAAQ;YACV,CAAC;YACD,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACjB,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;oBACvB,CAAC,IAAI,CAAC,CAAA;oBACN,SAAQ;gBACV,CAAC;gBACD,CAAC,EAAE,CAAA;gBACH,OAAM;YACR,CAAC;YACD,CAAC,EAAE,CAAA;QACL,CAAC;QACD,YAAY,GAAG,IAAI,CAAA;IACrB,CAAC,CAAA;IACD,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAC1B,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QACvB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACpB,CAAC,EAAE,CAAA;QACL,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;YAChC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAA;QACvC,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxC,gCAAgC;YAChC,IAAI,KAAK,GAAG,CAAC,CAAA;YACb,CAAC,IAAI,CAAC,CAAA;YACN,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACnC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;oBACzC,KAAK,EAAE,CAAA;oBACP,CAAC,IAAI,CAAC,CAAA;gBACR,CAAC;qBAAM,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;oBAChD,KAAK,EAAE,CAAA;oBACP,CAAC,IAAI,CAAC,CAAA;gBACR,CAAC;;oBAAM,CAAC,EAAE,CAAA;YACZ,CAAC;YACD,IAAI,KAAK,GAAG,CAAC;gBAAE,YAAY,GAAG,IAAI,CAAA;QACpC,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxB,UAAU,CAAC,KAAK,CAAC,CAAA;QACnB,CAAC;aAAM,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YAC1D,CAAC,EAAE,CAAA;YACH,UAAU,CAAC,IAAI,CAAC,CAAA;QAClB,CAAC;aAAM,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAChF,CAAC,IAAI,CAAC,CAAA;YACN,UAAU,CAAC,KAAK,CAAC,CAAA;QACnB,CAAC;aAAM,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAChF,iBAAiB,GAAG,IAAI,CAAA;YACxB,CAAC,IAAI,CAAC,CAAA;QACR,CAAC;aAAM,IACL,CAAC,IAAI,KAAK,GAAG;YACX,IAAI,KAAK,GAAG;YACZ,IAAI,KAAK,GAAG;YACZ,IAAI,KAAK,GAAG;YACZ,IAAI,KAAK,GAAG;YACZ,IAAI,KAAK,GAAG,CAAC;YACf,IAAI,KAAK,GAAG,EACZ,CAAC;YACD,CAAC,EAAE,CAAA;YACH,UAAU,CAAC,KAAK,CAAC,CAAA;QACnB,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,CAAC,CAAA;YAChB,IAAI,KAAK,GAAG,EAAE,CAAA;YACd,IAAI,MAAM,GAAG,KAAK,CAAA;YAClB,CAAC,EAAE,CAAA;YACH,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;gBACtB,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;oBACnB,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;wBACvB,KAAK,IAAI,GAAG,CAAA;wBACZ,CAAC,IAAI,CAAC,CAAA;wBACN,SAAQ;oBACV,CAAC;oBACD,CAAC,EAAE,CAAA;oBACH,MAAM,GAAG,IAAI,CAAA;oBACb,MAAK;gBACP,CAAC;gBACD,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,CAAA;gBACf,CAAC,EAAE,CAAA;YACL,CAAC;YACD,IAAI,CAAC,MAAM;gBAAE,YAAY,GAAG,IAAI,CAAA;YAChC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QAC3D,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;YACtD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACtB,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAA;gBAC5C,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;oBACf,YAAY,GAAG,IAAI,CAAA;oBACnB,CAAC,GAAG,GAAG,CAAC,MAAM,CAAA;gBAChB,CAAC;;oBAAM,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,MAAM,CAAA;YAC7B,CAAC;iBAAM,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC;gBAC5D,MAAM,KAAK,GAAG,CAAC,CAAA;gBACf,CAAC,EAAE,CAAA;gBACH,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;oBAAE,CAAC,EAAE,CAAA;gBACzD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;YACxF,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;gBACnE,CAAC,EAAE,CAAA;YACL,CAAC;QACH,CAAC;aAAM,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,CAAC,CAAA;YACf,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBAAE,CAAC,EAAE,CAAA;YAC3D,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;QACtF,CAAC;aAAM,IACL,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC;YAC5B,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAC1D,CAAC;YACD,4FAA4F;YAC5F,gDAAgD;YAChD,MAAM,KAAK,GAAG,CAAC,CAAA;YACf,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBAAE,CAAC,EAAE,CAAA;YAC3D,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;gBAC3E,CAAC,IAAI,CAAC,CAAA;gBACN,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;oBAAE,CAAC,EAAE,CAAA;YAC3D,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;QACzF,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;YACnE,CAAC,EAAE,CAAA;QACL,CAAC;IACH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAA;AACpD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAsB;IACzD,QAAQ;IACR,KAAK;IACL,UAAU;IACV,QAAQ;IACR,cAAc;IACd,sBAAsB;IACtB,mBAAmB;IACnB,gBAAgB;IAChB,YAAY;IACZ,aAAa;IACb,iBAAiB;IACjB,WAAW;IACX,cAAc;IACd,cAAc;IACd,eAAe;IACf,eAAe;IACf,iBAAiB;IACjB,UAAU;IACV,yBAAyB;IACzB,eAAe;IACf,cAAc;IACd,eAAe;IACf,yBAAyB;IACzB,YAAY;IACZ,mBAAmB;IACnB,SAAS;IACT,QAAQ;CACT,CAAA;AAED,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;AACjE,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAA;AAOnE;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,iBAAiB,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,CAAA;IACpE,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,qDAAqD,EAAE,CAAA;IAC9F,CAAC;IACD,IAAI,iBAAiB,EAAE,CAAC;QACtB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,wDAAwD,EAAE,CAAA;IACjG,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,KAAK,KAAK,GAAG,CAAC,CAAA;IAC7F,IAAI,UAAU,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAA;IAC7E,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;IACrE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC,CAAA;IACnF,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,CAAA;IAC5E,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QAC5D,OAAO;YACL,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,0EAA0E,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE;SAC9G,CAAA;IACH,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,SAAQ;QAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;QAC5B,IACE,KAAK,CAAC,IAAI;YACV,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,KAAK;YACnC,IAAI,EAAE,IAAI,KAAK,IAAI;YACnB,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,EAC/C,CAAC;YACD,OAAO;gBACL,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,0EAA0E;aACpF,CAAA;QACH,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAClD,KAAK,EAAE,CAAA;YACP,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;YAC9B,IAAI,MAAM,EAAE,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAA;gBACvC,IAAI,wBAAwB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;oBACvE,OAAO;wBACL,IAAI,EAAE,UAAU;wBAChB,IAAI;wBACJ,OAAO,EAAE,GAAG,IAAI,qDAAqD;qBACtE,CAAA;gBACH,CAAC;YACH,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,CAAC,KAAK,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACzD,KAAK,EAAE,CAAA;YACP,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACd,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,oDAAoD,EAAE,CAAA;YAC7F,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,yCAAyC,EAAE,CAAA;IACjG,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3C,OAAO,IAAI,EAAE,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;AACvF,CAAC"}
@@ -0,0 +1,161 @@
1
+ /**
2
+ * What both database engines share and the MCP layer reuses: the refusal codes, the SQLite statement
3
+ * gates, the caps and the JSON-safe result shape. No runtime imports, so `@nifrajs/mcp-db` itself
4
+ * stays free of `node:*` modules; `engine.ts` re-exports all of it.
5
+ */
6
+ /** The structural slice of `bun:sqlite`'s `Database` this package needs. */
7
+ export interface SqliteDatabaseLike {
8
+ /** Prepare a statement; `all` runs it and returns row objects. */
9
+ prepare(sql: string): {
10
+ all(...params: unknown[]): unknown[];
11
+ };
12
+ /** Execute a statement for its side effect (used only for `PRAGMA query_only`). */
13
+ run(sql: string): unknown;
14
+ /** Optional path this database was opened from; a file-backed one can be reopened read-only in a
15
+ * worker so `run_query` runs off the serving connection. `:memory:` and the empty anonymous
16
+ * database cannot, and run in process. */
17
+ readonly filename?: string;
18
+ }
19
+ /** Every reason a database call is refused or fails, as a stable code. */
20
+ export type DbRefusalCode = "NIFRA_DB_NOT_DECLARED" | "NIFRA_DB_CONFIG" | "NIFRA_DB_OUTSIDE_ROOT" | "NIFRA_DB_REMOTE_HOST" | "NIFRA_DB_SUPERUSER" | "NIFRA_DB_EXTENSION" | "NIFRA_DB_QUERY_OFF" | "NIFRA_DB_WRITE_REFUSED" | "NIFRA_DB_FUNCTION_REFUSED" | "NIFRA_DB_TABLE_EXCLUDED" | "NIFRA_DB_COLUMN_REFUSED" | "NIFRA_DB_TIMEOUT" | "NIFRA_DB_QUERY_FAILED" | "NIFRA_DB_DRIVER";
21
+ /** A refused or failed call: what happened, the fix, and its anchor under `https://nifra.dev/docs/`. */
22
+ export interface DbRefusal {
23
+ readonly code: DbRefusalCode;
24
+ readonly message: string;
25
+ readonly fix: string;
26
+ readonly docsAnchor: string;
27
+ }
28
+ /** Build a {@link DbRefusal} for `code` with its fix and docs anchor. */
29
+ export declare function dbRefusal(code: DbRefusalCode, message: string): DbRefusal;
30
+ /** True for a value {@link dbRefusal} built. */
31
+ export declare function isDbRefusal(value: unknown): value is DbRefusal;
32
+ /** Reject multi-statement input: allow one terminator only when it is the final character. */
33
+ /**
34
+ * Names a statement defines as CTEs, column lists included (`WITH RECURSIVE c(x) AS (...)`), which
35
+ * {@link gateSqliteStatement}'s relation scan does not see past. Only for callers whose own check of
36
+ * the compiled statement is the authority on real tables: a CTE that reads a table still opens it.
37
+ */
38
+ export declare function sqliteCteNames(sql: string): string[];
39
+ /** The outcome of {@link gateSqliteStatement}. A refusal's `text` is the message `run_query` returns. */
40
+ export type SqliteGate = {
41
+ readonly ok: true;
42
+ readonly query: string;
43
+ } | {
44
+ readonly ok: false;
45
+ readonly reason: "empty" | "multiple" | "not-read" | "unexposed";
46
+ readonly text: string;
47
+ readonly relation?: string;
48
+ };
49
+ /**
50
+ * Gate one statement before SQLite sees it: non-empty, a single statement, SELECT/WITH only, and every
51
+ * relation it names after `FROM`/`JOIN` exposed. Returns the statement without its terminator, ready
52
+ * to wrap. Relation names are checked here as well as in the plan because SQLite's plan names an
53
+ * alias as the scan target (`users AS habits` plans as `SCAN habits`).
54
+ */
55
+ export declare function gateSqliteStatement(input: string, exposed: (relation: string) => boolean): SqliteGate;
56
+ /**
57
+ * The first relation an `EXPLAIN QUERY PLAN` result scans or searches that `exposed` rejects, as the
58
+ * plan spells it, or `undefined` when every scanned relation is exposed.
59
+ */
60
+ export declare function unexposedPlanRelation(planRows: readonly {
61
+ readonly detail?: unknown;
62
+ }[], exposed: (relation: string) => boolean): string | undefined;
63
+ /** Wrap a gated query so SQLite materializes at most one row beyond `maxRows`. */
64
+ export declare function boundedSqliteQuery(query: string, maxRows: number): string;
65
+ /** Wrap a gated query to count its rows (re-executes it). */
66
+ export declare function countSqliteQuery(query: string): string;
67
+ /**
68
+ * Serialize `build(shown)` for the largest `shown <= count` (halving from `count`) whose JSON fits
69
+ * `maxBytes`. `undefined` when even `build(0)` does not fit.
70
+ */
71
+ export declare function fitToBytes<T>(count: number, build: (shown: number) => T, maxBytes: number): {
72
+ readonly value: T;
73
+ readonly serialized: string;
74
+ readonly shown: number;
75
+ } | undefined;
76
+ /** What keeps secrets out of a result: which columns to mask, and how to scrub text. */
77
+ export interface DbRedaction {
78
+ /** True for a column (or a key inside a JSON value) whose values must not leave the process. */
79
+ readonly column?: (name: string) => boolean;
80
+ /** Scrub one string value: key formats, tokens, environment values. */
81
+ readonly text?: (value: string) => string;
82
+ }
83
+ /** The value a masked cell carries. */
84
+ export declare const REDACTED_CELL = "[redacted]";
85
+ /**
86
+ * One database value as JSON: bytes become `<n bytes>`, a bigint outside the safe range a string,
87
+ * a date an ISO string, a non-finite number a string. Strings go through `redaction.text`, and a
88
+ * key inside a JSON value that `redaction.column` matches is masked.
89
+ */
90
+ export declare function toJsonCell(value: unknown, redaction?: DbRedaction, depth?: number): unknown;
91
+ /** Options for {@link shapeRows}. */
92
+ export interface ShapeRowsOptions {
93
+ readonly maxRows: number;
94
+ readonly maxResultBytes: number;
95
+ readonly redaction?: DbRedaction;
96
+ }
97
+ /** Rows ready to leave the process: capped, masked and JSON-safe. */
98
+ export interface DbRows {
99
+ readonly columns: readonly string[];
100
+ readonly rows: readonly (readonly unknown[])[];
101
+ readonly rowCount: number;
102
+ /** More rows exist than `rows` carries (the row cap or the byte cap cut them). */
103
+ readonly truncated: boolean;
104
+ /** Columns whose values were replaced by {@link REDACTED_CELL}. */
105
+ readonly redactedColumns: readonly string[];
106
+ }
107
+ /**
108
+ * Cap, mask and normalize rows fetched as arrays (at most `maxRows + 1`, so truncation is known
109
+ * without counting). The byte cap halves the row count until the JSON fits.
110
+ */
111
+ export declare function shapeRows(columns: readonly string[], rows: readonly (readonly unknown[])[], options: ShapeRowsOptions): DbRows;
112
+ /** A plan for a statement, as the engine reports it. */
113
+ export interface DbPlan {
114
+ readonly plan: unknown;
115
+ /** True when the plan carries actual timings (Postgres `EXPLAIN ANALYZE`). */
116
+ readonly analyzed: boolean;
117
+ readonly truncated: boolean;
118
+ }
119
+ /** A column in {@link DbSchemaTable}. */
120
+ export interface DbSchemaColumn {
121
+ readonly name: string;
122
+ readonly type: string;
123
+ readonly nullable: boolean;
124
+ readonly default: string | null;
125
+ readonly primaryKey: boolean;
126
+ /** Query results mask this column's values. */
127
+ readonly redacted: boolean;
128
+ }
129
+ /** A foreign key in {@link DbSchemaTable}. */
130
+ export interface DbSchemaForeignKey {
131
+ readonly columns: readonly string[];
132
+ readonly references: {
133
+ readonly schema?: string;
134
+ readonly table: string;
135
+ readonly columns: readonly string[];
136
+ };
137
+ }
138
+ /** An index in {@link DbSchemaTable}. */
139
+ export interface DbSchemaIndex {
140
+ readonly name: string;
141
+ readonly columns: readonly string[];
142
+ readonly unique: boolean;
143
+ }
144
+ /** One exposed table or view. */
145
+ export interface DbSchemaTable {
146
+ readonly schema?: string;
147
+ readonly name: string;
148
+ readonly kind: "table" | "view" | "materialized view" | "foreign table" | "partitioned table";
149
+ /** Rows, estimated by the engine's statistics; `null` when it keeps none. */
150
+ readonly rowEstimate: number | null;
151
+ readonly columns: readonly DbSchemaColumn[];
152
+ readonly foreignKeys: readonly DbSchemaForeignKey[];
153
+ readonly indexes: readonly DbSchemaIndex[];
154
+ }
155
+ /** The exposed schema, built only from catalog queries the engine writes itself. */
156
+ export interface DbSchemaReport {
157
+ readonly tables: readonly DbSchemaTable[];
158
+ /** Relations left out: named in `exclude`, or (Postgres) inheriting from or reading one. */
159
+ readonly excludedCount: number;
160
+ }
161
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/internal/shared.ts"],"names":[],"mappings":"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"}