From d74fb4a4c20f09852461b7f9fed0da57f655f46a Mon Sep 17 00:00:00 2001 From: huyphan Date: Tue, 14 Jul 2026 15:25:45 -0600 Subject: [PATCH] fix: make DB2 dev workflow work on Windows Use cross-env for dev scripts so the API starts on Windows cmd, call setupDb2ClientEnv before ibm_db driver checks, and surface clearer errors when the backend is unreachable. Co-authored-by: Cursor --- apps/web/package.json | 7 ++++--- apps/web/src/frontend/api/schemaApi.ts | 17 ++++++++++++++++- apps/web/src/frontend/lib/provider-settings.ts | 6 +++--- packages/core/src/cores/driver-detector.ts | 5 +++++ 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 945a554..005234c 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -12,10 +12,10 @@ }, "scripts": { "dev": "vite", - "dev:api": "AUTH_REQUIRED=true APP_ENCRYPTION_KEY=${APP_ENCRYPTION_KEY:-0000000000000000000000000000000000000000000000000000000000000000} tsx watch src/backend/index.ts", + "dev:api": "cross-env AUTH_REQUIRED=true APP_ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000 tsx watch src/backend/index.ts", "dev:all": "concurrently -n api,web -c cyan,magenta \"npm run dev:api\" \"npm run dev\"", - "dev:auth": "AUTH_REQUIRED=true LOCAL_SINGLE_USER=false vite", - "dev:api:auth": "AUTH_REQUIRED=true LOCAL_SINGLE_USER=false APP_ENCRYPTION_KEY=${APP_ENCRYPTION_KEY:-0000000000000000000000000000000000000000000000000000000000000000} tsx watch src/backend/index.ts", + "dev:auth": "cross-env AUTH_REQUIRED=true LOCAL_SINGLE_USER=false vite", + "dev:api:auth": "cross-env AUTH_REQUIRED=true LOCAL_SINGLE_USER=false APP_ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000 tsx watch src/backend/index.ts", "dev:all:auth": "concurrently -n api,web -c cyan,magenta \"npm run dev:api:auth\" \"npm run dev:auth\"", "build": "tsc && vite build", "preview": "vite preview", @@ -55,6 +55,7 @@ "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^6.0.2", "concurrently": "^10.0.3", + "cross-env": "^7.0.3", "tsx": "^4.22.4", "vite": "^8.0.12" } diff --git a/apps/web/src/frontend/api/schemaApi.ts b/apps/web/src/frontend/api/schemaApi.ts index 3cf465c..5398408 100644 --- a/apps/web/src/frontend/api/schemaApi.ts +++ b/apps/web/src/frontend/api/schemaApi.ts @@ -58,7 +58,22 @@ export function invalidateCache(prefix?: string): void { } async function parseJson(res: Response): Promise { - const data = (await res.json()) as T & { error?: string }; + const text = await res.text(); + if (!text.trim()) { + throw new Error( + res.status === 502 || res.status === 504 || res.type === 'opaque' + ? 'API server unreachable — run `npm run dev` from the repo root (starts both the API and UI).' + : `Empty response from server (${res.status} ${res.statusText || 'unknown'})` + ); + } + + let data: T & { error?: string }; + try { + data = JSON.parse(text) as T & { error?: string }; + } catch { + throw new Error(`Invalid response from server (${res.status}): ${text.slice(0, 200)}`); + } + if (!res.ok) { throw new Error( typeof data === 'object' && data && 'error' in data && data.error diff --git a/apps/web/src/frontend/lib/provider-settings.ts b/apps/web/src/frontend/lib/provider-settings.ts index 8bde09a..e243a05 100644 --- a/apps/web/src/frontend/lib/provider-settings.ts +++ b/apps/web/src/frontend/lib/provider-settings.ts @@ -86,13 +86,13 @@ const db2Settings: ProviderSettings = { label: 'IBM DB2', defaultPort: 50000, defaultSchema: '', - schemaRequired: false, + schemaRequired: true, buildConnectionString(o) { if (o.connectionString?.trim()) return o.connectionString.trim(); const host = o.host || 'localhost'; const port = o.port || this.defaultPort; - let cs = `DATABASE=${o.database || ''};HOSTNAME=${host};PORT=${port};PROTOCOL=TCPIP;UID=${o.username || ''};PWD=${o.password || ''};`; - if (o.schema) cs += `CurrentSchema=${o.schema};`; + let cs = `DATABASE=${o.database || ''};HOSTNAME=${host};PORT=${port};PROTOCOL=TCPIP;UID=${o.username || ''};PWD=${o.password || ''};Authentication=SERVER;`; + if (o.schema) cs += `CurrentSchema=${o.schema.toUpperCase()};`; return cs; }, }; diff --git a/packages/core/src/cores/driver-detector.ts b/packages/core/src/cores/driver-detector.ts index 3b9251a..685e6ab 100644 --- a/packages/core/src/cores/driver-detector.ts +++ b/packages/core/src/cores/driver-detector.ts @@ -1,6 +1,7 @@ import { createRequire } from 'node:module'; import type { DriverInfo } from '../interfaces'; import { getAdapter, ADAPTERS } from '../providers/adapter-registry'; +import { setupDb2ClientEnv } from '../providers/db2/db2.env'; const nodeRequire = createRequire(import.meta.url); @@ -20,6 +21,10 @@ export class DriverDetector { } private static checkPackage(dialect: string, packageName: string): DriverInfo { + // ibm_db's native bindings need the bundled clidriver on PATH/LD_LIBRARY_PATH + // (especially on Windows) — same setup the DB2 adapter runs before open(). + if (packageName === 'ibm_db') setupDb2ClientEnv(); + try { const mod = nodeRequire(packageName); return {