Technical — Database Connect
RAGA's database proxy service, built on Node.js + Express. Accepts database connection parameters via per-request HTTP headers, forwards SQL queries to PostgreSQL or MariaDB/MySQL, and returns the result as JSON. Used by the Raga Engine (Text-to-SQL) in api-tarantula to execute LLM-generated queries against externally configured user databases.
Note: this service is stateless — no database configuration is stored. All credentials are sent by the caller via request headers on every request.
Repository
| Key | Value |
|---|---|
| Git Remote | https://git.tlab.co.id/tarantula/service/database-connect.git |
| Active Branch | main |
git clone https://git.tlab.co.id/tarantula/service/database-connect.git
cd database-connectTech Stack
| Layer | Technology |
|---|---|
| Runtime | Node.js 18 |
| Framework | Express 4 |
| PostgreSQL Client | pg (node-postgres) |
| MariaDB/MySQL Client | mariadb |
| API Docs | swagger-ui-express + swagger.json |
| Dev Runner | nodemon |
| Containerization | Docker (node:18) |
Folder Structure
database-connect/
├── index.js # Express app + all connection & query logic
├── swagger.json # Swagger/OpenAPI 3.0 spec (mounted at /api-docs)
├── package.json
├── Dockerfile
├── Dockerfile.stag
└── docker-compose.dev.ymlEnvironment Variables
This service does not use environment variables for database configuration. All connection parameters are sent via per-request HTTP headers by the caller.
Request Headers (Required on Every Request)
| Header | Example | Description |
|---|---|---|
x-db-mode | postgresql | Database mode: postgresql, mariadb, or mysql |
x-db-host | 10.1.102.15 | Database server host |
x-db-port | 5432 | Database server port |
x-db-user | postgres | Database username |
x-db-password | secret | Database password |
x-db-name | raga_db | Database / schema name |
The connection is created per request (not a connection pool) with a 15-second timeout. The connection is closed automatically once the query finishes.
Operational note:
index.jscurrently writes the full connection details — includingx-db-passwordin plaintext — toconsole.logevery time a connection is created, and logs the rawquerytext on every/executecall. Make sure this service's container logs are not stored anywhere broadly accessible (a shared log aggregator, etc.) until this behavior is changed to mask credentials.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /health | Service health check |
GET | /check-connection | Tests the database connection |
GET | /tables | Lists all tables + columns in the database |
POST | /execute | Executes a raw SQL query |
GET | /api-docs | Swagger UI (OpenAPI 3.0) |
GET /check-connection
Tests whether a connection to the database can be established, then immediately closes it.
200 Response:
{ "status": "Connected successfully" }500 Response:
{ "error": "Connection timeout" }GET /tables
Returns a list of all tables in the database along with their column names and data types. The information_schema query is adapted per database engine.
200 Response:
{
"tables": {
"users": [
{ "column_name": "id", "data_type": "integer" },
{ "column_name": "name", "data_type": "character varying" },
{ "column_name": "created_at", "data_type": "timestamp without time zone" }
],
"orders": [
{ "column_name": "id", "data_type": "integer" },
{ "column_name": "user_id", "data_type": "integer" }
]
}
}POST /execute
Executes a raw SQL query (SELECT, INSERT, UPDATE, DELETE, etc.) and returns the result.
Request body:
{
"query": "SELECT id, name FROM users WHERE created_at > '2026-01-01' LIMIT 10"
}200 Response:
{
"result": [
{ "id": 1, "name": "Budi Santoso" },
{ "id": 2, "name": "Sari Dewi" }
]
}400 Response:
{ "error": "Query is required" }GET /health
{ "status": "OK", "timestamp": "2026-06-30T10:00:00.000Z" }Request Flow
Data Type Normalization
The database response is normalized so it can be safely serialized to JSON:
| DB Type | Converted To | Example |
|---|---|---|
BigInt | string | 9007199254740993 |
Date | ISO 8601 string | "2026-06-30T10:00:00.000Z" |
Buffer | Base64 string | "SGVsbG8=" |
| Other | Unchanged | — |
Query per Database Engine
| Operation | PostgreSQL | MariaDB / MySQL |
|---|---|---|
| List tables | information_schema.tables WHERE table_schema='public' | information_schema.tables WHERE table_schema = ? |
| List columns | information_schema.columns WHERE table_name = $1 | information_schema.columns WHERE table_schema = ? AND table_name = ? |
Build & Run
# Install dependencies
npm install
# Run development (nodemon)
npm start
# Docker Compose (dev)
docker compose -f docker-compose.dev.yml up --build
# Standalone Docker build & run
docker build -t database-connect .
docker run -p 3000:3000 database-connectExample calls once the service is running:
# Test a PostgreSQL connection
curl -X GET http://localhost:3000/check-connection \
-H "x-db-mode: postgresql" \
-H "x-db-host: 10.1.102.15" \
-H "x-db-port: 5432" \
-H "x-db-user: postgres" \
-H "x-db-password: secret" \
-H "x-db-name: raga_db"
# Execute a query
curl -X POST http://localhost:3000/execute \
-H "Content-Type: application/json" \
-H "x-db-mode: postgresql" \
-H "x-db-host: 10.1.102.15" \
-H "x-db-port: 5432" \
-H "x-db-user: postgres" \
-H "x-db-password: secret" \
-H "x-db-name: raga_db" \
-d '{"query": "SELECT * FROM users LIMIT 5"}'