@elyracode/db-tools 0.3.1 → 0.3.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
@@ -10,20 +10,41 @@ elyra install npm:@elyracode/db-tools
10
10
 
11
11
  ## Configuration
12
12
 
13
- Set environment variables for your database connections:
13
+ ### Automatic: .env file (recommended)
14
14
 
15
- ### MySQL
15
+ If your project has a `.env` file (e.g. Laravel), db-tools reads it automatically. Standard key names are mapped:
16
+
17
+ | .env key | Maps to | Used by |
18
+ |----------|---------|--------|
19
+ | `DB_HOST` | `ELYRA_MYSQL_HOST` | MySQL |
20
+ | `DB_PORT` | `ELYRA_MYSQL_PORT` | MySQL |
21
+ | `DB_DATABASE` | `ELYRA_MYSQL_DATABASE` | MySQL |
22
+ | `DB_USERNAME` | `ELYRA_MYSQL_USER` | MySQL |
23
+ | `DB_PASSWORD` | `ELYRA_MYSQL_PASSWORD` | MySQL |
24
+ | `CLICKHOUSE_HOST` | `ELYRA_CLICKHOUSE_HOST` | ClickHouse |
25
+ | `CLICKHOUSE_PORT` | `ELYRA_CLICKHOUSE_PORT` | ClickHouse |
26
+ | `CLICKHOUSE_DATABASE` | `ELYRA_CLICKHOUSE_DATABASE` | ClickHouse |
27
+ | `CLICKHOUSE_USERNAME` | `ELYRA_CLICKHOUSE_USERNAME` | ClickHouse |
28
+ | `CLICKHOUSE_PASSWORD` | `ELYRA_CLICKHOUSE_PASSWORD` | ClickHouse |
29
+ | `CLICKHOUSE_HTTPS` | `ELYRA_CLICKHOUSE_HTTPS` | ClickHouse |
30
+ | `CLICKHOUSE_TIMEOUT_CONNECT` | `ELYRA_CLICKHOUSE_TIMEOUT_CONNECT` | ClickHouse |
31
+ | `CLICKHOUSE_TIMEOUT_QUERY` | `ELYRA_CLICKHOUSE_TIMEOUT_QUERY` | ClickHouse |
32
+
33
+ For a typical Laravel project, your existing `.env` already has `DB_HOST`, `DB_DATABASE`, etc. -- db-tools picks them up with zero configuration.
34
+
35
+ ### Manual: environment variables
36
+
37
+ You can also set `ELYRA_*` env vars directly. These always take precedence over `.env` values.
16
38
 
17
39
  ```
40
+ # MySQL
18
41
  export ELYRA_MYSQL_HOST=localhost
19
42
  export ELYRA_MYSQL_PORT=3306
20
43
  export ELYRA_MYSQL_USER=readonly_user
21
44
  export ELYRA_MYSQL_PASSWORD=secret
22
45
  export ELYRA_MYSQL_DATABASE=myapp
23
- ```
24
46
 
