@bytebase/dbhub 0.21.1 → 0.21.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.
package/README.md CHANGED
@@ -119,8 +119,8 @@ See [Testing](.claude/skills/testing/SKILL.md) and [Debug](https://dbhub.ai/conf
119
119
 
120
120
  <a href="https://www.star-history.com/?repos=bytebase%2Fdbhub&type=date&legend=top-left">
121
121
  <picture>
122
- <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/image?repos=bytebase/dbhub&type=date&theme=dark&legend=top-left" />
123
- <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/image?repos=bytebase/dbhub&type=date&legend=top-left" />
124
- <img alt="Star History Chart" src="https://api.star-history.com/image?repos=bytebase/dbhub&type=date&legend=top-left" />
122
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=bytebase/dbhub&type=date&theme=dark&legend=top-left" />
123
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=bytebase/dbhub&type=date&legend=top-left" />
124
+ <img alt="Star History Chart" src="https://api.star-history.com/chart?repos=bytebase/dbhub&type=date&legend=top-left" />
125
125
  </picture>
126
126
  </a>
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isDriverNotInstalled
3
- } from "./chunk-GWPUVYLO.js";
3
+ } from "./chunk-WVVMH6FJ.js";
4
4
  import {
5
5
  ConnectorRegistry,
6
6
  SafeURL,
@@ -11,6 +11,13 @@ function isDriverNotInstalled(err, driver) {
11
11
  const missingSpecifier = match[1];
12
12
  return missingSpecifier === driver || missingSpecifier.startsWith(`${driver}/`);
13
13
  }
14
+ function isModuleNotFound(err) {
15
+ if (!(err instanceof Error) || !("code" in err)) {
16
+ return false;
17
+ }
18
+ const code = err.code;
19
+ return code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND";
20
+ }
14
21
  async function loadConnectors(connectorModules) {
15
22
  await Promise.all(
16
23
  connectorModules.map(async ({ load, name, driver }) => {
@@ -21,6 +28,13 @@ async function loadConnectors(connectorModules) {
21
28
  console.error(
22
29
  `Skipping ${name} connector: driver package "${driver}" not installed.`
23
30
  );
31
+ } else if (isModuleNotFound(err)) {
32
+ const msg = err instanceof Error ? err.message : String(err);
33
+ const match = msg.match(MISSING_MODULE_RE);
34
+ const missing = match ? match[1] : "unknown";
35
+ console.error(
36
+ `Skipping ${name} connector: required dependency "${missing}" not installed.`
37
+ );
24
38
  } else {
25
39
  throw err;
26
40
  }
package/dist/index.js CHANGED
@@ -12,10 +12,10 @@ import {
12
12
  resolveSourceConfigs,
13
13
  resolveTomlConfigPath,
14
14
  resolveTransport
15
- } from "./chunk-6JFMPX62.js";
15
+ } from "./chunk-7D6RKVK2.js";
16
16
  import {
17
17
  loadConnectors
18
- } from "./chunk-GWPUVYLO.js";
18
+ } from "./chunk-WVVMH6FJ.js";
19
19
  import {
20
20
  quoteQualifiedIdentifier
21
21
  } from "./chunk-JFWX35TB.js";
@@ -1421,7 +1421,7 @@ See documentation for more details on configuring database connections.
1421
1421
  const sources = sourceConfigsData.sources;
1422
1422
  console.error(`Configuration source: ${sourceConfigsData.source}`);
1423
1423
  await connectorManager.connectWithSources(sources);
1424
- const { initializeToolRegistry: initializeToolRegistry2 } = await import("./registry-I2JQWFDX.js");
1424
+ const { initializeToolRegistry: initializeToolRegistry2 } = await import("./registry-Y755MTUO.js");
1425
1425
  initializeToolRegistry2({
1426
1426
  sources: sourceConfigsData.sources,
1427
1427
  tools: sourceConfigsData.tools
@@ -1466,6 +1466,20 @@ See documentation for more details on configuring database connections.
1466
1466
  app.use(express.json());
1467
1467
  app.use((req, res, next) => {
1468
1468
  const origin = req.headers.origin;
1469
+ if (origin) {
1470
+ const host = (req.headers.host ?? "").split(":")[0].toLowerCase();
1471
+ try {
1472
+ const originHost = new URL(origin).hostname.toLowerCase();
1473
+ if (originHost !== host) {
1474
+ return res.status(403).json({
1475
+ error: "Forbidden",
1476
+ message: "Origin does not match Host header (DNS rebinding protection)"
1477
+ });
1478
+ }
1479
+ } catch {
1480
+ return res.status(400).json({ error: "Bad Request", message: "Malformed Origin header" });
1481
+ }
1482
+ }
1469
1483
  res.header("Access-Control-Allow-Origin", origin || "http://localhost");
1470
1484
  res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
1471
1485
  res.header("Access-Control-Allow-Headers", "Content-Type, Mcp-Session-Id");
@@ -1550,10 +1564,10 @@ See documentation for more details on configuring database connections.
1550
1564
  // src/index.ts
1551
1565
  var connectorModules = [
1552
1566
  { load: () => import("./postgres-4PCNQDGV.js"), name: "PostgreSQL", driver: "pg" },
1553
- { load: () => import("./sqlserver-JBR6X37Z.js"), name: "SQL Server", driver: "mssql" },
1567
+ { load: () => import("./sqlserver-YV3KVJ3B.js"), name: "SQL Server", driver: "mssql" },
1554
1568
  { load: () => import("./sqlite-FSCLCRIH.js"), name: "SQLite", driver: "better-sqlite3" },
1555
- { load: () => import("./mysql-I35IQ2GH.js"), name: "MySQL", driver: "mysql2" },
1556
- { load: () => import("./mariadb-VGTS4WXE.js"), name: "MariaDB", driver: "mariadb" }
1569
+ { load: () => import("./mysql-M4INQQ46.js"), name: "MySQL", driver: "mysql2" },
1570
+ { load: () => import("./mariadb-4IBCPIEV.js"), name: "MariaDB", driver: "mariadb" }
1557
1571
  ];
1558
1572
  loadConnectors(connectorModules).then(() => main()).catch((error) => {
1559
1573
  console.error("Fatal error:", error);
@@ -2,6 +2,9 @@ import {
2
2
  extractAffectedRows,
3
3
  parseQueryResults
4
4
  } from "./chunk-RTB262PR.js";
5
+ import {
6
+ quoteIdentifier
7
+ } from "./chunk-JFWX35TB.js";
5
8
  import {
6
9
  SQLRowLimiter
7
10
  } from "./chunk-BRXZ5ZQB.js";
@@ -352,10 +355,12 @@ var MariaDBConnector = class _MariaDBConnector {
352
355
  let definition = procedure.ROUTINE_DEFINITION;
353
356
  try {
354
357
  const schemaValue = schema || await this.getCurrentSchema();
358
+ const quotedSchema = quoteIdentifier(schemaValue, "mariadb");
359
+ const quotedProcName = quoteIdentifier(procedureName, "mariadb");
355
360
  if (procedure.procedure_type === "procedure") {
356
361
  try {
357
362
  const defRows = await this.pool.query(`
358
- SHOW CREATE PROCEDURE ${schemaValue}.${procedureName}
363
+ SHOW CREATE PROCEDURE ${quotedSchema}.${quotedProcName}
359
364
  `);
360
365
  if (defRows && defRows.length > 0) {
361
366
  definition = defRows[0]["Create Procedure"];
@@ -366,7 +371,7 @@ var MariaDBConnector = class _MariaDBConnector {
366
371
  } else {
367
372
  try {
368
373
  const defRows = await this.pool.query(`
369
- SHOW CREATE FUNCTION ${schemaValue}.${procedureName}
374
+ SHOW CREATE FUNCTION ${quotedSchema}.${quotedProcName}
370
375
  `);
371
376
  if (defRows && defRows.length > 0) {
372
377
  definition = defRows[0]["Create Function"];
@@ -2,6 +2,9 @@ import {
2
2
  extractAffectedRows,
3
3
  parseQueryResults
4
4
  } from "./chunk-RTB262PR.js";
5
+ import {
6
+ quoteIdentifier
7
+ } from "./chunk-JFWX35TB.js";
5
8
  import {
6
9
  SQLRowLimiter
7
10
  } from "./chunk-BRXZ5ZQB.js";
@@ -358,10 +361,12 @@ var MySQLConnector = class _MySQLConnector {
358
361
  let definition = procedure.ROUTINE_DEFINITION;
359
362
  try {
360
363
  const schemaValue = schema || await this.getCurrentSchema();
364
+ const quotedSchema = quoteIdentifier(schemaValue, "mysql");
365
+ const quotedProcName = quoteIdentifier(procedureName, "mysql");
361
366
  if (procedure.procedure_type === "procedure") {
362
367
  try {
363
368
  const [defRows] = await this.pool.query(`
364
- SHOW CREATE PROCEDURE ${schemaValue}.${procedureName}
369
+ SHOW CREATE PROCEDURE ${quotedSchema}.${quotedProcName}
365
370
  `);
366
371
  if (defRows && defRows.length > 0) {
367
372
  definition = defRows[0]["Create Procedure"];
@@ -372,7 +377,7 @@ var MySQLConnector = class _MySQLConnector {
372
377
  } else {
373
378
  try {
374
379
  const [defRows] = await this.pool.query(`
375
- SHOW CREATE FUNCTION ${schemaValue}.${procedureName}
380
+ SHOW CREATE FUNCTION ${quotedSchema}.${quotedProcName}
376
381
  `);
377
382
  if (defRows && defRows.length > 0) {
378
383
  definition = defRows[0]["Create Function"];
@@ -2,8 +2,8 @@ import {
2
2
  ToolRegistry,
3
3
  getToolRegistry,
4
4
  initializeToolRegistry
5
- } from "./chunk-6JFMPX62.js";
6
- import "./chunk-GWPUVYLO.js";
5
+ } from "./chunk-7D6RKVK2.js";
6
+ import "./chunk-WVVMH6FJ.js";
7
7
  import "./chunk-C7WEAPX4.js";
8
8
  export {
9
9
  ToolRegistry,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isDriverNotInstalled
3
- } from "./chunk-GWPUVYLO.js";
3
+ } from "./chunk-WVVMH6FJ.js";
4
4
  import {
5
5
  SQLRowLimiter
6
6
  } from "./chunk-BRXZ5ZQB.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytebase/dbhub",
3
- "version": "0.21.1",
3
+ "version": "0.21.2",
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": {