Skip to main content
Glama

DBHub

by bytebase
import dotenv from "dotenv"; import path from "path"; import fs from "fs"; import { fileURLToPath } from "url"; // Create __dirname equivalent for ES modules const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Parse command line arguments export function parseCommandLineArgs() { // Check if any args start with '--' (the way tsx passes them) const args = process.argv.slice(2); const parsedManually: Record<string, string> = {}; for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg.startsWith("--")) { const [key, value] = arg.substring(2).split("="); if (value) { // Handle --key=value format parsedManually[key] = value; } else if (i + 1 < args.length && !args[i + 1].startsWith("--")) { // Handle --key value format parsedManually[key] = args[i + 1]; i++; // Skip the next argument as it's the value } else { // Handle --key format (boolean flag) parsedManually[key] = "true"; } } } // Just use the manually parsed args - removed parseArgs dependency for Node.js <18.3.0 compatibility return parsedManually; } /** * Load environment files from various locations * Returns the name of the file that was loaded, or null if none was found */ export function loadEnvFiles(): string | null { // Determine if we're in development or production mode const isDevelopment = process.env.NODE_ENV === "development" || process.argv[1]?.includes("tsx"); // Select environment file names based on environment const envFileNames = isDevelopment ? [".env.local", ".env"] // In development, try .env.local first, then .env : [".env"]; // In production, only look for .env // Build paths to check for environment files const envPaths = []; for (const fileName of envFileNames) { envPaths.push( fileName, // Current working directory path.join(__dirname, "..", "..", fileName), // Two levels up (src/config -> src -> root) path.join(process.cwd(), fileName) // Explicit current working directory ); } // Try to load the first env file found from the prioritized locations for (const envPath of envPaths) { console.error(`Checking for env file: ${envPath}`); if (fs.existsSync(envPath)) { dotenv.config({ path: envPath }); // Return the name of the file that was loaded return path.basename(envPath); } } return null; } /** * Check if demo mode is enabled from command line args * Returns true if --demo flag is provided */ export function isDemoMode(): boolean { const args = parseCommandLineArgs(); return args.demo === "true"; } /** * Check if readonly mode is enabled from command line args or environment * Returns true if --readonly flag is provided */ export function isReadOnlyMode(): boolean { const args = parseCommandLineArgs(); // Check command line args first if (args.readonly !== undefined) { return args.readonly === "true"; } // Check environment variable if (process.env.READONLY !== undefined) { return process.env.READONLY === "true"; } // Default to false return false; } /** * Resolve DSN from command line args, environment variables, or .env files * Returns the DSN and its source, or null if not found */ export function resolveDSN(): { dsn: string; source: string; isDemo?: boolean } | null { // Get command line arguments const args = parseCommandLineArgs(); // Check for demo mode first (highest priority) if (isDemoMode()) { // Will use in-memory SQLite with demo data return { dsn: "sqlite::memory:", source: "demo mode", isDemo: true, }; } // 1. Check command line arguments if (args.dsn) { return { dsn: args.dsn, source: "command line argument" }; } // 2. Check environment variables before loading .env if (process.env.DSN) { return { dsn: process.env.DSN, source: "environment variable" }; } // 3. Try loading from .env files const loadedEnvFile = loadEnvFiles(); if (loadedEnvFile && process.env.DSN) { return { dsn: process.env.DSN, source: `${loadedEnvFile} file` }; } return null; } /** * Resolve transport type from command line args or environment variables * Returns 'stdio' or 'sse', with 'stdio' as the default */ export function resolveTransport(): { type: "stdio" | "sse"; source: string } { // Get command line arguments const args = parseCommandLineArgs(); // 1. Check command line arguments first (highest priority) if (args.transport) { const type = args.transport === "sse" ? "sse" : "stdio"; return { type, source: "command line argument" }; } // 2. Check environment variables if (process.env.TRANSPORT) { const type = process.env.TRANSPORT === "sse" ? "sse" : "stdio"; return { type, source: "environment variable" }; } // 3. Default to stdio return { type: "stdio", source: "default" }; } /** * Resolve port from command line args or environment variables * Returns port number with 8080 as the default * * Note: The port option is only applicable when using --transport=sse * as it controls the HTTP server port for SSE connections. */ export function resolvePort(): { port: number; source: string } { // Get command line arguments const args = parseCommandLineArgs(); // 1. Check command line arguments first (highest priority) if (args.port) { const port = parseInt(args.port, 10); return { port, source: "command line argument" }; } // 2. Check environment variables if (process.env.PORT) { const port = parseInt(process.env.PORT, 10); return { port, source: "environment variable" }; } // 3. Default to 8080 return { port: 8080, source: "default" }; } /** * Redact sensitive information from a DSN string * Replaces the password with asterisks * @param dsn - The DSN string to redact * @returns The sanitized DSN string */ export function redactDSN(dsn: string): string { try { // Create a URL object to parse the DSN const url = new URL(dsn); // Replace the password with asterisks if (url.password) { url.password = "*******"; } // Return the sanitized DSN return url.toString(); } catch (error) { // If parsing fails, do basic redaction with regex return dsn.replace(/\/\/([^:]+):([^@]+)@/, "//$1:***@"); } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bytebase/dbhub'

If you have feedback or need assistance with the MCP directory API, please join our Discord server