25
- ### ClickHouse
26
- ```
47
+ # ClickHouse
27
48
  export ELYRA_CLICKHOUSE_HOST=localhost
28
49
  export ELYRA_CLICKHOUSE_PORT=8123
29
50
  export ELYRA_CLICKHOUSE_DATABASE=mydb
@@ -1,15 +1,22 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
1
3
  import type { ExtensionAPI } from "@elyracode/coding-agent";
2
4
  import { createClient } from "@clickhouse/client";
3
5
  import mysql2 from "mysql2/promise";
4
6
  import { Type } from "typebox";
5
7
 
6
8
  export default function (elyra: ExtensionAPI) {
9
+ // ── Load .env ──
10
+ // Reads the project's .env file (if it exists) and maps common Laravel/Docker
11
+ // env var names to the ELYRA_ equivalents. Explicit ELYRA_* env vars always
12
+ // take precedence over .env values.
13
+ loadEnvFile(elyra);
14
+
7
15
  // ── Configuration ──
8
- // Connection details come from environment variables.
9
- // MySQL: ELYRA_MYSQL_HOST, ELYRA_MYSQL_PORT, ELYRA_MYSQL_USER, ELYRA_MYSQL_PASSWORD, ELYRA_MYSQL_DATABASE
10
- // ClickHouse: ELYRA_CLICKHOUSE_HOST, ELYRA_CLICKHOUSE_PORT, ELYRA_CLICKHOUSE_DATABASE,
11
- // ELYRA_CLICKHOUSE_USERNAME, ELYRA_CLICKHOUSE_PASSWORD, ELYRA_CLICKHOUSE_HTTPS,
12
- // ELYRA_CLICKHOUSE_TIMEOUT_CONNECT, ELYRA_CLICKHOUSE_TIMEOUT_QUERY
16
+ // Connection config is resolved from (in priority order):
17
+ // 1. ELYRA_MYSQL_* / ELYRA_CLICKHOUSE_* environment variables
18
+ // 2. Standard names from .env: DB_HOST, DB_PORT, DB_USERNAME, DB_PASSWORD, DB_DATABASE (MySQL)
19
+ // CLICKHOUSE_HOST, CLICKHOUSE_PORT, CLICKHOUSE_DATABASE, CLICKHOUSE_USERNAME, etc. (ClickHouse)
13
20
 
14
21
  // ── Tool: query_mysql ──
15
22
  elyra.registerTool({
@@ -266,6 +273,69 @@ function isReadOnly(sql: string): boolean {
266
273
  return /^(SELECT|SHOW|DESCRIBE|DESC|EXPLAIN|WITH)\b/.test(trimmed);
267
274
  }
268
275
 
276
+ // ── .env Loading ──
277
+
278
+ /** Parse a .env file into key-value pairs (handles quotes and comments) */
279
+ function parseEnvFile(content: string): Record<string, string> {
280
+ const result: Record<string, string> = {};
281
+ for (const line of content.split("\n")) {
282
+ const trimmed = line.trim();
283
+ if (!trimmed || trimmed.startsWith("#")) continue;
284
+ const eqIndex = trimmed.indexOf("=");
285
+ if (eqIndex === -1) continue;
286
+ const key = trimmed.slice(0, eqIndex).trim();
287
+ let value = trimmed.slice(eqIndex + 1).trim();
288
+ // Strip surrounding quotes
289
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
290
+ value = value.slice(1, -1);
291
+ }
292
+ result[key] = value;
293
+ }
294
+ return result;
295
+ }
296
+
297
+ /**
298
+ * Mapping from standard .env keys (Laravel, Docker, etc.) to ELYRA_ env vars.
299
+ * Only sets the ELYRA_ var if it's not already set (explicit env vars win).
300
+ */
301
+ const ENV_KEY_MAP: Array<[string, string]> = [
302
+ // MySQL (Laravel DB_* convention)
303
+ ["DB_HOST", "ELYRA_MYSQL_HOST"],
304
+ ["DB_PORT", "ELYRA_MYSQL_PORT"],
305
+ ["DB_DATABASE", "ELYRA_MYSQL_DATABASE"],
306
+ ["DB_USERNAME", "ELYRA_MYSQL_USER"],
307
+ ["DB_PASSWORD", "ELYRA_MYSQL_PASSWORD"],
308
+ // ClickHouse
309
+ ["CLICKHOUSE_HOST", "ELYRA_CLICKHOUSE_HOST"],
310
+ ["CLICKHOUSE_PORT", "ELYRA_CLICKHOUSE_PORT"],
311
+ ["CLICKHOUSE_DATABASE", "ELYRA_CLICKHOUSE_DATABASE"],
312
+ ["CLICKHOUSE_USERNAME", "ELYRA_CLICKHOUSE_USERNAME"],
313
+ ["CLICKHOUSE_PASSWORD", "ELYRA_CLICKHOUSE_PASSWORD"],
314
+ ["CLICKHOUSE_HTTPS", "ELYRA_CLICKHOUSE_HTTPS"],
315
+ ["CLICKHOUSE_TIMEOUT_CONNECT", "ELYRA_CLICKHOUSE_TIMEOUT_CONNECT"],
316
+ ["CLICKHOUSE_TIMEOUT_QUERY", "ELYRA_CLICKHOUSE_TIMEOUT_QUERY"],
317
+ ];
318
+
319
+ /** Load .env from the project root and map keys to ELYRA_ equivalents */
320
+ function loadEnvFile(elyra: ExtensionAPI): void {
321
+ try {
322
+ const cwd = process.cwd();
323
+ const envPath = join(cwd, ".env");
324
+ if (!existsSync(envPath)) return;
325
+
326
+ const parsed = parseEnvFile(readFileSync(envPath, "utf-8"));
327
+
328
+ for (const [sourceKey, targetKey] of ENV_KEY_MAP) {
329
+ const value = parsed[sourceKey];
330
+ if (value !== undefined && !process.env[targetKey]) {
331
+ process.env[targetKey] = value;
332
+ }
333
+ }
334
+ } catch {
335
+ // Never fail on .env parse errors
336
+ }
337
+ }
338
+
269
339
  // ── Schema Discovery ──
270
340
 
271
341
  async function getMysqlSchema(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elyracode/db-tools",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Database tools for Elyra - query MySQL and ClickHouse with schema awareness and safety guardrails",
5
5
  "type": "module",
6
6
  "keywords": ["elyra-package", "database", "mysql", "clickhouse", "sql"],