@dbx-app/node-core 0.4.4 → 0.4.5

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/dist/database.js CHANGED
@@ -4,6 +4,7 @@ import { join } from "node:path";
4
4
  import { homedir, platform } from "node:os";
5
5
  import Database from "better-sqlite3";
6
6
  import { sqlSafetyFromEnv } from "./sql-safety.js";
7
+ import { isDirectQueryType } from "./diagnostics.js";
7
8
  const MAX_ROWS = 100;
8
9
  const IDLE_TIMEOUT_MS = 5 * 60 * 1000;
9
10
  const QUERY_TIMEOUT_MS = 30_000;
@@ -194,19 +195,6 @@ function portBytes(port) {
194
195
  function isMysqlType(dbType) {
195
196
  return dbType === "mysql" || dbType === "doris" || dbType === "starrocks";
196
197
  }
197
- function isDirectType(dbType) {
198
- switch (dbType) {
199
- case "postgres":
200
- case "redshift":
201
- case "mysql":
202
- case "doris":
203
- case "starrocks":
204
- case "sqlite":
205
- return true;
206
- default:
207
- return false;
208
- }
209
- }
210
198
  function bridgeAppDataDir() {
211
199
  const home = homedir();
212
200
  switch (platform()) {
@@ -366,7 +354,7 @@ export async function executeQuery(config, sql, options) {
366
354
  }
367
355
  throw new Error("Use MongoDB shell-style commands, for example: db.projects.find({}).limit(100), db.projects.countDocuments({}), db.projects.insertOne({...}), db.projects.updateOne({...}, {$set: {...}}), or db.projects.deleteOne({...})");
368
356
  }
369
- if (isDirectType(config.db_type)) {
357
+ if (isDirectQueryType(config.db_type)) {
370
358
  return query(config, sql, undefined, options);
371
359
  }
372
360
  const result = await withTimeout(bridgeDataRequest("/data/execute-query", {
@@ -389,7 +377,7 @@ export async function listTables(config, schema) {
389
377
  const result = await query(config, `SELECT name, type FROM sqlite_master WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%' ORDER BY name`);
390
378
  return result.rows.map((r) => ({ name: String(r.name || ""), type: String(r.type || "table") }));
391
379
  }
392
- if (!isDirectType(config.db_type)) {
380
+ if (!isDirectQueryType(config.db_type)) {
393
381
  const tables = await bridgeDataRequest("/data/list-tables", {
394
382
  connection_name: config.name,
395
383
  database: config.database || "",
@@ -422,7 +410,7 @@ export async function describeTable(config, table, schema) {
422
410
  comment: null,
423
411
  }));
424
412
  }
425
- if (!isDirectType(config.db_type)) {
413
+ if (!isDirectQueryType(config.db_type)) {
426
414
  const columns = await bridgeDataRequest("/data/describe-table", {
427
415
  connection_name: config.name,
428
416
  database: config.database || "",
@@ -1,4 +1,6 @@
1
1
  export declare const DIRECT_QUERY_TYPES: readonly ["postgres", "redshift", "mysql", "doris", "starrocks", "sqlite", "gaussdb", "opengauss"];
2
+ export type DirectQueryType = (typeof DIRECT_QUERY_TYPES)[number];
3
+ export declare function isDirectQueryType(dbType: string): dbType is DirectQueryType;
2
4
  export declare const BRIDGE_REQUIRED_TYPES: readonly ["redis", "mongodb", "duckdb", "clickhouse", "sqlserver", "oracle", "elasticsearch", "dameng", "kingbase", "highgo", "vastbase", "goldendb", "yashandb", "databricks", "saphana", "teradata", "vertica", "firebird", "exasol", "oceanbase-oracle", "gbase", "tdengine", "h2", "snowflake", "trino", "hive", "db2", "informix", "neo4j", "cassandra", "bigquery", "kylin", "sundb", "xugu", "jdbc", "access"];
3
5
  export interface DbxDiagnostics {
4
6
  appDataDir: string;
@@ -2,6 +2,10 @@ import { access, readFile } from "node:fs/promises";
2
2
  import { bridgePortFilePath, dbPath, appDataDir } from "./paths.js";
3
3
  import { inspectConnectionStore } from "./connections.js";
4
4
  export const DIRECT_QUERY_TYPES = ["postgres", "redshift", "mysql", "doris", "starrocks", "sqlite", "gaussdb", "opengauss"];
5
+ const DIRECT_QUERY_TYPE_SET = new Set(DIRECT_QUERY_TYPES);
6
+ export function isDirectQueryType(dbType) {
7
+ return DIRECT_QUERY_TYPE_SET.has(dbType);
8
+ }
5
9
  export const BRIDGE_REQUIRED_TYPES = [
6
10
  "redis",
7
11
  "mongodb",
@@ -0,0 +1 @@
1
+ export declare function isMainModule(moduleUrl: string, argvPath: string | undefined): boolean;
@@ -0,0 +1,20 @@
1
+ import { realpathSync } from "node:fs";
2
+ import { normalize, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ export function isMainModule(moduleUrl, argvPath) {
5
+ if (!argvPath)
6
+ return false;
7
+ return normalizeEntryPath(fileURLToPath(moduleUrl)) === normalizeEntryPath(argvPath);
8
+ }
9
+ function normalizeEntryPath(path) {
10
+ const normalized = normalize(realpathIfPossible(resolve(path)));
11
+ return process.platform === "win32" ? normalized.toLowerCase() : normalized;
12
+ }
13
+ function realpathIfPossible(path) {
14
+ try {
15
+ return realpathSync.native(path);
16
+ }
17
+ catch {
18
+ return path;
19
+ }
20
+ }
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from "./bridge.js";
3
3
  export * from "./connections.js";
4
4
  export * from "./database.js";
5
5
  export * from "./diagnostics.js";
6
+ export * from "./entrypoint.js";
6
7
  export * from "./format.js";
7
8
  export * from "./paths.js";
8
9
  export * from "./schema-context.js";
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ export * from "./bridge.js";
3
3
  export * from "./connections.js";
4
4
  export * from "./database.js";
5
5
  export * from "./diagnostics.js";
6
+ export * from "./entrypoint.js";
6
7
  export * from "./format.js";
7
8
  export * from "./paths.js";
8
9
  export * from "./schema-context.js";
@@ -1,6 +1,7 @@
1
1
  export interface SqlSafetyOptions {
2
2
  allowWrites?: boolean;
3
3
  allowDangerous?: boolean;
4
+ allowMultipleStatements?: boolean;
4
5
  }
5
6
  export interface SqlSafetyDecision {
6
7
  allowed: boolean;
@@ -8,3 +9,4 @@ export interface SqlSafetyDecision {
8
9
  }
9
10
  export declare function evaluateSqlSafety(sql: string, options?: SqlSafetyOptions): SqlSafetyDecision;
10
11
  export declare function sqlSafetyFromEnv(env?: NodeJS.ProcessEnv): SqlSafetyOptions;
12
+ export declare function splitSqlStatements(sql: string): string[];
@@ -4,9 +4,24 @@ export function evaluateSqlSafety(sql, options = {}) {
4
4
  const statements = splitSqlStatements(sql);
5
5
  if (statements.length === 0)
6
6
  return { allowed: false, reason: "SQL is empty." };
7
- if (statements.length > 1)
8
- return { allowed: false, reason: "Only one SQL statement is allowed per MCP query." };
9
- const normalized = stripSqlCommentsAndStrings(statements[0]).trim();
7
+ if (statements.length > 1 && !options.allowMultipleStatements) {
8
+ return { allowed: false, reason: "Only one SQL statement is allowed per query." };
9
+ }
10
+ for (let i = 0; i < statements.length; i++) {
11
+ const decision = evaluateSingleSqlStatementSafety(statements[i], options);
12
+ if (!decision.allowed && statements.length > 1) {
13
+ return {
14
+ allowed: false,
15
+ reason: `Statement ${i + 1}: ${decision.reason ?? "SQL blocked."}`,
16
+ };
17
+ }
18
+ if (!decision.allowed)
19
+ return decision;
20
+ }
21
+ return { allowed: true };
22
+ }
23
+ function evaluateSingleSqlStatementSafety(sql, options = {}) {
24
+ const normalized = stripSqlCommentsAndStrings(sql).trim();
10
25
  const firstKeyword = normalized.match(/^[a-zA-Z_]+/)?.[0]?.toLowerCase();
11
26
  if (!firstKeyword)
12
27
  return { allowed: false, reason: "SQL statement is not recognized." };
@@ -37,7 +52,7 @@ export function sqlSafetyFromEnv(env = process.env) {
37
52
  allowDangerous: env.DBX_MCP_ALLOW_DANGEROUS_SQL === "1" || env.DBX_MCP_ALLOW_DANGEROUS_SQL === "true",
38
53
  };
39
54
  }
40
- function splitSqlStatements(sql) {
55
+ export function splitSqlStatements(sql) {
41
56
  const statements = [];
42
57
  let current = "";
43
58
  let quote = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dbx-app/node-core",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "description": "Shared Node.js database and DBX connection utilities for DBX CLI and MCP server",
5
5
  "type": "module",
6
6
  "engines": {
@@ -16,6 +16,7 @@
16
16
  "./connections": "./dist/connections.js",
17
17
  "./database": "./dist/database.js",
18
18
  "./diagnostics": "./dist/diagnostics.js",
19
+ "./entrypoint": "./dist/entrypoint.js",
19
20
  "./format": "./dist/format.js",
20
21
  "./paths": "./dist/paths.js",
21
22
  "./schema-context": "./dist/schema-context.js",