@bytebase/dbhub 1.1.0 → 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 +3 -3
- package/dist/{chunk-GSSLHJB6.js → chunk-CUBIR72I.js} +17 -1
- package/dist/{chunk-EPOKWSFC.js → chunk-PBN2UXB5.js} +1 -1
- package/dist/{chunk-NIILHXTG.js → chunk-QEFMUQJ2.js} +26 -37
- package/dist/{chunk-S2V6RZ3C.js → chunk-RSB7DPO2.js} +64 -3
- package/dist/{chunk-JEZZN2YZ.js → chunk-WIQ4DWGY.js} +16 -0
- package/dist/index.js +72 -25
- package/dist/{mariadb-DUDFBY5W.js → mariadb-E33EXGJZ.js} +7 -9
- package/dist/{mysql-265M3KBD.js → mysql-RLDQI3SJ.js} +56 -11
- package/dist/{postgres-5ZOFYV6X.js → postgres-6XY2GPQV.js} +19 -13
- package/dist/public/assets/{index-DBYlgGks.js → index-DOZ5HOZ9.js} +21 -20
- package/dist/public/index.html +1 -1
- package/dist/{registry-JYRRNC3E.js → registry-XMEJF7WW.js} +2 -2
- package/dist/{sqlite-5M7SDAQZ.js → sqlite-CZE6Z36Y.js} +14 -13
- package/dist/{sqlserver-PSAZRH7G.js → sqlserver-IIGRXGYK.js} +69 -13
- package/package.json +4 -2
package/dist/public/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>DBHub - Minimal Database MCP Server</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-DOZ5HOZ9.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-BJ-1UrcV.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
ToolRegistry,
|
|
3
3
|
getToolRegistry,
|
|
4
4
|
initializeToolRegistry
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-CUBIR72I.js";
|
|
6
6
|
import "./chunk-WVVMH6FJ.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-WIQ4DWGY.js";
|
|
8
8
|
export {
|
|
9
9
|
ToolRegistry,
|
|
10
10
|
getToolRegistry,
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
SQLRowLimiter,
|
|
6
6
|
closeQuietly
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-RSB7DPO2.js";
|
|
8
8
|
import {
|
|
9
9
|
ConnectorRegistry,
|
|
10
10
|
SafeURL,
|
|
11
11
|
obfuscateDSNPassword,
|
|
12
12
|
splitSQLStatements
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-WIQ4DWGY.js";
|
|
14
14
|
|
|
15
15
|
// src/connectors/sqlite/suppress-experimental-warning.ts
|
|
16
16
|
var installed = false;
|
|
@@ -340,10 +340,10 @@ var SQLiteConnector = class _SQLiteConnector {
|
|
|
340
340
|
if (isReadStatement) {
|
|
341
341
|
if (parameters && parameters.length > 0) {
|
|
342
342
|
const rows = this.prepare(processedStatement).all(...parameters);
|
|
343
|
-
return { rows, rowCount: rows.length };
|
|
343
|
+
return { resultSets: [{ sql: statements[0], rows, rowCount: rows.length }] };
|
|
344
344
|
} else {
|
|
345
345
|
const rows = this.prepare(processedStatement).all();
|
|
346
|
-
return { rows, rowCount: rows.length };
|
|
346
|
+
return { resultSets: [{ sql: statements[0], rows, rowCount: rows.length }] };
|
|
347
347
|
}
|
|
348
348
|
} else {
|
|
349
349
|
let result;
|
|
@@ -352,7 +352,9 @@ var SQLiteConnector = class _SQLiteConnector {
|
|
|
352
352
|
} else {
|
|
353
353
|
result = this.prepare(processedStatement).run();
|
|
354
354
|
}
|
|
355
|
-
return {
|
|
355
|
+
return {
|
|
356
|
+
resultSets: [{ sql: statements[0], rows: [], rowCount: Number(result.changes) }]
|
|
357
|
+
};
|
|
356
358
|
}
|
|
357
359
|
} else {
|
|
358
360
|
if (parameters && parameters.length > 0) {
|
|
@@ -368,24 +370,23 @@ var SQLiteConnector = class _SQLiteConnector {
|
|
|
368
370
|
writeStatements.push(statement);
|
|
369
371
|
}
|
|
370
372
|
}
|
|
371
|
-
|
|
373
|
+
const resultSets = [];
|
|
372
374
|
for (const statement of writeStatements) {
|
|
373
375
|
if (options.readonly) {
|
|
374
376
|
this.db.exec("PRAGMA query_only = ON");
|
|
375
377
|
}
|
|
376
378
|
const result = this.prepare(statement).run();
|
|
377
|
-
|
|
379
|
+
resultSets.push({ sql: statement, rows: [], rowCount: Number(result.changes) });
|
|
378
380
|
}
|
|
379
|
-
|
|
380
|
-
for (let statement of readStatements) {
|
|
381
|
+
for (const statement of readStatements) {
|
|
381
382
|
if (options.readonly) {
|
|
382
383
|
this.db.exec("PRAGMA query_only = ON");
|
|
383
384
|
}
|
|
384
|
-
|
|
385
|
-
const
|
|
386
|
-
|
|
385
|
+
const processedStatement = SQLRowLimiter.applyMaxRows(statement, options.maxRows);
|
|
386
|
+
const rows = this.prepare(processedStatement).all();
|
|
387
|
+
resultSets.push({ sql: statement, rows, rowCount: rows.length });
|
|
387
388
|
}
|
|
388
|
-
return {
|
|
389
|
+
return { resultSets };
|
|
389
390
|
}
|
|
390
391
|
} finally {
|
|
391
392
|
if (options.readonly) {
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
sqlServerDynamicSqlPattern,
|
|
4
4
|
sqlServerPassThroughKeywords,
|
|
5
5
|
sqlServerPassThroughPattern
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PBN2UXB5.js";
|
|
7
7
|
import {
|
|
8
8
|
isDriverNotInstalled
|
|
9
9
|
} from "./chunk-WVVMH6FJ.js";
|
|
@@ -14,13 +14,14 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
SQLRowLimiter,
|
|
16
16
|
closeQuietly
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-RSB7DPO2.js";
|
|
18
18
|
import {
|
|
19
19
|
ConnectorRegistry,
|
|
20
20
|
SafeURL,
|
|
21
21
|
obfuscateDSNPassword,
|
|
22
|
+
splitSQLStatements,
|
|
22
23
|
stripCommentsAndStrings
|
|
23
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-WIQ4DWGY.js";
|
|
24
25
|
|
|
25
26
|
// src/connectors/sqlserver/index.ts
|
|
26
27
|
import sql from "mssql";
|
|
@@ -564,8 +565,9 @@ var _SQLServerConnector = class _SQLServerConnector {
|
|
|
564
565
|
if (options.maxRows) {
|
|
565
566
|
processedSQL = SQLRowLimiter.applyMaxRowsForSQLServer(sqlQuery, options.maxRows);
|
|
566
567
|
}
|
|
568
|
+
const isSingleStatement = splitSQLStatements(processedSQL, "sqlserver").length === 1;
|
|
567
569
|
if (options.readonly) {
|
|
568
|
-
return await this.executeReadOnly(processedSQL, parameters);
|
|
570
|
+
return await this.executeReadOnly(processedSQL, parameters, isSingleStatement);
|
|
569
571
|
}
|
|
570
572
|
const request = this.connection.request();
|
|
571
573
|
const messages = [];
|
|
@@ -584,14 +586,57 @@ var _SQLServerConnector = class _SQLServerConnector {
|
|
|
584
586
|
_SQLServerConnector.bindParameters(request, parameters);
|
|
585
587
|
const result = await request.query(processedSQL);
|
|
586
588
|
return {
|
|
587
|
-
|
|
588
|
-
|
|
589
|
+
resultSets: _SQLServerConnector.buildResultSets(
|
|
590
|
+
result.recordsets,
|
|
591
|
+
result.rowsAffected,
|
|
592
|
+
isSingleStatement ? processedSQL : void 0
|
|
593
|
+
),
|
|
589
594
|
...messages.length > 0 ? { messages } : {}
|
|
590
595
|
};
|
|
591
596
|
} catch (error) {
|
|
592
597
|
throw new Error(`Failed to execute query: ${error.message}`);
|
|
593
598
|
}
|
|
594
599
|
}
|
|
600
|
+
/**
|
|
601
|
+
* Builds one result set per SELECT-producing statement in the batch, plus
|
|
602
|
+
* (if any) a trailing result set summarizing the write-only statements.
|
|
603
|
+
*
|
|
604
|
+
* node-mssql only pushes a `recordsets` entry for statements that produce
|
|
605
|
+
* columns (SELECT); INSERT/UPDATE/DELETE statements in the same batch
|
|
606
|
+
* contribute to `rowsAffected` only, with no way to recover which
|
|
607
|
+
* `rowsAffected` entry belongs to which statement from the driver's final
|
|
608
|
+
* arrays (`recordsets`/`rowsAffected` aren't index-aligned - see the
|
|
609
|
+
* tedious `doneHandler`, which always pushes to `rowsAffected` but only
|
|
610
|
+
* conditionally to `recordsets`). So a batch of pure writes collapses to a
|
|
611
|
+
* single summed result set, and a batch mixing writes with selects gets
|
|
612
|
+
* one result set per select plus one trailing "writes" set for the rest -
|
|
613
|
+
* not a truly per-statement breakdown, but no read statement's rows are
|
|
614
|
+
* ever merged with another's, which is what mattered for #380.
|
|
615
|
+
*
|
|
616
|
+
* `sourceSql`, when given, is attributed to the single resulting set - it
|
|
617
|
+
* must be omitted (pass `undefined`) unless the caller has already
|
|
618
|
+
* confirmed the batch is unambiguously one statement, since for a genuine
|
|
619
|
+
* multi-statement batch there's no reliable way to say which source
|
|
620
|
+
* statement a given recordset (or the trailing writes set) came from.
|
|
621
|
+
*/
|
|
622
|
+
static buildResultSets(recordsets, rowsAffected, sourceSql) {
|
|
623
|
+
const sets = (recordsets ?? []).map((recordset) => {
|
|
624
|
+
const rows = recordset ?? [];
|
|
625
|
+
return { rows, rowCount: rows.length };
|
|
626
|
+
});
|
|
627
|
+
const totalAffected = (rowsAffected ?? []).reduce((total, count) => total + (count ?? 0), 0);
|
|
628
|
+
const accountedFor = sets.reduce((total, set) => total + set.rowCount, 0);
|
|
629
|
+
const writesOnly = totalAffected - accountedFor;
|
|
630
|
+
if (sets.length === 0) {
|
|
631
|
+
sets.push({ rows: [], rowCount: totalAffected });
|
|
632
|
+
} else if (writesOnly > 0) {
|
|
633
|
+
sets.push({ rows: [], rowCount: writesOnly });
|
|
634
|
+
}
|
|
635
|
+
if (sets.length === 1 && sourceSql !== void 0) {
|
|
636
|
+
sets[0].sql = sourceSql;
|
|
637
|
+
}
|
|
638
|
+
return sets;
|
|
639
|
+
}
|
|
595
640
|
/**
|
|
596
641
|
* Bind positional parameters as @p1, @p2, ... inferring the SQL Server type
|
|
597
642
|
* from each JavaScript value. Shared by every execution path so they cannot
|
|
@@ -673,7 +718,7 @@ var _SQLServerConnector = class _SQLServerConnector {
|
|
|
673
718
|
* Dangerous constructs are rejected before the transaction opens; see
|
|
674
719
|
* assertNoReadOnlyEscapes.
|
|
675
720
|
*/
|
|
676
|
-
async executeReadOnly(processedSQL, parameters) {
|
|
721
|
+
async executeReadOnly(processedSQL, parameters, isSingleStatement) {
|
|
677
722
|
this.assertNoReadOnlyEscapes(processedSQL, { transactionControl: true });
|
|
678
723
|
const transaction = new sql.Transaction(this.connection);
|
|
679
724
|
await transaction.begin();
|
|
@@ -710,8 +755,11 @@ var _SQLServerConnector = class _SQLServerConnector {
|
|
|
710
755
|
}
|
|
711
756
|
}
|
|
712
757
|
return {
|
|
713
|
-
|
|
714
|
-
|
|
758
|
+
resultSets: _SQLServerConnector.buildResultSets(
|
|
759
|
+
result.recordsets,
|
|
760
|
+
result.rowsAffected,
|
|
761
|
+
isSingleStatement ? processedSQL : void 0
|
|
762
|
+
),
|
|
715
763
|
...messages.length > 0 ? { messages } : {}
|
|
716
764
|
};
|
|
717
765
|
}
|
|
@@ -756,8 +804,12 @@ var _SQLServerConnector = class _SQLServerConnector {
|
|
|
756
804
|
const planRow = planResult.recordset?.[0];
|
|
757
805
|
const planXml = planRow ? Object.values(planRow)[0] : null;
|
|
758
806
|
return {
|
|
759
|
-
|
|
760
|
-
|
|
807
|
+
resultSets: [
|
|
808
|
+
{
|
|
809
|
+
rows: planXml != null ? [{ plan: planXml }] : [],
|
|
810
|
+
rowCount: planXml != null ? 1 : 0
|
|
811
|
+
}
|
|
812
|
+
]
|
|
761
813
|
};
|
|
762
814
|
} catch (error) {
|
|
763
815
|
throw new Error(`Failed to explain query: ${error.message}`);
|
|
@@ -878,8 +930,12 @@ var _SQLServerConnector = class _SQLServerConnector {
|
|
|
878
930
|
}
|
|
879
931
|
const planXml = _SQLServerConnector.extractPlanXml(planResult);
|
|
880
932
|
return {
|
|
881
|
-
|
|
882
|
-
|
|
933
|
+
resultSets: [
|
|
934
|
+
{
|
|
935
|
+
rows: planXml != null ? [{ plan: planXml }] : [],
|
|
936
|
+
rowCount: planXml != null ? 1 : 0
|
|
937
|
+
}
|
|
938
|
+
]
|
|
883
939
|
};
|
|
884
940
|
} catch (error) {
|
|
885
941
|
throw new Error(`Failed to explain analyze query: ${error.message}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bytebase/dbhub",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"mcpName": "io.github.bytebase/dbhub",
|
|
5
5
|
"description": "Minimal, token-efficient Database MCP Server for PostgreSQL, MySQL, SQL Server, SQLite, MariaDB",
|
|
6
6
|
"repository": {
|
|
@@ -33,7 +33,9 @@
|
|
|
33
33
|
"test:unit": "vitest run --project unit",
|
|
34
34
|
"test:watch": "vitest",
|
|
35
35
|
"test:integration": "vitest run --project integration",
|
|
36
|
-
"test:build": "node scripts/smoke-test-build.mjs"
|
|
36
|
+
"test:build": "node scripts/smoke-test-build.mjs",
|
|
37
|
+
"sync-version": "node scripts/sync-version.mjs",
|
|
38
|
+
"version": "pnpm run sync-version && git add plugin/.claude-plugin/plugin.json plugin/.mcp.json server.json"
|
|
37
39
|
},
|
|
38
40
|
"engines": {
|
|
39
41
|
"node": ">=22.5.0"
|