@pilat/mcp-datalink 1.0.3 → 1.2.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.
- package/README.md +30 -387
- package/dist/adapters/factory.d.ts +0 -4
- package/dist/adapters/factory.d.ts.map +1 -1
- package/dist/adapters/factory.js +3 -8
- package/dist/adapters/factory.js.map +1 -1
- package/dist/adapters/mysql/adapter.d.ts +2 -31
- package/dist/adapters/mysql/adapter.d.ts.map +1 -1
- package/dist/adapters/mysql/adapter.js +27 -283
- package/dist/adapters/mysql/adapter.js.map +1 -1
- package/dist/adapters/postgresql/adapter.d.ts +2 -22
- package/dist/adapters/postgresql/adapter.d.ts.map +1 -1
- package/dist/adapters/postgresql/adapter.js +18 -175
- package/dist/adapters/postgresql/adapter.js.map +1 -1
- package/dist/adapters/sqlite/adapter.d.ts +3 -25
- package/dist/adapters/sqlite/adapter.d.ts.map +1 -1
- package/dist/adapters/sqlite/adapter.js +65 -364
- package/dist/adapters/sqlite/adapter.js.map +1 -1
- package/dist/adapters/sqlite/pragma-check.d.ts +19 -0
- package/dist/adapters/sqlite/pragma-check.d.ts.map +1 -0
- package/dist/adapters/sqlite/pragma-check.js +25 -0
- package/dist/adapters/sqlite/pragma-check.js.map +1 -0
- package/dist/adapters/sqlite/url-parser.d.ts +34 -0
- package/dist/adapters/sqlite/url-parser.d.ts.map +1 -0
- package/dist/adapters/sqlite/url-parser.js +73 -0
- package/dist/adapters/sqlite/url-parser.js.map +1 -0
- package/dist/adapters/types.d.ts +10 -113
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/config/loader.d.ts +10 -7
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +20 -97
- package/dist/config/loader.js.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -9
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +113 -40
- package/dist/server.js.map +1 -1
- package/dist/tools/describe-table.d.ts +5 -6
- package/dist/tools/describe-table.d.ts.map +1 -1
- package/dist/tools/describe-table.js +65 -9
- package/dist/tools/describe-table.js.map +1 -1
- package/dist/tools/execute.d.ts +5 -6
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/execute.js +13 -11
- package/dist/tools/execute.js.map +1 -1
- package/dist/tools/explain.d.ts +5 -10
- package/dist/tools/explain.d.ts.map +1 -1
- package/dist/tools/explain.js +25 -26
- package/dist/tools/explain.js.map +1 -1
- package/dist/tools/list-databases.d.ts +5 -7
- package/dist/tools/list-databases.d.ts.map +1 -1
- package/dist/tools/list-databases.js +31 -0
- package/dist/tools/list-databases.js.map +1 -1
- package/dist/tools/list-tables.d.ts +5 -10
- package/dist/tools/list-tables.d.ts.map +1 -1
- package/dist/tools/list-tables.js +27 -9
- package/dist/tools/list-tables.js.map +1 -1
- package/dist/tools/query.d.ts +1 -6
- package/dist/tools/query.d.ts.map +1 -1
- package/dist/tools/query.js +7 -27
- package/dist/tools/query.js.map +1 -1
- package/dist/types.d.ts +39 -12
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/formatter.d.ts +7 -4
- package/dist/utils/formatter.d.ts.map +1 -1
- package/dist/utils/formatter.js +20 -10
- package/dist/utils/formatter.js.map +1 -1
- package/dist/utils/sql-parser.d.ts +51 -0
- package/dist/utils/sql-parser.d.ts.map +1 -0
- package/dist/utils/sql-parser.js +310 -0
- package/dist/utils/sql-parser.js.map +1 -0
- package/dist/utils/truncate.d.ts +4 -13
- package/dist/utils/truncate.d.ts.map +1 -1
- package/dist/utils/truncate.js +38 -18
- package/dist/utils/truncate.js.map +1 -1
- package/dist/utils/validation.d.ts +35 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +89 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +11 -13
- package/databases.example.json +0 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/tools/explain.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/tools/explain.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* list_databases tool - returns configured databases from config
|
|
3
3
|
*/
|
|
4
|
-
import type { Config } from '../types.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}>;
|
|
10
|
-
}
|
|
4
|
+
import type { Config, ListDatabasesResult } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Format ListDatabasesResult as Markdown table
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatListDatabasesResultAsMarkdown(result: ListDatabasesResult, config: Config): string;
|
|
11
9
|
/**
|
|
12
10
|
* Returns all configured databases with their readonly flags.
|
|
13
11
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-databases.d.ts","sourceRoot":"","sources":["../../src/tools/list-databases.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"list-databases.d.ts","sourceRoot":"","sources":["../../src/tools/list-databases.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAoB/D;;GAEG;AACH,wBAAgB,mCAAmC,CACjD,MAAM,EAAE,mBAAmB,EAC3B,MAAM,EAAE,MAAM,GACb,MAAM,CAaR;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAOjE"}
|
|
@@ -1,6 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* list_databases tool - returns configured databases from config
|
|
3
3
|
*/
|
|
4
|
+
import { formatAsMarkdownTable } from '../utils/formatter.js';
|
|
5
|
+
/**
|
|
6
|
+
* Extract database type from URL
|
|
7
|
+
*/
|
|
8
|
+
function getDatabaseType(url) {
|
|
9
|
+
if (url.startsWith('postgresql://') || url.startsWith('postgres://')) {
|
|
10
|
+
return 'postgresql';
|
|
11
|
+
}
|
|
12
|
+
if (url.startsWith('mysql://')) {
|
|
13
|
+
return 'mysql';
|
|
14
|
+
}
|
|
15
|
+
if (url.startsWith('sqlite://') || url.startsWith('sqlite:')) {
|
|
16
|
+
return 'sqlite';
|
|
17
|
+
}
|
|
18
|
+
return 'unknown';
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Format ListDatabasesResult as Markdown table
|
|
22
|
+
*/
|
|
23
|
+
export function formatListDatabasesResultAsMarkdown(result, config) {
|
|
24
|
+
if (result.databases.length === 0) {
|
|
25
|
+
return '_No databases configured_';
|
|
26
|
+
}
|
|
27
|
+
const headers = ['name', 'type', 'readonly'];
|
|
28
|
+
const rows = result.databases.map((db) => {
|
|
29
|
+
const dbConfig = config.databases[db.name];
|
|
30
|
+
const type = dbConfig ? getDatabaseType(dbConfig.url) : 'unknown';
|
|
31
|
+
return [db.name, type, db.readonly ? 'YES' : 'NO'];
|
|
32
|
+
});
|
|
33
|
+
return formatAsMarkdownTable(headers, rows);
|
|
34
|
+
}
|
|
4
35
|
/**
|
|
5
36
|
* Returns all configured databases with their readonly flags.
|
|
6
37
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-databases.js","sourceRoot":"","sources":["../../src/tools/list-databases.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"list-databases.js","sourceRoot":"","sources":["../../src/tools/list-databases.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACrE,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7D,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mCAAmC,CACjD,MAA2B,EAC3B,MAAc;IAEd,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,2BAA2B,CAAC;IACrC,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAClE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,OAAO,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5E,IAAI;QACJ,QAAQ,EAAE,QAAQ,CAAC,QAAQ;KAC5B,CAAC,CAAC,CAAC;IAEJ,OAAO,EAAE,SAAS,EAAE,CAAC;AACvB,CAAC"}
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* list_tables tool - lists tables in a database schema
|
|
3
3
|
*/
|
|
4
|
-
import type { Config,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export interface ListTablesResult {
|
|
10
|
-
tables: TableInfo[];
|
|
11
|
-
truncated: boolean;
|
|
12
|
-
totalAvailable?: number;
|
|
13
|
-
}
|
|
4
|
+
import type { Config, ListTablesParams, ListTablesResult } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Format ListTablesResult as Markdown table
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatListTablesResultAsMarkdown(result: ListTablesResult): string;
|
|
14
9
|
/**
|
|
15
10
|
* Lists tables and views in a database schema.
|
|
16
11
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-tables.d.ts","sourceRoot":"","sources":["../../src/tools/list-tables.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"list-tables.d.ts","sourceRoot":"","sources":["../../src/tools/list-tables.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAK9E;;GAEG;AACH,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAsBjF;AAGD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,gBAAgB,CAAC,CAyB3B"}
|
|
@@ -2,7 +2,32 @@
|
|
|
2
2
|
* list_tables tool - lists tables in a database schema
|
|
3
3
|
*/
|
|
4
4
|
import { createAdapter } from '../adapters/index.js';
|
|
5
|
-
import {
|
|
5
|
+
import { formatAsMarkdownTable } from '../utils/formatter.js';
|
|
6
|
+
/**
|
|
7
|
+
* Format ListTablesResult as Markdown table
|
|
8
|
+
*/
|
|
9
|
+
export function formatListTablesResultAsMarkdown(result) {
|
|
10
|
+
const parts = [];
|
|
11
|
+
if (result.tables.length > 0) {
|
|
12
|
+
const headers = ['name', 'schema', 'type', 'rows_estimate'];
|
|
13
|
+
const rows = result.tables.map((table) => [
|
|
14
|
+
table.name,
|
|
15
|
+
table.schema,
|
|
16
|
+
table.type,
|
|
17
|
+
table.rows_estimate !== null ? String(table.rows_estimate) : 'NULL',
|
|
18
|
+
]);
|
|
19
|
+
parts.push(formatAsMarkdownTable(headers, rows));
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
parts.push('_No tables found_');
|
|
23
|
+
}
|
|
24
|
+
if (result.truncated && result.totalAvailable !== undefined) {
|
|
25
|
+
parts.push('');
|
|
26
|
+
parts.push(`**Note:** Showing ${result.tables.length} of ${result.totalAvailable} tables`);
|
|
27
|
+
}
|
|
28
|
+
return parts.join('\n');
|
|
29
|
+
}
|
|
30
|
+
import { getValidatedDatabase } from '../utils/validation.js';
|
|
6
31
|
/**
|
|
7
32
|
* Lists tables and views in a database schema.
|
|
8
33
|
*
|
|
@@ -12,15 +37,8 @@ import { DbMcpError, ErrorCode } from '../utils/errors.js';
|
|
|
12
37
|
*/
|
|
13
38
|
export async function listTables(params, config) {
|
|
14
39
|
const maxTables = config.defaults.maxTables;
|
|
15
|
-
|
|
16
|
-
const dbConfig = config.databases[params.database];
|
|
17
|
-
if (!dbConfig) {
|
|
18
|
-
throw new DbMcpError(ErrorCode.DATABASE_NOT_FOUND, `Database "${params.database}" not found in configuration`, { database: params.database, available: Object.keys(config.databases) });
|
|
19
|
-
}
|
|
20
|
-
// Create adapter for this database
|
|
40
|
+
const dbConfig = getValidatedDatabase(params.database, config);
|
|
21
41
|
const adapter = createAdapter(dbConfig, config.defaults);
|
|
22
|
-
// Use provided schema or adapter's default schema
|
|
23
|
-
// PostgreSQL: "public", MySQL: database name, SQLite: "main"
|
|
24
42
|
const schema = params.schema ?? adapter.getDefaultSchema();
|
|
25
43
|
return adapter.withConnection(async (conn) => {
|
|
26
44
|
const result = await conn.listTables(schema, maxTables);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-tables.js","sourceRoot":"","sources":["../../src/tools/list-tables.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"list-tables.js","sourceRoot":"","sources":["../../src/tools/list-tables.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,MAAM,UAAU,gCAAgC,CAAC,MAAwB;IACvE,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI;YACV,KAAK,CAAC,MAAM;YACZ,KAAK,CAAC,IAAI;YACV,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM;SACpE,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,qBAAqB,MAAM,CAAC,MAAM,CAAC,MAAM,OAAO,MAAM,CAAC,cAAc,SAAS,CAAC,CAAC;IAC7F,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AACD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAwB,EACxB,MAAc;IAEd,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;IAC5C,MAAM,QAAQ,GAAG,oBAAoB,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAE3D,OAAO,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;QAChC,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QAC7C,MAAM,SAAS,GAAG,cAAc,GAAG,SAAS,CAAC;QAE7C,IAAI,SAAS,EAAE,CAAC;YACd,OAAO;gBACL,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC;gBACrC,SAAS,EAAE,IAAI;gBACf,cAAc;aACf,CAAC;QACJ,CAAC;QAED,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;SACjB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/tools/query.d.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Query tool for executing SELECT statements
|
|
3
3
|
*/
|
|
4
|
-
import type { Config, QueryResult } from '../types.js';
|
|
5
|
-
export interface QueryParams {
|
|
6
|
-
database: string;
|
|
7
|
-
sql: string;
|
|
8
|
-
params?: unknown[];
|
|
9
|
-
}
|
|
4
|
+
import type { Config, QueryParams, QueryResult } from '../types.js';
|
|
10
5
|
/**
|
|
11
6
|
* Format QueryResult as Markdown table followed by metadata
|
|
12
7
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAOpE;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAqBvE;AAED;;;;;;;;;GASG;AACH,wBAAsB,KAAK,CACzB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,WAAW,CAAC,CAmEtB"}
|
package/dist/tools/query.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Query tool for executing SELECT statements
|
|
3
3
|
*/
|
|
4
4
|
import { createAdapter } from '../adapters/index.js';
|
|
5
|
-
import { DbMcpError, ErrorCode } from '../utils/errors.js';
|
|
6
|
-
import { truncateRows, truncateCell, checkTotalSize } from '../utils/truncate.js';
|
|
7
5
|
import { formatAsMarkdownTable, formatValue } from '../utils/formatter.js';
|
|
6
|
+
import { truncateCell, truncateRows } from '../utils/truncate.js';
|
|
7
|
+
import { getValidatedDatabase, validateParamCount } from '../utils/validation.js';
|
|
8
8
|
/**
|
|
9
9
|
* Format QueryResult as Markdown table followed by metadata
|
|
10
10
|
*/
|
|
@@ -39,34 +39,23 @@ export function formatQueryResultAsMarkdown(result) {
|
|
|
39
39
|
*/
|
|
40
40
|
export async function query(params, config) {
|
|
41
41
|
const startTime = Date.now();
|
|
42
|
-
|
|
43
|
-
const dbConfig = config.databases[params.database];
|
|
44
|
-
if (!dbConfig) {
|
|
45
|
-
throw new DbMcpError(ErrorCode.DATABASE_NOT_FOUND, `Database "${params.database}" not found in configuration`, { database: params.database, available: Object.keys(config.databases) });
|
|
46
|
-
}
|
|
47
|
-
// Create adapter for this database
|
|
42
|
+
const dbConfig = getValidatedDatabase(params.database, config);
|
|
48
43
|
const adapter = createAdapter(dbConfig, config.defaults);
|
|
49
|
-
// Step 1: Validate that this is a SELECT query
|
|
50
44
|
adapter.validateQueryForTool(params.sql, 'query');
|
|
51
|
-
|
|
45
|
+
validateParamCount(params.sql, params.params ?? []);
|
|
52
46
|
const parsed = adapter.parseQuery(params.sql);
|
|
53
47
|
let sql = params.sql;
|
|
54
48
|
if (!parsed.hasLimit) {
|
|
55
|
-
// Get maxRows from database config or defaults
|
|
56
49
|
const maxRows = dbConfig?.maxRows ?? config.defaults.maxRows;
|
|
57
50
|
sql = adapter.injectLimit(params.sql, maxRows);
|
|
58
51
|
}
|
|
59
|
-
// Step 3: Convert placeholders for non-PostgreSQL dialects
|
|
60
|
-
// PostgreSQL uses $1, $2; MySQL/SQLite use ?
|
|
61
52
|
sql = adapter.convertPlaceholders(sql);
|
|
62
53
|
const result = await adapter.withConnection(async (conn) => {
|
|
63
54
|
return conn.query(sql, params.params ?? []);
|
|
64
55
|
});
|
|
65
56
|
const columns = result.fields.map((field) => field.name);
|
|
66
57
|
const rawRows = result.rows;
|
|
67
|
-
// Step 4: Format each cell value
|
|
68
58
|
let formattedRows = rawRows.map((row) => row.map((cell) => formatValue(cell)));
|
|
69
|
-
// Step 5: Truncate individual cells if over maxCellLength
|
|
70
59
|
let anyCellTruncated = false;
|
|
71
60
|
formattedRows = formattedRows.map((row) => row.map((cell) => {
|
|
72
61
|
const truncated = truncateCell(cell, config.defaults.maxCellLength);
|
|
@@ -75,19 +64,10 @@ export async function query(params, config) {
|
|
|
75
64
|
}
|
|
76
65
|
return truncated.value;
|
|
77
66
|
}));
|
|
78
|
-
// Step 6: Truncate rows if over maxRows
|
|
79
67
|
const { rows: truncatedRows, info: rowTruncationInfo } = truncateRows(formattedRows, config.defaults.maxRows);
|
|
80
|
-
|
|
81
|
-
const tableOutput = formatAsMarkdownTable(columns, truncatedRows);
|
|
82
|
-
const sizeInfo = checkTotalSize(tableOutput, config.defaults.maxTotalSize);
|
|
83
|
-
// Determine final truncation state
|
|
84
|
-
const truncated = rowTruncationInfo.truncated || anyCellTruncated || sizeInfo.truncated;
|
|
85
|
-
// Determine truncation reason (priority: maxTotalSize > maxRows > maxCellLength)
|
|
68
|
+
const truncated = rowTruncationInfo.truncated || anyCellTruncated;
|
|
86
69
|
let truncationReason;
|
|
87
|
-
if (
|
|
88
|
-
truncationReason = sizeInfo.truncationReason;
|
|
89
|
-
}
|
|
90
|
-
else if (rowTruncationInfo.truncated) {
|
|
70
|
+
if (rowTruncationInfo.truncated) {
|
|
91
71
|
truncationReason = rowTruncationInfo.truncationReason;
|
|
92
72
|
}
|
|
93
73
|
else if (anyCellTruncated) {
|
|
@@ -102,7 +82,7 @@ export async function query(params, config) {
|
|
|
102
82
|
truncationReason,
|
|
103
83
|
totalAvailable: rowTruncationInfo.totalAvailable,
|
|
104
84
|
returned: rowTruncationInfo.returned,
|
|
105
|
-
hint: rowTruncationInfo.hint
|
|
85
|
+
hint: rowTruncationInfo.hint,
|
|
106
86
|
executionTime,
|
|
107
87
|
};
|
|
108
88
|
}
|
package/dist/tools/query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -3,15 +3,10 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export type QueryType = 'select' | 'insert' | 'update' | 'delete' | 'other';
|
|
5
5
|
export interface ParsedQuery {
|
|
6
|
-
/** The type of SQL query */
|
|
7
6
|
type: QueryType;
|
|
8
|
-
/** Whether the query has a LIMIT clause (for SELECT queries) */
|
|
9
7
|
hasLimit: boolean;
|
|
10
|
-
/** Whether the query is dangerous (DROP, TRUNCATE, ALTER, etc.) */
|
|
11
8
|
isDangerous: boolean;
|
|
12
|
-
/** Reason why query is considered dangerous */
|
|
13
9
|
dangerousReason?: string;
|
|
14
|
-
/** The original SQL string */
|
|
15
10
|
sql: string;
|
|
16
11
|
}
|
|
17
12
|
export interface DatabaseConfig {
|
|
@@ -32,13 +27,6 @@ export interface Config {
|
|
|
32
27
|
databases: Record<string, DatabaseConfig>;
|
|
33
28
|
defaults: DefaultsConfig;
|
|
34
29
|
}
|
|
35
|
-
/** Raw config shape before defaults are applied */
|
|
36
|
-
export interface RawConfig {
|
|
37
|
-
databases?: Record<string, Partial<DatabaseConfig> & {
|
|
38
|
-
url: string;
|
|
39
|
-
}>;
|
|
40
|
-
defaults?: Partial<DefaultsConfig>;
|
|
41
|
-
}
|
|
42
30
|
export interface QueryResult {
|
|
43
31
|
columns: string[];
|
|
44
32
|
rows: unknown[][];
|
|
@@ -90,4 +78,43 @@ export interface TableInfo {
|
|
|
90
78
|
type: 'table' | 'view';
|
|
91
79
|
rows_estimate: number | null;
|
|
92
80
|
}
|
|
81
|
+
export interface ListDatabasesResult {
|
|
82
|
+
databases: Array<{
|
|
83
|
+
name: string;
|
|
84
|
+
readonly: boolean;
|
|
85
|
+
}>;
|
|
86
|
+
}
|
|
87
|
+
export interface ListTablesParams {
|
|
88
|
+
database: string;
|
|
89
|
+
schema?: string;
|
|
90
|
+
}
|
|
91
|
+
export interface ListTablesResult {
|
|
92
|
+
tables: TableInfo[];
|
|
93
|
+
truncated: boolean;
|
|
94
|
+
totalAvailable?: number;
|
|
95
|
+
}
|
|
96
|
+
export interface DescribeTableParams {
|
|
97
|
+
database: string;
|
|
98
|
+
table: string;
|
|
99
|
+
schema?: string;
|
|
100
|
+
}
|
|
101
|
+
export interface QueryParams {
|
|
102
|
+
database: string;
|
|
103
|
+
sql: string;
|
|
104
|
+
params?: unknown[];
|
|
105
|
+
}
|
|
106
|
+
export interface ExecuteParams {
|
|
107
|
+
database: string;
|
|
108
|
+
sql: string;
|
|
109
|
+
params?: unknown[];
|
|
110
|
+
}
|
|
111
|
+
export interface ExplainParams {
|
|
112
|
+
database: string;
|
|
113
|
+
sql: string;
|
|
114
|
+
analyze?: boolean;
|
|
115
|
+
}
|
|
116
|
+
export interface ExplainResult {
|
|
117
|
+
plan: string;
|
|
118
|
+
executionTime: number;
|
|
119
|
+
}
|
|
93
120
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE5E,MAAM,WAAW,WAAW;IAC1B,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
* Formatting utilities for query results
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* JSON replacer function that handles BigInt values by converting them to strings.
|
|
6
|
+
* This prevents "TypeError: Do not know how to serialize a BigInt" when using JSON.stringify.
|
|
7
7
|
*/
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function bigIntReplacer(_key: string, value: unknown): unknown;
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Safely stringify a value to JSON, handling BigInt values.
|
|
11
11
|
*/
|
|
12
|
+
export declare function safeJsonStringify(value: unknown): string;
|
|
13
|
+
/** Format a value for display (handles null, dates, objects, primitives) */
|
|
14
|
+
export declare function formatValue(value: unknown): string;
|
|
12
15
|
export declare function formatAsMarkdownTable(columns: string[], rows: (string | null)[][]): string;
|
|
13
16
|
//# sourceMappingURL=formatter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,
|
|
1
|
+
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAKpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAExD;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAsBlD;AASD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,GACxB,MAAM,CAyBR"}
|
package/dist/utils/formatter.js
CHANGED
|
@@ -2,9 +2,22 @@
|
|
|
2
2
|
* Formatting utilities for query results
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* JSON replacer function that handles BigInt values by converting them to strings.
|
|
6
|
+
* This prevents "TypeError: Do not know how to serialize a BigInt" when using JSON.stringify.
|
|
7
7
|
*/
|
|
8
|
+
export function bigIntReplacer(_key, value) {
|
|
9
|
+
if (typeof value === 'bigint') {
|
|
10
|
+
return value.toString();
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Safely stringify a value to JSON, handling BigInt values.
|
|
16
|
+
*/
|
|
17
|
+
export function safeJsonStringify(value) {
|
|
18
|
+
return JSON.stringify(value, bigIntReplacer);
|
|
19
|
+
}
|
|
20
|
+
/** Format a value for display (handles null, dates, objects, primitives) */
|
|
8
21
|
export function formatValue(value) {
|
|
9
22
|
if (value === null || value === undefined) {
|
|
10
23
|
return 'NULL';
|
|
@@ -19,19 +32,16 @@ export function formatValue(value) {
|
|
|
19
32
|
return value.toISOString();
|
|
20
33
|
}
|
|
21
34
|
if (typeof value === 'object') {
|
|
22
|
-
return
|
|
35
|
+
return safeJsonStringify(value);
|
|
23
36
|
}
|
|
24
37
|
return String(value);
|
|
25
38
|
}
|
|
26
|
-
/**
|
|
27
|
-
* Escape pipe characters in cell content for Markdown tables
|
|
28
|
-
*/
|
|
29
39
|
function escapeForMarkdown(value) {
|
|
30
|
-
return value
|
|
40
|
+
return value
|
|
41
|
+
.replace(/\|/g, '\\|')
|
|
42
|
+
.replace(/\r\n|\r|\n/g, ' ')
|
|
43
|
+
.replace(/`/g, '\\`');
|
|
31
44
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Format query results as a Markdown table
|
|
34
|
-
*/
|
|
35
45
|
export function formatAsMarkdownTable(columns, rows) {
|
|
36
46
|
if (columns.length === 0) {
|
|
37
47
|
return '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC5D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;IAC7B,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,
|
|
1
|
+
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,KAAc;IACzD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;AAC/C,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC5D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;IAC7B,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa;IACtC,OAAO,KAAK;SACT,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,OAAiB,EACjB,IAAyB;IAEzB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,aAAa;IACb,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;IACjE,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IAElD,gBAAgB;IAChB,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;IAChD,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IAErD,YAAY;IACZ,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;YAC5C,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified SQL Parser Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides SQL parsing and validation for PostgreSQL, MySQL, and SQLite
|
|
5
|
+
* using node-sql-parser library.
|
|
6
|
+
*/
|
|
7
|
+
import type { QueryType } from '../types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Supported SQL dialects
|
|
10
|
+
*/
|
|
11
|
+
export type SqlDialect = 'PostgreSQL' | 'MySQL' | 'SQLite';
|
|
12
|
+
/**
|
|
13
|
+
* Inject a LIMIT clause into a SELECT query if it doesn't have one
|
|
14
|
+
*
|
|
15
|
+
* @param sql - SQL query
|
|
16
|
+
* @param limit - Maximum number of rows
|
|
17
|
+
* @param dialect - SQL dialect
|
|
18
|
+
* @returns SQL with LIMIT clause
|
|
19
|
+
*/
|
|
20
|
+
export declare function injectLimit(sql: string, limit: number, dialect: SqlDialect): string;
|
|
21
|
+
/**
|
|
22
|
+
* Result of parsing a SQL query
|
|
23
|
+
*/
|
|
24
|
+
export interface ParseResult {
|
|
25
|
+
type: QueryType;
|
|
26
|
+
hasLimit: boolean;
|
|
27
|
+
isDangerous: boolean;
|
|
28
|
+
dangerousReason?: string;
|
|
29
|
+
sql: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parse and validate a SQL query
|
|
33
|
+
*
|
|
34
|
+
* @param sql - SQL query to parse
|
|
35
|
+
* @param dialect - SQL dialect
|
|
36
|
+
* @returns Parsed query information
|
|
37
|
+
* @throws DbMcpError if query is invalid or contains multiple statements
|
|
38
|
+
*/
|
|
39
|
+
export declare function parseQuery(sql: string, dialect: SqlDialect): ParseResult;
|
|
40
|
+
/**
|
|
41
|
+
* Validate that a parsed SQL query is appropriate for a specific tool
|
|
42
|
+
*
|
|
43
|
+
* This function contains the shared validation logic used by all database adapters.
|
|
44
|
+
* Adapters may perform additional adapter-specific checks before calling this.
|
|
45
|
+
*
|
|
46
|
+
* @param parsed - Parsed query result from parseQuery
|
|
47
|
+
* @param tool - Tool being used ('query' for SELECT, 'execute' for INSERT/UPDATE/DELETE)
|
|
48
|
+
* @throws DbMcpError if the query is not appropriate for the specified tool
|
|
49
|
+
*/
|
|
50
|
+
export declare function validateQueryForTool(parsed: ParseResult, tool: 'query' | 'execute'): void;
|
|
51
|
+
//# sourceMappingURL=sql-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-parser.d.ts","sourceRoot":"","sources":["../../src/utils/sql-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAI7C;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,OAAO,GAAG,QAAQ,CAAC;AA6J3D;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,MAAM,CAyCnF;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;CACb;AA6CD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,WAAW,CAwExE;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,OAAO,GAAG,SAAS,GACxB,IAAI,CA6CN"}
|