db-studio 1.14.1 → 1.16.0
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/index.js +142 -78
- package/dist/index.js.map +1 -1
- package/dist/web-dist/assets/_pathlessLayout-Boc5CMy6.js +1 -0
- package/dist/web-dist/assets/{_pathlessLayout-BYQmoqT2.js → _pathlessLayout-CR6og_FO.js} +52 -52
- package/dist/web-dist/assets/_queryId-B11-YnBQ.js +1 -0
- package/dist/web-dist/assets/{_table-ClkqBjYZ.js → _table-Bqn27t7B.js} +1 -1
- package/dist/web-dist/assets/{_table-BI9E6-Je.js → _table-DxQhMcry.js} +1 -1
- package/dist/web-dist/assets/{badge-SEQODpjR.js → badge-CCWwBQqD.js} +1 -1
- package/dist/web-dist/assets/{browser-CHG4p052.js → browser-8cP9ndIh.js} +1 -1
- package/dist/web-dist/assets/{bundle-mjs-BZOM22--.js → bundle-mjs-DB1RllIB.js} +1 -1
- package/dist/web-dist/assets/{code-editor-BIfiMFMb.js → code-editor-BgChfnuO.js} +2 -2
- package/dist/web-dist/assets/database.store-BQBwzxfV.js +57 -0
- package/dist/web-dist/assets/{dist-D_0esNxp.js → dist-DkQ5_Uxh.js} +1 -1
- package/dist/web-dist/assets/{format-cell-value-D41tFXxV.js → format-cell-value-iKbN4Wqi.js} +1 -1
- package/dist/web-dist/assets/highlighted-body-OFNGDK62-v8ygEbhn.js +1 -0
- package/dist/web-dist/assets/{icons-rRDRsZcq.js → icons-BCT3bskt.js} +1 -1
- package/dist/web-dist/assets/index-Ir-8O5kw.css +2 -0
- package/dist/web-dist/assets/index-UKp_x9Z2.js +36 -0
- package/dist/web-dist/assets/{indexes-DMAVA8iJ.js → indexes-B4-rFB3b.js} +1 -1
- package/dist/web-dist/assets/{logs-DCMuv22K.js → logs-BOXFja-k.js} +1 -1
- package/dist/web-dist/assets/mermaid-GHXKKRXX-DEXfBzpg.js +1 -0
- package/dist/web-dist/assets/{middleware-Y6OdmOWR.js → middleware-BW-pB9ic.js} +1 -1
- package/dist/web-dist/assets/{monaco-editor-BO3WVEVM.js → monaco-editor-BzOxyRit.js} +1 -1
- package/dist/web-dist/assets/{monitoring-BtlIcl3k.js → monitoring-BfsJUyIb.js} +1 -1
- package/dist/web-dist/assets/overlay.store-F1O5kYfc.js +11 -0
- package/dist/web-dist/assets/{queries.store-CxkLh1ra.js → queries.store-BY0EJQVG.js} +1 -1
- package/dist/web-dist/assets/query-runner-Cf8qZvua.js +17 -0
- package/dist/web-dist/assets/{radix-ui-C1Z_SoKk.js → radix-ui-BgeXyBqe.js} +1 -1
- package/dist/web-dist/assets/{react-1gU4DcpZ.js → react--smpiBOs.js} +1 -1
- package/dist/web-dist/assets/{react-dom-DkH0eaTq.js → react-dom-DJiIHdcx.js} +1 -1
- package/dist/web-dist/assets/{redis-value-BmLGJf9X.js → redis-value-D-VAbClW.js} +1 -1
- package/dist/web-dist/assets/{rolldown-runtime-DY1mqKjv.js → rolldown-runtime-aFZ5dRI8.js} +1 -1
- package/dist/web-dist/assets/runner-DD-JnaQG.js +1 -0
- package/dist/web-dist/assets/schema-C4Vx4FfH.js +1 -0
- package/dist/web-dist/assets/{schema-C-10JjXl.js → schema-D2srYuEZ.js} +1 -1
- package/dist/web-dist/assets/{table-C75Kr4aI.js → table-D4qAO6ym.js} +1 -1
- package/dist/web-dist/assets/{tanstack-C3XvOIUf.js → tanstack-BMrziknI.js} +1 -1
- package/dist/web-dist/assets/use-database-engine-Dnkkyy1a.js +1 -0
- package/dist/web-dist/assets/{visualizer-CiiH2acP.js → visualizer-DKVyuUTU.js} +1 -1
- package/dist/web-dist/index.html +19 -18
- package/package.json +8 -4
- package/dist/web-dist/assets/_pathlessLayout-CdSIARYp.js +0 -1
- package/dist/web-dist/assets/_queryId-IoOxUaz6.js +0 -1
- package/dist/web-dist/assets/database.store-OsasuLJl.js +0 -1
- package/dist/web-dist/assets/highlighted-body-OFNGDK62-DBl3trdK.js +0 -1
- package/dist/web-dist/assets/index-Be5YdcX5.css +0 -2
- package/dist/web-dist/assets/index-CJ2YPwW4.js +0 -36
- package/dist/web-dist/assets/mermaid-GHXKKRXX-DJ7TvQxw.js +0 -1
- package/dist/web-dist/assets/overlay.store-DjYsesE7.js +0 -11
- package/dist/web-dist/assets/query-runner-keHo7IiI.js +0 -17
- package/dist/web-dist/assets/runner-CvUPs6q4.js +0 -1
- package/dist/web-dist/assets/schema-9nf0q_01.js +0 -57
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../_sentry-injection-stub","../../shared/src/constants/chat.ts","../../shared/src/constants/column-types-mysql.ts","../../shared/src/constants/column-types-pgsql.ts","../../shared/src/constants/defaults.ts","../../shared/src/constants/links.ts","../../shared/src/constants/meta.ts","../../shared/src/constants/proxy-limits.ts","../../shared/src/constants/index.ts","../package.json","../src/observability.ts","../src/db-manager.ts","../src/cmd/check-database.ts","../src/adapters/adapter.registry.ts","../src/adapters/base.adapter.ts","../src/adapters/connections.ts","../src/utils/mongo-database-visibility.ts","../src/utils/parse-database-url.ts","../src/adapters/mongo/mongo.pipeline-builder.ts","../src/adapters/mongo/mongo.adapter.ts","../../shared/src/types/database.types.ts","../../shared/src/types/add-column.types.ts","../../shared/src/types/add-record.types.ts","../../shared/src/types/ai-provider.types.ts","../../shared/src/types/delete-column.types.ts","../../shared/src/types/alter-column.types.ts","../../shared/src/types/api-response.types.ts","../../shared/src/types/bulk-insert-records.type.ts","../../shared/src/types/chat.types.ts","../../shared/src/types/cmd-args.types.ts","../../shared/src/types/column-info.types.ts","../../shared/src/types/column.type.ts","../../shared/src/types/create-table.types.ts","../../shared/src/types/database-capabilities.types.ts","../../shared/src/types/database-list.types.ts","../../shared/src/types/database-schema.type.ts","../../shared/src/types/delete-record.types.ts","../../shared/src/types/delete-table.types.ts","../../shared/src/types/execute-query.types.ts","../../shared/src/types/export-table.types.ts","../../shared/src/types/key-browser.types.ts","../../shared/src/types/rate-limit-response.type.ts","../../shared/src/types/rename-column.types.ts","../../shared/src/types/rename-table.types.ts","../../shared/src/types/table-data.types.ts","../../shared/src/types/table-info.type.ts","../../shared/src/types/table-schema.types.ts","../../shared/src/types/update-recors.types.ts","../../shared/src/types/index.ts","../src/adapters/mssql/mssql.query-builder.ts","../src/adapters/mssql/mssql.adapter.ts","../src/adapters/mysql/mysql.query-builder.ts","../src/adapters/mysql/mysql.adapter.ts","../src/adapters/pg/pg.query-builder.ts","../src/adapters/pg/pg.adapter.ts","../src/adapters/redis/redis.command-shaper.ts","../src/adapters/redis/redis.adapter.ts","../src/adapters/sqlite/sqlite.query-builder.ts","../src/adapters/sqlite/sqlite.adapter.ts","../src/adapters/register.ts","../src/middlewares/error-handler.ts","../src/utils/system-prompt-generator.ts","../src/utils/table-details-schema.ts","../src/routes/chat.routes.ts","../src/routes/databases.routes.ts","../src/routes/keys.routes.ts","../src/routes/query.routes.ts","../src/routes/records.routes.ts","../src/utils/get-export-file.ts","../src/routes/tables.routes.ts","../src/routes/telemetry.routes.ts","../src/utils/create-server.ts","../src/index.ts","sentry-debug-id-stub:_sentry-debug-id-injection-stub?sentry-module-id=335b1cd5-afec-4564-8d80-55c17e4b59d4","../src/index.ts","../src/cmd/args.ts","../src/cmd/get-db-url.ts","../src/cmd/load-env.ts","../src/cmd/open-browser.ts","../src/cmd/sanitize-error.ts","../src/cmd/show-help.ts","../src/cmd/show-status.ts","../src/cmd/show-version.ts"],"sourcesContent":["!function(){try{var e=\"undefined\"!=typeof window?window:\"undefined\"!=typeof global?global:\"undefined\"!=typeof globalThis?globalThis:\"undefined\"!=typeof self?self:{};e.SENTRY_RELEASE={id:\"db-studio@1.14.1\"};}catch(e){}}();","export const CHAT_SUGGESTIONS = [\n\t\"Show me all tables in my database\",\n\t\"What columns are in the users table?\",\n\t\"Write a query to find all active users\",\n\t\"How many orders were placed last month?\",\n\t\"Find top 5 customers by total spend\",\n\t\"Write a JOIN between users and orders\",\n\t\"Users who haven't made any purchase yet\",\n\t\"Generate monthly revenue summary query\",\n\t\"Suggest useful indexes for better performance\",\n\t\"Show schema of the products / inventory table\",\n\t\"Latest 20 orders with customer names\",\n\t\"Help me write a safe UPDATE query\",\n];\n\n// const MODEL_LIST = [\n// \t{\n// \t\tid: \"gpt-4o\",\n// \t\tname: \"GPT-4o\",\n// \t\tchef: \"OpenAI\",\n// \t\tchefSlug: \"openai\",\n// \t},\n// \t{\n// \t\tid: \"gpt-4o-mini\",\n// \t\tname: \"GPT-4o Mini\",\n// \t\tchef: \"OpenAI\",\n// \t\tchefSlug: \"openai\",\n// \t},\n// \t{\n// \t\tid: \"claude-opus-4-20250514\",\n// \t\tname: \"Claude 4 Opus\",\n// \t\tchef: \"Anthropic\",\n// \t\tchefSlug: \"anthropic\",\n// \t},\n// \t{\n// \t\tid: \"claude-sonnet-4-20250514\",\n// \t\tname: \"Claude 4 Sonnet\",\n// \t\tchef: \"Anthropic\",\n// \t\tchefSlug: \"anthropic\",\n// \t},\n// \t{\n// \t\tid: \"gemini-2.0-flash-exp\",\n// \t\tname: \"Gemini 2.0 Flash\",\n// \t\tchef: \"Google\",\n// \t\tchefSlug: \"google\",\n// \t},\n// ];\n","export const MYSQL_COLUMN_TYPES = [\n\t// Numeric\n\t{ value: \"tinyint\", label: \"tinyint\" },\n\t{ value: \"smallint\", label: \"smallint\" },\n\t{ value: \"mediumint\", label: \"mediumint\" },\n\t{ value: \"int\", label: \"int\" },\n\t{ value: \"bigint\", label: \"bigint\" },\n\t{ value: \"decimal\", label: \"decimal\" },\n\t{ value: \"float\", label: \"float\" },\n\t{ value: \"double\", label: \"double\" },\n\t{ value: \"bit\", label: \"bit\" },\n\t// Boolean\n\t{ value: \"boolean\", label: \"boolean\" },\n\t// Text\n\t{ value: \"char\", label: \"char\" },\n\t{ value: \"varchar\", label: \"varchar\" },\n\t{ value: \"tinytext\", label: \"tinytext\" },\n\t{ value: \"text\", label: \"text\" },\n\t{ value: \"mediumtext\", label: \"mediumtext\" },\n\t{ value: \"longtext\", label: \"longtext\" },\n\t// Binary\n\t{ value: \"binary\", label: \"binary\" },\n\t{ value: \"varbinary\", label: \"varbinary\" },\n\t{ value: \"tinyblob\", label: \"tinyblob\" },\n\t{ value: \"blob\", label: \"blob\" },\n\t{ value: \"mediumblob\", label: \"mediumblob\" },\n\t{ value: \"longblob\", label: \"longblob\" },\n\t// JSON\n\t{ value: \"json\", label: \"json\" },\n\t// Date / Time\n\t{ value: \"date\", label: \"date\" },\n\t{ value: \"time\", label: \"time\" },\n\t{ value: \"datetime\", label: \"datetime\" },\n\t{ value: \"timestamp\", label: \"timestamp\" },\n\t{ value: \"year\", label: \"year\" },\n\t// Complex\n\t{ value: \"enum\", label: \"enum\" },\n\t{ value: \"set\", label: \"set\" },\n] as const;\n\nexport type MysqlColumnType = (typeof MYSQL_COLUMN_TYPES)[number][\"value\"];\n","export const PGSQL_COLUMN_TYPES = [\n\t// Numeric\n\t{ value: \"integer\", label: \"integer\" },\n\t{ value: \"bigint\", label: \"bigint\" },\n\t{ value: \"smallint\", label: \"smallint\" },\n\t{ value: \"numeric\", label: \"numeric\" },\n\t{ value: \"real\", label: \"real\" },\n\t{ value: \"double precision\", label: \"double precision\" },\n\t{ value: \"money\", label: \"money\" },\n\t{ value: \"serial\", label: \"serial\" },\n\t{ value: \"bigserial\", label: \"bigserial\" },\n\t// Boolean\n\t{ value: \"boolean\", label: \"boolean\" },\n\t// Text\n\t{ value: \"text\", label: \"text\" },\n\t{ value: \"varchar\", label: \"varchar\" },\n\t{ value: \"char\", label: \"char\" },\n\t// JSON\n\t{ value: \"json\", label: \"json\" },\n\t{ value: \"jsonb\", label: \"jsonb\" },\n\t{ value: \"xml\", label: \"xml\" },\n\t// UUID\n\t{ value: \"uuid\", label: \"uuid\" },\n\t// Date / Time\n\t{ value: \"date\", label: \"date\" },\n\t{ value: \"time\", label: \"time\" },\n\t{ value: \"timestamp\", label: \"timestamp\" },\n\t{ value: \"timestamptz\", label: \"timestamptz\" },\n\t{ value: \"interval\", label: \"interval\" },\n\t// Binary\n\t{ value: \"bytea\", label: \"bytea\" },\n\t// Network\n\t{ value: \"inet\", label: \"inet\" },\n\t{ value: \"cidr\", label: \"cidr\" },\n\t{ value: \"macaddr\", label: \"macaddr\" },\n\t{ value: \"macaddr8\", label: \"macaddr8\" },\n\t// Geometric\n\t{ value: \"point\", label: \"point\" },\n\t{ value: \"line\", label: \"line\" },\n\t{ value: \"polygon\", label: \"polygon\" },\n] as const;\n\nexport type PgsqlColumnType = (typeof PGSQL_COLUMN_TYPES)[number][\"value\"];\n","const env = (\n\tglobalThis as typeof globalThis & {\n\t\tprocess?: {\n\t\t\tenv?: {\n\t\t\t\tNODE_ENV?: string;\n\t\t\t\tDB_STUDIO_PROXY_URL?: string;\n\t\t\t};\n\t\t};\n\t}\n).process?.env;\n\nconst nodeEnv = env?.NODE_ENV;\n\nexport const DEFAULTS = {\n\tPORT: 3333,\n\tENV: \".env\",\n\tVAR_NAME: \"DATABASE_URL\",\n\tBASE_URL: \"https://api.db-studio.localhost\",\n\t/**\n\t * URL namespace for all HTTP API routes. The API and the SPA are served\n\t * from the same origin in self-hosted mode, so the API is mounted under\n\t * this prefix to keep it from colliding with client-side (SPA) routes such\n\t * as `/table/:name` on a page refresh. See db-studio#214.\n\t */\n\tAPI_PREFIX: \"/api\",\n\tIS_DEV: nodeEnv === \"development\",\n\tPROXY_URL:\n\t\tenv?.DB_STUDIO_PROXY_URL ??\n\t\t(nodeEnv === \"development\"\n\t\t\t? \"https://proxy.db-studio.localhost\"\n\t\t\t: \"https://db-studio-proxy.husamql3.workers.dev\"),\n};\n","export const HEADER_LINKS = [\n\t{ label: \"Home\", href: \"/\" },\n\t{ label: \"Roadmap\", href: \"/roadmap\" },\n\t{ label: \"Docs\", href: \"/docs/$\" },\n\t{ label: \"Changelog\", href: \"/changelog\" },\n];\n","export const META = {\n\t//* author\n\tAUTHOR: \"Hüsam 🥑 <devhsmq@gmail.com>\",\n\tAUTHOR_NAME: \"Hüsam\",\n\tAUTHOR_AVATAR: \"/avocado.png\",\n\tAUTHOR_USERNAME: \"husamql3\",\n\tAUTHOR_GITHUB_LINK: \"https://github.com/husamql3\",\n\t//* site\n\tSITE_DESCRIPTION: \"The modern pgAdmin alternative that works with every database.\",\n\tSITE_KEYWORDS: [\n\t\t\"pgadmin alternative\",\n\t\t\"database client\",\n\t\t\"database gui\",\n\t\t\"database browser\",\n\t\t\"sql editor\",\n\t\t\"postgresql client\",\n\t\t\"mysql client\",\n\t\t\"table editor\",\n\t\t\"ai sql\",\n\t\t\"er diagram\",\n\t],\n\tSITE_TITLE: \"db-studio\",\n\tSITE_NAME: \"dbstudio.sh\",\n\tSITE_URL: \"https://dbstudio.sh\",\n\tSITE_X_LINK: \"https://x.com/dbstudio_sh\",\n\tSITE_GITHUB_LINK: \"https://github.com/husamql3/db-studio\",\n\tSITE_GITHUB_NEW_ISSUE_LINK: \"https://github.com/husamql3/db-studio/issues/new/choose\",\n\tSITE_DOCS_LINK: \"https://dbstudio.sh/docs\",\n\tSITE_CHANGELOG_LINK: \"https://dbstudio.sh/changelog\",\n\tSITE_ROADMAP_LINK: \"https://dbstudio.sh/roadmap\",\n\tSITE_IMAGE: \"https://dbstudio.sh/og-image.png\",\n\tSITE_IMAGE_WIDTH: \"1200\",\n\tSITE_IMAGE_HEIGHT: \"630\",\n\tSITE_IMAGE_ALT: \"dbstudio.sh – Modern database management studio\",\n\tSITE_COLOR: \"#1447e6\",\n};\n","export const ONE_DAY = 24 * 60 * 60 * 1000;\nexport const LIMIT = 3;\n/**\n * Ceiling for requests that carry a personal API key (BYOK). Those requests do\n * not spend our hosted Gemini quota, so they get a far higher allowance — but\n * not an unlimited one, otherwise an arbitrary `x-byok-*` header would be enough\n * to bypass the limiter entirely.\n */\nexport const BYOK_LIMIT = 120;\n","export * from \"./chat.js\";\nexport * from \"./column-types-mysql.js\";\nexport * from \"./column-types-pgsql.js\";\nexport * from \"./defaults.js\";\nexport * from \"./links.js\";\nexport * from \"./meta.js\";\nexport * from \"./proxy-limits.js\";\n","{\n \"name\": \"db-studio\",\n \"type\": \"module\",\n \"version\": \"1.14.1\",\n \"description\": \"Modern database client for PostgreSQL with spreadsheet-like grid, AI-powered SQL assistance, ER diagrams, fast data browsing and editing. CLI tool, upcoming desktop & web versions.\",\n \"keywords\": [\n \"database client\",\n \"database gui\",\n \"database browser\",\n \"sql client\",\n \"sql editor\",\n \"query tool\",\n \"table editor\",\n \"data editor\",\n \"postgres\",\n \"postgresql\",\n \"postgresql client\",\n \"postgresql gui\",\n \"pgadmin alternative\",\n \"mysql\",\n \"mysql client\",\n \"ai sql\",\n \"er diagram\",\n \"database management\",\n \"database studio\"\n ],\n \"author\": \"Hüsam 🥑 <husam@ql3.dev>\",\n \"homepage\": \"https://dbstudio.sh\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/husamql3/db-studio.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/husamql3/db-studio/issues\"\n },\n \"license\": \"Apache-2.0\",\n \"bin\": {\n \"db-studio\": \"./dist/index.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"dev\": \"portless run\",\n \"dev:app\": \"NODE_ENV=development tsx watch src/index.ts\",\n \"build\": \"tsup --minify\",\n \"prepack\": \"cd ../web && bun run build && cd ../server && bun run build\",\n \"start\": \"sh -c 'APP_PORT=${PORT:-3333}; portless proxy start >/dev/null && portless alias db-studio \\\"$APP_PORT\\\" --force >/dev/null && HOST=127.0.0.1 PORT=\\\"$APP_PORT\\\" DB_STUDIO_SERVER_URL=https://db-studio.localhost node dist/index.js'\",\n \"format\": \"biome check --write --unsafe\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"portless\": {\n \"name\": \"api.db-studio\",\n \"script\": \"dev:app\"\n },\n \"dependencies\": {\n \"@clack/prompts\": \"^1.0.1\",\n \"@hono/node-server\": \"^2.0.0\",\n \"@hono/zod-validator\": \"^0.9.0\",\n \"@sentry/node\": \"^10.73.0\",\n \"better-sqlite3\": \"^13.0.3\",\n \"commander\": \"^15.0.0\",\n \"dotenv\": \"^18.0.0\",\n \"hono\": \"^4.10.4\",\n \"ioredis\": \"^6.0.0\",\n \"mongodb\": \"^7.1.1\",\n \"mssql\": \"^12.2.0\",\n \"mysql2\": \"^3.18.2\",\n \"open\": \"^11.0.0\",\n \"pg\": \"^8.13.1\",\n \"picocolors\": \"^1.1.1\",\n \"posthog-node\": \"^5.20.0\",\n \"xlsx\": \"^0.18.5\",\n \"zod\": \"^4.2.1\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.2.6\",\n \"@db-studio/shared\": \"workspace:*\",\n \"@sentry/esbuild-plugin\": \"^5.4.0\",\n \"@types/better-sqlite3\": \"^9.6.0\",\n \"@types/mssql\": \"^12.3.0\",\n \"@types/node\": \"^26.0.0\",\n \"@types/pg\": \"^8.16.0\",\n \"@vitest/coverage-v8\": \"^5.0.0\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.7.1\",\n \"typescript\": \"^7.0.2\",\n \"vitest\": \"^5.0.0\"\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir, platform } from \"node:os\";\nimport path from \"node:path\";\nimport type { DatabaseTypeSchema } from \"@db-studio/shared/types\";\nimport * as Sentry from \"@sentry/node\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { PostHog } from \"posthog-node\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\ntype DurationBucket = \"under_100ms\" | \"100ms_1s\" | \"1s_5s\" | \"over_5s\";\ntype Outcome = \"success\" | \"client_error\" | \"server_error\";\n\ntype TelemetryState = {\n\tinstallationId: string;\n\tenabled: boolean;\n\tlastActiveAt?: string;\n};\n\ntype ServerEvent =\n\t| { event: \"installation_active\"; properties: { runtime: string; os: string } }\n\t| {\n\t\t\tevent: \"server_operation\";\n\t\t\tproperties: {\n\t\t\t\toperation: string;\n\t\t\t\tmethod: string;\n\t\t\t\toutcome: Outcome;\n\t\t\t\tduration_bucket: DurationBucket;\n\t\t\t\tdb_type?: DatabaseTypeSchema;\n\t\t\t};\n\t };\n\nconst isTestOrDevelopment = () =>\n\tprocess.env.NODE_ENV === \"test\" || process.env.NODE_ENV === \"development\";\n\nconst telemetryStatePath = () => {\n\tconst base =\n\t\tprocess.env.DB_STUDIO_DATA_DIR ??\n\t\tprocess.env.XDG_STATE_HOME ??\n\t\t(process.platform === \"win32\"\n\t\t\t? process.env.LOCALAPPDATA\n\t\t\t: path.join(homedir(), \".local\", \"state\"));\n\treturn path.join(base || path.join(homedir(), \".db-studio\"), \"db-studio\", \"telemetry.json\");\n};\n\nconst writeState = (value: TelemetryState): void => {\n\ttry {\n\t\tconst file = telemetryStatePath();\n\t\tmkdirSync(path.dirname(file), { recursive: true });\n\t\twriteFileSync(file, JSON.stringify(value), { encoding: \"utf8\", mode: 0o600 });\n\t} catch {\n\t\t// Telemetry persistence is best-effort and cannot affect the product.\n\t}\n};\n\nconst createState = (): TelemetryState => ({ installationId: randomUUID(), enabled: true });\n\nconst readState = (): TelemetryState => {\n\tconst file = telemetryStatePath();\n\ttry {\n\t\tif (existsSync(file)) {\n\t\t\tconst value = JSON.parse(readFileSync(file, \"utf8\")) as Partial<TelemetryState>;\n\t\t\tif (typeof value.installationId === \"string\" && typeof value.enabled === \"boolean\") {\n\t\t\t\treturn {\n\t\t\t\t\tinstallationId: value.installationId,\n\t\t\t\t\tenabled: value.enabled,\n\t\t\t\t\tlastActiveAt:\n\t\t\t\t\t\ttypeof value.lastActiveAt === \"string\" ? value.lastActiveAt : undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// A damaged local telemetry file must never prevent DB Studio from starting.\n\t}\n\tconst value = createState();\n\twriteState(value);\n\treturn value;\n};\n\nlet state: TelemetryState | undefined;\nlet posthog: PostHog | undefined;\nconst OFFICIAL_SENTRY_DSN =\n\t\"https://a1e890d1105f1f27fcb1dbead71c30dd@o4509725125181440.ingest.de.sentry.io/4512040493383760\";\nconst OFFICIAL_POSTHOG_KEY = \"phc_nxaQk54MWAehmL72J4gjVbrQCpbSTedMyHn3PvFxAhkd\";\nconst currentState = (): TelemetryState => (state ??= readState());\n\nexport const isTelemetryEnabled = (): boolean =>\n\t!isTestOrDevelopment() && process.env.DB_STUDIO_TELEMETRY !== \"0\" && currentState().enabled;\n\nexport const getTelemetryConfig = () => ({\n\tenabled: isTelemetryEnabled(),\n\tinstallationId: currentState().installationId,\n\tappVersion: packageJson.version,\n});\n\nexport const setTelemetryEnabled = (enabled: boolean): void => {\n\tstate = { ...currentState(), enabled };\n\twriteState(state);\n\tif (enabled) {\n\t\tvoid posthog?.enable();\n\t\tinitServerObservability();\n\t} else {\n\t\tvoid posthog?.disable();\n\t\tvoid Sentry.close(500);\n\t}\n};\n\nexport const resetTelemetryId = (): string => {\n\tstate = { ...currentState(), installationId: randomUUID(), lastActiveAt: undefined };\n\twriteState(state);\n\treturn state.installationId;\n};\n\nexport const durationBucket = (durationMs: number): DurationBucket => {\n\tif (durationMs < 100) return \"under_100ms\";\n\tif (durationMs < 1_000) return \"100ms_1s\";\n\tif (durationMs < 5_000) return \"1s_5s\";\n\treturn \"over_5s\";\n};\n\nexport const outcomeForStatus = (status: number): Outcome => {\n\tif (status >= 500) return \"server_error\";\n\tif (status >= 400) return \"client_error\";\n\treturn \"success\";\n};\n\nexport const operationForRequest = (method: string, pathname: string): string => {\n\tconst pathWithoutType = pathname.replace(\n\t\t/^\\/api\\/(?:pg|mysql|mssql|mongodb|sqlite|redis)(?=\\/|$)/,\n\t\t\"/api\",\n\t);\n\tconst rules: Array<[RegExp, string]> = [\n\t\t[/^\\/api\\/databases(?:\\/|$)/, \"databases\"],\n\t\t[/^\\/api\\/tables(?:\\/|$)/, \"tables\"],\n\t\t[/^\\/api\\/records(?:\\/|$)/, \"records\"],\n\t\t[/^\\/api\\/query(?:\\/|$)/, \"query\"],\n\t\t[/^\\/api\\/keys(?:\\/|$)/, \"keys\"],\n\t\t[/^\\/api\\/chat(?:\\/|$)/, \"chat\"],\n\t];\n\tconst resource = rules.find(([pattern]) => pattern.test(pathWithoutType))?.[1] ?? \"other\";\n\treturn `${method.toLowerCase()}_${resource}`;\n};\n\nexport const databaseTypeForRequest = (pathname: string): DatabaseTypeSchema | undefined =>\n\tpathname.match(/^\\/api\\/(pg|mysql|mssql|mongodb|sqlite|redis)(?=\\/|$)/)?.[1] as\n\t\t| DatabaseTypeSchema\n\t\t| undefined;\n\nexport const initServerObservability = (): void => {\n\tif (!isTelemetryEnabled()) return;\n\tconst sentryDsn = process.env.DB_STUDIO_SENTRY_DSN ?? OFFICIAL_SENTRY_DSN;\n\tif (\n\t\tsentryDsn &&\n\t\t(!Sentry.isInitialized() || Sentry.getClient()?.getOptions().enabled === false)\n\t) {\n\t\tSentry.init({\n\t\t\tdsn: sentryDsn,\n\t\t\tenvironment: process.env.NODE_ENV ?? \"production\",\n\t\t\trelease: `db-studio@${packageJson.version}`,\n\t\t\ttracesSampleRate: 0.1,\n\t\t\tsendDefaultPii: false,\n\t\t\tdefaultIntegrations: false,\n\t\t\tbeforeSend(event) {\n\t\t\t\tdelete event.request;\n\t\t\t\tdelete event.user;\n\t\t\t\tdelete event.breadcrumbs;\n\t\t\t\treturn event;\n\t\t\t},\n\t\t\tbeforeSendSpan(span) {\n\t\t\t\treturn {\n\t\t\t\t\t...span,\n\t\t\t\t\tdata: Object.fromEntries(\n\t\t\t\t\t\tObject.entries(span.data ?? {}).filter(([key]) => key.startsWith(\"db_studio.\")),\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t},\n\t\t});\n\t}\n\n\tconst posthogKey = process.env.DB_STUDIO_POSTHOG_KEY ?? OFFICIAL_POSTHOG_KEY;\n\tif (posthogKey && !posthog) {\n\t\tposthog = new PostHog(posthogKey, {\n\t\t\thost: process.env.DB_STUDIO_POSTHOG_HOST ?? \"https://eu.i.posthog.com\",\n\t\t\tflushAt: 20,\n\t\t\tflushInterval: 10_000,\n\t\t\trequestTimeout: 2_000,\n\t\t});\n\t}\n};\n\nexport const captureServerEvent = (event: ServerEvent): void => {\n\tif (!isTelemetryEnabled() || !posthog) return;\n\tposthog.capture({\n\t\tdistinctId: currentState().installationId,\n\t\tevent: event.event,\n\t\tproperties: {\n\t\t\t...event.properties,\n\t\t\tsource: \"server\",\n\t\t\tapp_version: packageJson.version,\n\t\t\t$geoip_disable: false,\n\t\t},\n\t});\n};\n\nexport const captureInstallationActive = (): void => {\n\tif (!isTelemetryEnabled()) return;\n\tconst current = currentState();\n\tconst lastActive = current.lastActiveAt ? Date.parse(current.lastActiveAt) : 0;\n\tif (Date.now() - lastActive < 86_400_000) return;\n\tstate = { ...current, lastActiveAt: new Date().toISOString() };\n\twriteState(state);\n\tcaptureServerEvent({\n\t\tevent: \"installation_active\",\n\t\tproperties: { runtime: `node-${process.versions.node.split(\".\")[0]}`, os: platform() },\n\t});\n};\n\nconst safeErrorType = (error: unknown): string => {\n\tconst name =\n\t\terror instanceof HTTPException\n\t\t\t? \"HTTPException\"\n\t\t\t: error instanceof Error\n\t\t\t\t? error.name\n\t\t\t\t: \"Error\";\n\treturn /^[A-Za-z][A-Za-z0-9]{0,49}$/.test(name) ? name : \"Error\";\n};\n\nconst safeErrorCode = (error: unknown): string | undefined => {\n\tif (!(error instanceof Error)) return undefined;\n\tconst { code, errno } = error as Error & { code?: unknown; errno?: unknown };\n\tif (typeof code === \"string\" && /^[A-Z0-9_]{2,32}$/.test(code)) return code;\n\tif (typeof errno === \"number\" && Number.isSafeInteger(errno)) return String(errno);\n\treturn undefined;\n};\n\nconst sanitizedError = (error: unknown, errorType: string): Error => {\n\tconst sanitized = new Error(\"Server operation failed\");\n\tsanitized.name = errorType;\n\tif (error instanceof Error && error.stack) {\n\t\tconst frames = error.stack\n\t\t\t.split(\"\\n\")\n\t\t\t.slice(1)\n\t\t\t.filter((line) => /^\\s*at\\s/.test(line));\n\t\tsanitized.stack = [`${errorType}: Server operation failed`, ...frames].join(\"\\n\");\n\t}\n\treturn sanitized;\n};\n\nexport const captureServerError = (\n\terror: unknown,\n\t{\n\t\toperation,\n\t\tstatus,\n\t\tdbType,\n\t}: { operation: string; status: number; dbType?: DatabaseTypeSchema },\n): void => {\n\tif (!isTelemetryEnabled() || status < 500) return;\n\tconst diagnosticError = error instanceof HTTPException && error.cause ? error.cause : error;\n\tconst errorType = safeErrorType(diagnosticError);\n\tconst errorCode = safeErrorCode(diagnosticError);\n\tSentry.captureException(sanitizedError(diagnosticError, errorType), {\n\t\ttags: {\n\t\t\toperation,\n\t\t\tsource: \"server\",\n\t\t\trelease: packageJson.version,\n\t\t\tstatus: String(status),\n\t\t\t...(dbType ? { db_type: dbType } : {}),\n\t\t\terror_type: errorType,\n\t\t\t...(errorCode ? { error_code: errorCode } : {}),\n\t\t},\n\t\tfingerprint: [operation, String(status), errorType, errorCode ?? \"unknown\"],\n\t});\n};\n\nexport const startServerSpan = <T>(\n\toperation: string,\n\tdbType: DatabaseTypeSchema | undefined,\n\tcallback: () => T,\n): T =>\n\tSentry.startSpan(\n\t\t{\n\t\t\tname: operation,\n\t\t\top: \"http.server\",\n\t\t\tattributes: {\n\t\t\t\t\"db_studio.operation\": operation,\n\t\t\t\t...(dbType ? { \"db_studio.db_type\": dbType } : {}),\n\t\t\t},\n\t\t},\n\t\tcallback,\n\t);\n\nexport const writeOperationalLog = (\n\tlevel: \"info\" | \"error\",\n\tevent: string,\n\tfields: Record<string, string | number | undefined>,\n): void => {\n\tconst safeFields = Object.fromEntries(\n\t\tObject.entries(fields).filter(([, value]) => value !== undefined),\n\t);\n\tprocess.stderr.write(\n\t\t`${JSON.stringify({ timestamp: new Date().toISOString(), level, event, ...safeFields })}\\n`,\n\t);\n};\n","import type { DatabaseTypeSchema } from \"@db-studio/shared/types\";\nimport Database from \"better-sqlite3\";\nimport { Redis, type RedisOptions } from \"ioredis\";\nimport { MongoClient, ObjectId } from \"mongodb\";\nimport type { ConnectionPool as MssqlPool } from \"mssql\";\nimport mssql from \"mssql\";\nimport type { Pool as MysqlPool } from \"mysql2/promise\";\nimport { createPool as createMysqlPool } from \"mysql2/promise\";\nimport { Pool, type PoolConfig } from \"pg\";\n\n/**\n * DatabaseManager - Manages multiple database connection pools for PostgreSQL, MySQL, SQL Server, and MongoDB\n */\nclass DatabaseManager {\n\tprivate pgPools: Map<string, Pool> = new Map();\n\tprivate mysqlPools: Map<string, MysqlPool> = new Map();\n\tprivate mssqlPools: Map<string, MssqlPool> = new Map();\n\tprivate mongoClient: MongoClient | null = null;\n\tprivate sqliteDb: Database.Database | null = null;\n\tprivate redisClients: Map<number, Redis> = new Map();\n\tprivate redisClusterChecked = false;\n\tprivate baseConfig: {\n\t\turl: string;\n\t\thost: string;\n\t\tport: number;\n\t\tuser: string;\n\t\tpassword: string;\n\t\tdbType: DatabaseTypeSchema;\n\t} | null = null;\n\tprivate initError: Error | null = null;\n\n\tconstructor() {\n\t\ttry {\n\t\t\tthis.initializeBaseConfig();\n\t\t} catch (e) {\n\t\t\tthis.initError = e instanceof Error ? e : new Error(String(e));\n\t\t\tconsole.error(`❌ Database configuration error: ${this.initError.message}`);\n\t\t}\n\t}\n\n\t/**\n\t * Detect database type from URL protocol\n\t */\n\tprivate detectDbType(url: URL): DatabaseTypeSchema {\n\t\tconst protocol = url.protocol.replace(\":\", \"\");\n\t\tswitch (protocol) {\n\t\t\tcase \"postgres\":\n\t\t\tcase \"postgresql\":\n\t\t\t\treturn \"pg\";\n\t\t\tcase \"mysql\":\n\t\t\tcase \"mysql2\":\n\t\t\t\treturn \"mysql\";\n\t\t\tcase \"mssql\":\n\t\t\tcase \"sqlserver\":\n\t\t\t\treturn \"mssql\";\n\t\t\tcase \"mongodb\":\n\t\t\tcase \"mongodb+srv\":\n\t\t\t\treturn \"mongodb\";\n\t\t\tcase \"sqlite\":\n\t\t\t\treturn \"sqlite\";\n\t\t\tcase \"redis\":\n\t\t\tcase \"rediss\":\n\t\t\t\treturn \"redis\";\n\t\t\tdefault:\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Unsupported database type: ${protocol}. Supported types: PostgreSQL (postgres://), MySQL (mysql://), SQL Server (mssql://), MongoDB (mongodb://), SQLite (sqlite://), Redis/Valkey (redis:// or rediss://).`,\n\t\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Parse DATABASE_URL and extract connection details\n\t */\n\tprivate initializeBaseConfig() {\n\t\tconst databaseUrl = process.env.DATABASE_URL;\n\t\tif (!databaseUrl) {\n\t\t\tthrow new Error(\"DATABASE_URL is not set. Please provide a database connection string.\");\n\t\t}\n\n\t\t// SQLite URLs use a file path that doesn't parse well as a standard URL\n\t\tif (databaseUrl.startsWith(\"sqlite://\")) {\n\t\t\tthis.baseConfig = {\n\t\t\t\turl: databaseUrl,\n\t\t\t\thost: \"localhost\",\n\t\t\t\tport: 0,\n\t\t\t\tuser: \"\",\n\t\t\t\tpassword: \"\",\n\t\t\t\tdbType: \"sqlite\",\n\t\t\t};\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst url = new URL(databaseUrl);\n\t\t\tconst detectedType = this.detectDbType(url);\n\t\t\tconst defaultPort =\n\t\t\t\tdetectedType === \"mysql\"\n\t\t\t\t\t? 3306\n\t\t\t\t\t: detectedType === \"mssql\"\n\t\t\t\t\t\t? 1433\n\t\t\t\t\t\t: detectedType === \"mongodb\"\n\t\t\t\t\t\t\t? 27017\n\t\t\t\t\t\t\t: detectedType === \"redis\"\n\t\t\t\t\t\t\t\t? 6379\n\t\t\t\t\t\t\t\t: 5432;\n\t\t\tthis.baseConfig = {\n\t\t\t\turl: databaseUrl,\n\t\t\t\thost: url.hostname,\n\t\t\t\tport: Number.parseInt(url.port, 10) || defaultPort,\n\t\t\t\tuser: url.username,\n\t\t\t\tpassword: url.password,\n\t\t\t\tdbType: detectedType,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthrow new Error(error instanceof Error ? error.message : String(error));\n\t\t}\n\t}\n\n\t/**\n\t * Get the detected database type\n\t */\n\tgetDbType(): DatabaseTypeSchema {\n\t\tif (this.initError) throw this.initError;\n\t\tif (!this.baseConfig) {\n\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t}\n\t\treturn this.baseConfig.dbType;\n\t}\n\n\t/**\n\t * Build a connection string for the specified database\n\t */\n\tbuildConnectionString(database?: string): string {\n\t\tif (this.initError) throw this.initError;\n\t\tif (!this.baseConfig) {\n\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t}\n\n\t\t// SQLite is a single-file database; the URL is already the full connection string\n\t\tif (this.baseConfig.dbType === \"sqlite\") {\n\t\t\treturn this.baseConfig.url;\n\t\t}\n\n\t\tif (!database) {\n\t\t\tconst url = new URL(this.baseConfig.url);\n\t\t\tdatabase = url.pathname.slice(1);\n\t\t}\n\n\t\ttry {\n\t\t\tconst url = new URL(this.baseConfig.url);\n\t\t\turl.pathname = `/${database}`;\n\t\t\treturn url.toString();\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to build connection string for database \"${database}\": ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Get or create the SQLite database connection\n\t */\n\tgetSqliteDb(): Database.Database {\n\t\tif (!this.baseConfig || this.baseConfig.dbType !== \"sqlite\") {\n\t\t\tthrow new Error(\"DATABASE_URL is not a sqlite:// connection\");\n\t\t}\n\n\t\tif (!this.sqliteDb) {\n\t\t\t// Strip \"sqlite://\" prefix to get the file path (e.g. sqlite:///path/db.sqlite → /path/db.sqlite)\n\t\t\tconst filePath = this.baseConfig.url.replace(/^sqlite:\\/\\//, \"\");\n\t\t\tconst db = new Database(filePath);\n\t\t\tdb.pragma(\"journal_mode = WAL\");\n\t\t\tdb.pragma(\"foreign_keys = ON\");\n\t\t\tthis.sqliteDb = db;\n\t\t}\n\n\t\treturn this.sqliteDb;\n\t}\n\n\t/**\n\t * Close the SQLite database connection\n\t */\n\tcloseSqliteDb(): void {\n\t\tif (this.sqliteDb) {\n\t\t\tthis.sqliteDb.close();\n\t\t\tthis.sqliteDb = null;\n\t\t}\n\t}\n\n\t/**\n\t * Get or create a PostgreSQL connection pool for the specified database\n\t */\n\tgetPgPool(database?: string): Pool {\n\t\tconst connectionString = this.buildConnectionString(database);\n\n\t\tif (!this.pgPools.has(connectionString)) {\n\t\t\tconst poolConfig: PoolConfig = {\n\t\t\t\tconnectionString,\n\t\t\t\tmax: 10,\n\t\t\t\tidleTimeoutMillis: 30000,\n\t\t\t\tconnectionTimeoutMillis: 2000,\n\t\t\t};\n\n\t\t\tconst pool = new Pool(poolConfig);\n\n\t\t\t// The tables list spans every user schema, but the SQL the adapters\n\t\t\t// build refers to tables by bare name, so a table outside \"public\" is\n\t\t\t// listed yet every query against it fails with \"relation does not\n\t\t\t// exist\". Widen search_path on each new connection.\n\t\t\t//\n\t\t\t// pg emits \"connect\" synchronously and hands the client straight to\n\t\t\t// the caller, so this must enqueue in one shot: awaiting a lookup\n\t\t\t// first would let the caller's query jump ahead of the SET. \"public\"\n\t\t\t// stays first so it keeps winning a name collision, as before.\n\t\t\tpool.on(\"connect\", (client) => {\n\t\t\t\tclient\n\t\t\t\t\t.query(\n\t\t\t\t\t\t`DO $$\n\t\t\t\t\t\tDECLARE extra text;\n\t\t\t\t\t\tBEGIN\n\t\t\t\t\t\t\tSELECT string_agg(quote_ident(nspname), ', ' ORDER BY nspname) INTO extra\n\t\t\t\t\t\t\tFROM pg_namespace\n\t\t\t\t\t\t\tWHERE nspname NOT IN ('pg_catalog', 'information_schema', 'public')\n\t\t\t\t\t\t\t\tAND nspname NOT LIKE 'pg_toast%'\n\t\t\t\t\t\t\t\tAND nspname NOT LIKE 'pg_temp%';\n\t\t\t\t\t\t\tIF extra IS NOT NULL THEN\n\t\t\t\t\t\t\t\tEXECUTE 'SET search_path TO public, ' || extra;\n\t\t\t\t\t\t\tEND IF;\n\t\t\t\t\t\tEND $$;`,\n\t\t\t\t\t)\n\t\t\t\t\t.catch((err: Error) => {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t`Failed to widen search_path for \"${connectionString}\":`,\n\t\t\t\t\t\t\terr.message,\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t});\n\n\t\t\tpool.on(\"error\", (err) => {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`Unexpected error on PostgreSQL pool for \"${connectionString}\":`,\n\t\t\t\t\terr.message,\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tthis.pgPools.set(connectionString, pool);\n\t\t}\n\n\t\treturn this.pgPools.get(connectionString) ?? new Pool({ connectionString });\n\t}\n\n\t/**\n\t * Get or create a MySQL connection pool for the specified database\n\t */\n\tgetMysqlPool(database?: string): MysqlPool {\n\t\tif (!this.baseConfig) {\n\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t}\n\n\t\tconst connectionString = this.buildConnectionString(database);\n\n\t\tif (!this.mysqlPools.has(connectionString)) {\n\t\t\tconst url = new URL(connectionString);\n\t\t\tconst dbName = url.pathname.slice(1);\n\n\t\t\tconst pool = createMysqlPool({\n\t\t\t\thost: this.baseConfig.host,\n\t\t\t\tport: this.baseConfig.port,\n\t\t\t\tuser: this.baseConfig.user,\n\t\t\t\tpassword: this.baseConfig.password,\n\t\t\t\tdatabase: dbName || undefined,\n\t\t\t\twaitForConnections: true,\n\t\t\t\tconnectionLimit: 10,\n\t\t\t\tidleTimeout: 30000,\n\t\t\t\tconnectTimeout: 2000,\n\t\t\t\t// Enable multiple statements for raw query support\n\t\t\t\tmultipleStatements: false,\n\t\t\t});\n\n\t\t\tthis.mysqlPools.set(connectionString, pool);\n\t\t}\n\n\t\treturn this.mysqlPools.get(connectionString) as MysqlPool;\n\t}\n\n\t/**\n\t * Get or create a SQL Server connection pool for the specified database\n\t */\n\tasync getMssqlPool(database?: string): Promise<MssqlPool> {\n\t\tif (!this.baseConfig) {\n\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t}\n\n\t\tconst connectionString = this.buildConnectionString(database);\n\n\t\tif (!this.mssqlPools.has(connectionString)) {\n\t\t\tconst url = new URL(connectionString);\n\t\t\tconst dbName = url.pathname.slice(1);\n\n\t\t\tconst config: mssql.config = {\n\t\t\t\tserver: this.baseConfig.host,\n\t\t\t\tport: this.baseConfig.port,\n\t\t\t\tuser: this.baseConfig.user,\n\t\t\t\tpassword: this.baseConfig.password,\n\t\t\t\tdatabase: dbName || undefined,\n\t\t\t\toptions: {\n\t\t\t\t\tencrypt: false, // Use true for Azure\n\t\t\t\t\ttrustServerCertificate: true,\n\t\t\t\t\tenableArithAbort: true,\n\t\t\t\t\tconnectTimeout: 2000,\n\t\t\t\t},\n\t\t\t\tpool: {\n\t\t\t\t\tmax: 10,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tidleTimeoutMillis: 30000,\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst pool = await new mssql.ConnectionPool(config).connect();\n\n\t\t\tpool.on(\"error\", (err) => {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`Unexpected error on SQL Server pool for \"${connectionString}\":`,\n\t\t\t\t\terr.message,\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tthis.mssqlPools.set(connectionString, pool);\n\t\t}\n\n\t\treturn this.mssqlPools.get(connectionString) as MssqlPool;\n\t}\n\n\t/**\n\t * Get the appropriate pool based on database type (legacy/PG-only helper)\n\t */\n\tgetPool(database?: string): Pool {\n\t\treturn this.getPgPool(database);\n\t}\n\n\t/**\n\t * Close a specific PostgreSQL pool by connection string\n\t */\n\tasync closePgPool(connectionString: string): Promise<void> {\n\t\tconst pool = this.pgPools.get(connectionString);\n\t\tif (pool) {\n\t\t\tawait pool.end();\n\t\t\tthis.pgPools.delete(connectionString);\n\t\t\tconsole.log(`Closed PostgreSQL connection pool for: ${connectionString}`);\n\t\t}\n\t}\n\n\t/**\n\t * Close a specific MySQL pool by connection string\n\t */\n\tasync closeMysqlPool(connectionString: string): Promise<void> {\n\t\tconst pool = this.mysqlPools.get(connectionString);\n\t\tif (pool) {\n\t\t\tawait pool.end();\n\t\t\tthis.mysqlPools.delete(connectionString);\n\t\t\tconsole.log(`Closed MySQL connection pool for: ${connectionString}`);\n\t\t}\n\t}\n\n\t/**\n\t * Close a specific SQL Server pool by connection string\n\t */\n\tasync closeMssqlPool(connectionString: string): Promise<void> {\n\t\tconst pool = this.mssqlPools.get(connectionString);\n\t\tif (pool) {\n\t\t\tawait pool.close();\n\t\t\tthis.mssqlPools.delete(connectionString);\n\t\t\tconsole.log(`Closed SQL Server connection pool for: ${connectionString}`);\n\t\t}\n\t}\n\n\t/**\n\t * Close a specific database pool by connection string (both types)\n\t */\n\tasync closePool(connectionString: string): Promise<void> {\n\t\tif (this.baseConfig?.dbType === \"sqlite\" && connectionString === this.baseConfig.url) {\n\t\t\tthis.closeSqliteDb();\n\t\t\treturn;\n\t\t}\n\t\tawait this.closePgPool(connectionString);\n\t\tawait this.closeMysqlPool(connectionString);\n\t\tawait this.closeMssqlPool(connectionString);\n\t}\n\n\t/**\n\t * Close a specific database pool by database name\n\t */\n\tasync closePoolByDatabase(database: string): Promise<void> {\n\t\tif (this.baseConfig?.dbType === \"sqlite\") {\n\t\t\tthis.closeSqliteDb();\n\t\t\treturn;\n\t\t}\n\t\tconst connectionString = this.buildConnectionString(database);\n\t\tawait this.closePool(connectionString);\n\t}\n\n\t/**\n\t * Get or create a MongoDB client\n\t */\n\tasync getMongoClient(): Promise<MongoClient> {\n\t\tif (!this.mongoClient) {\n\t\t\tif (!this.baseConfig) {\n\t\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t\t}\n\t\t\tconst nextClient = new MongoClient(this.baseConfig.url);\n\t\t\ttry {\n\t\t\t\tawait nextClient.connect();\n\t\t\t\tthis.mongoClient = nextClient;\n\t\t\t} catch (error) {\n\t\t\t\ttry {\n\t\t\t\t\tawait nextClient.close();\n\t\t\t\t} catch {\n\t\t\t\t\t// ignore close errors\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\treturn this.mongoClient;\n\t}\n\n\t/**\n\t * Get the MongoDB database name from the connection URL\n\t */\n\tgetMongoDbName(): string {\n\t\tif (!this.baseConfig) {\n\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t}\n\t\tconst raw = new URL(this.baseConfig.url).pathname.replace(/^\\/+|\\/+$/g, \"\");\n\t\ttry {\n\t\t\treturn decodeURIComponent(raw) || \"admin\";\n\t\t} catch {\n\t\t\t// Malformed percent-encoding — fall back to the literal path segment.\n\t\t\treturn raw || \"admin\";\n\t\t}\n\t}\n\n\t/**\n\t * Get a MongoDB database instance\n\t */\n\tasync getMongoDb(dbName?: string) {\n\t\tconst mongoClient = await this.getMongoClient();\n\t\treturn mongoClient.db(dbName ?? this.getMongoDbName());\n\t}\n\n\t/**\n\t * Get or create a Redis client for the specified logical DB index (0-15 by default)\n\t */\n\tasync getRedisClient(dbIndex?: number): Promise<Redis> {\n\t\tif (!this.baseConfig) {\n\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t}\n\t\tif (this.baseConfig.dbType !== \"redis\") {\n\t\t\tthrow new Error(\"DATABASE_URL is not a redis:// connection\");\n\t\t}\n\n\t\tconst index = dbIndex ?? this.getRedisDefaultDb();\n\n\t\tconst existing = this.redisClients.get(index);\n\t\tif (existing) return existing;\n\n\t\tconst url = new URL(this.baseConfig.url);\n\t\tconst options: RedisOptions = {\n\t\t\thost: this.baseConfig.host,\n\t\t\tport: this.baseConfig.port,\n\t\t\tdb: index,\n\t\t\tlazyConnect: true,\n\t\t\tmaxRetriesPerRequest: 1,\n\t\t\tenableReadyCheck: true,\n\t\t\tconnectTimeout: 2000,\n\t\t};\n\t\tif (this.baseConfig.user) options.username = decodeURIComponent(this.baseConfig.user);\n\t\tif (this.baseConfig.password)\n\t\t\toptions.password = decodeURIComponent(this.baseConfig.password);\n\t\tif (url.protocol === \"rediss:\") options.tls = {};\n\n\t\tconst client = new Redis(options);\n\t\ttry {\n\t\t\tawait client.connect();\n\t\t\tif (!this.redisClusterChecked) {\n\t\t\t\tconst info = await client.info(\"server\");\n\t\t\t\tif (/^redis_mode:(cluster|sentinel)\\b/m.test(info)) {\n\t\t\t\t\tawait client.quit().catch(() => {});\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Redis cluster and Sentinel modes are not supported. Use a standalone redis:// connection.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst version = info.match(/^redis_version:([^\\r\\n]+)/m)?.[1];\n\t\t\t\tconst [major = 0, minor = 0] = version?.split(\".\").map(Number) ?? [];\n\t\t\t\tif (major < 6 || (major === 6 && minor < 2)) {\n\t\t\t\t\tawait client.quit().catch(() => {});\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Redis 6.2 or newer is required. Connected server reports ${version ?? \"an unknown version\"}.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis.redisClusterChecked = true;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait client.quit().catch(() => {});\n\t\t\tthrow error;\n\t\t}\n\n\t\tthis.redisClients.set(index, client);\n\t\treturn client;\n\t}\n\n\tasync getIsolatedRedisClient(dbIndex?: number): Promise<Redis> {\n\t\tconst client = (await this.getRedisClient(dbIndex)).duplicate();\n\t\tawait client.connect();\n\t\treturn client;\n\t}\n\n\t/**\n\t * Get the default Redis logical DB from the URL (e.g. redis://host/3 → 3)\n\t */\n\tgetRedisDefaultDb(): number {\n\t\tif (!this.baseConfig) return 0;\n\t\ttry {\n\t\t\tconst url = new URL(this.baseConfig.url);\n\t\t\tconst path = url.pathname.replace(/^\\//, \"\");\n\t\t\tif (!path) return 0;\n\t\t\tconst parsed = Number.parseInt(path, 10);\n\t\t\treturn Number.isFinite(parsed) ? parsed : 0;\n\t\t} catch {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\t/**\n\t * Close all database pools\n\t */\n\tasync closeAll(): Promise<void> {\n\t\tconst pgClosePromises = Array.from(this.pgPools.entries()).map(\n\t\t\tasync ([connectionString, pool]) => {\n\t\t\t\tawait pool.end();\n\t\t\t\tconsole.log(`Closed PostgreSQL pool for: ${connectionString}`);\n\t\t\t},\n\t\t);\n\t\tconst mysqlClosePromises = Array.from(this.mysqlPools.entries()).map(\n\t\t\tasync ([connectionString, pool]) => {\n\t\t\t\tawait pool.end();\n\t\t\t\tconsole.log(`Closed MySQL pool for: ${connectionString}`);\n\t\t\t},\n\t\t);\n\t\tconst mssqlClosePromises = Array.from(this.mssqlPools.entries()).map(\n\t\t\tasync ([connectionString, pool]) => {\n\t\t\t\tawait pool.close();\n\t\t\t\tconsole.log(`Closed SQL Server pool for: ${connectionString}`);\n\t\t\t},\n\t\t);\n\t\tawait Promise.all([...pgClosePromises, ...mysqlClosePromises, ...mssqlClosePromises]);\n\t\tthis.pgPools.clear();\n\t\tthis.mysqlPools.clear();\n\t\tthis.mssqlPools.clear();\n\t\tif (this.mongoClient) {\n\t\t\tawait this.mongoClient.close();\n\t\t\tthis.mongoClient = null;\n\t\t}\n\t\tthis.closeSqliteDb();\n\t\tconst redisClosePromises = Array.from(this.redisClients.entries()).map(\n\t\t\tasync ([index, client]) => {\n\t\t\t\tawait client.quit().catch(() => {});\n\t\t\t\tconsole.log(`Closed Redis client for db=${index}`);\n\t\t\t},\n\t\t);\n\t\tawait Promise.all(redisClosePromises);\n\t\tthis.redisClients.clear();\n\t\tthis.redisClusterChecked = false;\n\t}\n\n\t/**\n\t * Get all active pool connection strings\n\t */\n\tgetActivePools(): string[] {\n\t\treturn [\n\t\t\t...Array.from(this.pgPools.keys()),\n\t\t\t...Array.from(this.mysqlPools.keys()),\n\t\t\t...Array.from(this.mssqlPools.keys()),\n\t\t];\n\t}\n}\n\n// Singleton instance\nconst databaseManager = new DatabaseManager();\n\n/**\n * Get a PostgreSQL pool for the specified database\n */\nexport const getDbPool = (database?: string): Pool => {\n\treturn databaseManager.getPgPool(database);\n};\n\n/**\n * Get a MySQL pool for the specified database\n */\nexport const getMysqlPool = (database?: string): MysqlPool => {\n\treturn databaseManager.getMysqlPool(database);\n};\n\n/**\n * Get a SQL Server pool for the specified database\n */\nexport const getMssqlPool = async (database?: string): Promise<MssqlPool> => {\n\treturn databaseManager.getMssqlPool(database);\n};\n\n/**\n * Get the detected database type from DATABASE_URL\n */\nexport const getDbType = (): DatabaseTypeSchema => {\n\treturn databaseManager.getDbType();\n};\n\n/**\n * Build a connection string for the specified database\n */\nconst _buildDbConnectionString = (database?: string): string => {\n\treturn databaseManager.buildConnectionString(database);\n};\n\n/**\n * Close a specific database pool by database name\n */\nconst _closeDbPool = async (database: string): Promise<void> => {\n\treturn databaseManager.closePoolByDatabase(database);\n};\n\n/**\n * Close a specific database pool by connection string\n */\nconst _closeDbPoolByConnectionString = async (connectionString: string): Promise<void> => {\n\treturn databaseManager.closePool(connectionString);\n};\n\n/**\n * Close all database pools\n */\nconst _closeAllDbPools = async (): Promise<void> => {\n\treturn databaseManager.closeAll();\n};\n\n/**\n * Get list of active pool connection strings\n */\nconst _getActivePools = (): string[] => {\n\treturn databaseManager.getActivePools();\n};\n\n/**\n * Get the SQLite database connection (single file, opened once)\n */\nexport const getSqliteDb = (): Database.Database => {\n\treturn databaseManager.getSqliteDb();\n};\n\n/**\n * Get or create the MongoDB client\n */\nexport const getMongoClient = (): Promise<MongoClient> => {\n\treturn databaseManager.getMongoClient();\n};\n\n/**\n * Get the MongoDB database name from the connection URL\n */\nexport const getMongoDbName = (): string => {\n\treturn databaseManager.getMongoDbName();\n};\n\n/**\n * Get a MongoDB database instance\n */\nexport const getMongoDb = (dbName?: string) => {\n\treturn databaseManager.getMongoDb(dbName);\n};\n\n/**\n * Get or create a Redis client for the specified logical DB index\n */\nexport const getRedisClient = (dbIndex?: number): Promise<Redis> => {\n\treturn databaseManager.getRedisClient(dbIndex);\n};\n\nexport const getIsolatedRedisClient = (dbIndex?: number): Promise<Redis> => {\n\treturn databaseManager.getIsolatedRedisClient(dbIndex);\n};\n\n/**\n * Get the default Redis logical DB index from the connection URL\n */\nexport const getRedisDefaultDb = (): number => {\n\treturn databaseManager.getRedisDefaultDb();\n};\n\nexport const isValidObjectId = (value: unknown): value is string => {\n\treturn typeof value === \"string\" && ObjectId.isValid(value);\n};\n\nexport const coerceObjectId = (value: unknown): unknown => {\n\tif (typeof value === \"string\" && ObjectId.isValid(value)) {\n\t\treturn new ObjectId(value);\n\t}\n\treturn value;\n};\n","import type { DatabaseTypeSchema } from \"@db-studio/shared/types\";\nimport {\n\tgetDbPool,\n\tgetDbType,\n\tgetMongoClient,\n\tgetMongoDbName,\n\tgetMssqlPool,\n\tgetMysqlPool,\n\tgetRedisClient,\n\tgetSqliteDb,\n} from \"@/db-manager.js\";\n\nconst DATABASE_NAMES: Record<DatabaseTypeSchema, string> = {\n\tpg: \"PostgreSQL\",\n\tmysql: \"MySQL\",\n\tmssql: \"SQL Server\",\n\tmongodb: \"MongoDB\",\n\tsqlite: \"SQLite\",\n\tredis: \"Redis\",\n};\n\nconst STARTUP_TIMEOUT_MS = 2_000;\n\nconst withStartupTimeout = async <T>(operation: Promise<T>): Promise<T> => {\n\tlet timeout: ReturnType<typeof setTimeout> | undefined;\n\ttry {\n\t\treturn await Promise.race([\n\t\t\toperation,\n\t\t\tnew Promise<never>((_, reject) => {\n\t\t\t\ttimeout = setTimeout(\n\t\t\t\t\t() => reject(new Error(\"Database startup check timed out\")),\n\t\t\t\t\tSTARTUP_TIMEOUT_MS,\n\t\t\t\t);\n\t\t\t}),\n\t\t]);\n\t} finally {\n\t\tif (timeout) clearTimeout(timeout);\n\t}\n};\n\nexport type DatabaseConnectionDetails = {\n\ttype: DatabaseTypeSchema;\n\tname: string;\n\tdestination: string;\n};\n\nexport const getDatabaseConnectionDetails = (\n\tdatabaseUrl: string,\n): DatabaseConnectionDetails => {\n\tconst type = getDbType();\n\tif (type === \"sqlite\") {\n\t\treturn { type, name: DATABASE_NAMES[type], destination: \"local file\" };\n\t}\n\n\tconst url = new URL(databaseUrl);\n\tconst defaultPorts: Record<Exclude<DatabaseTypeSchema, \"sqlite\">, number> = {\n\t\tpg: 5432,\n\t\tmysql: 3306,\n\t\tmssql: 1433,\n\t\tmongodb: 27017,\n\t\tredis: 6379,\n\t};\n\tconst port = Number.parseInt(url.port, 10) || defaultPorts[type];\n\n\treturn { type, name: DATABASE_NAMES[type], destination: `${url.hostname}:${port}` };\n};\n\nexport const checkDatabaseConnection = async (type: DatabaseTypeSchema): Promise<void> => {\n\tswitch (type) {\n\t\tcase \"pg\":\n\t\t\tawait withStartupTimeout(getDbPool().query(\"SELECT 1\"));\n\t\t\treturn;\n\t\tcase \"mysql\":\n\t\t\tawait getMysqlPool().query(\"SELECT 1\");\n\t\t\treturn;\n\t\tcase \"mssql\":\n\t\t\tawait (await getMssqlPool()).request().query(\"SELECT 1\");\n\t\t\treturn;\n\t\tcase \"mongodb\": {\n\t\t\tconst client = await getMongoClient();\n\t\t\tawait client.db(getMongoDbName()).command({ ping: 1 });\n\t\t\treturn;\n\t\t}\n\t\tcase \"sqlite\":\n\t\t\tgetSqliteDb().prepare(\"SELECT 1\").get();\n\t\t\treturn;\n\t\tcase \"redis\":\n\t\t\tawait (await getRedisClient()).ping();\n\t}\n};\n","import type { DatabaseTypeSchema } from \"@db-studio/shared/types/database.types.js\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { IDbAdapter } from \"./adapter.interface.js\";\nimport type { IKeyValueAdapter } from \"./key-value-adapter.interface.js\";\n\nexport class AdapterRegistry {\n\tprivate adapters = new Map<DatabaseTypeSchema, IDbAdapter>();\n\n\tregister(type: DatabaseTypeSchema, adapter: IDbAdapter): void {\n\t\tthis.adapters.set(type, adapter);\n\t}\n\n\tget(type: DatabaseTypeSchema): IDbAdapter {\n\t\tconst adapter = this.adapters.get(type);\n\t\tif (!adapter) {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: `Unsupported database type: \"${type}\". Supported types: ${this.getSupportedTypes().join(\", \")}`,\n\t\t\t});\n\t\t}\n\t\treturn adapter;\n\t}\n\n\thas(type: string): type is DatabaseTypeSchema {\n\t\treturn this.adapters.has(type as DatabaseTypeSchema);\n\t}\n\n\tgetSupportedTypes(): DatabaseTypeSchema[] {\n\t\treturn [...this.adapters.keys()];\n\t}\n}\n\nexport const adapterRegistry = new AdapterRegistry();\n\n/**\n * Drop-in replacement for getDaoFactory() — resolves to the registered\n * IDbAdapter for the given database type.\n */\nexport function getAdapter(dbType: DatabaseTypeSchema): IDbAdapter {\n\treturn adapterRegistry.get(dbType);\n}\n\nconst isKeyValueAdapter = (adapter: IDbAdapter): adapter is IDbAdapter & IKeyValueAdapter =>\n\t\"scanKeys\" in adapter && typeof adapter.scanKeys === \"function\";\n\nexport function assertKeyValueAdapter(\n\tadapter: IDbAdapter,\n\tdbType: DatabaseTypeSchema,\n): IKeyValueAdapter {\n\tif (!isKeyValueAdapter(adapter)) {\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: `Key browsing is not supported for database type: \"${dbType}\"`,\n\t\t});\n\t}\n\treturn adapter;\n}\n\nexport function getKeyValueAdapter(dbType: DatabaseTypeSchema): IKeyValueAdapter {\n\treturn assertKeyValueAdapter(adapterRegistry.get(dbType), dbType);\n}\n","import type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tCellValue,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tCursorData,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tTableDataResultSchemaType,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { DatabaseError } from \"pg\";\nimport type { GetTableDataParams, IDbAdapter } from \"@/adapters/adapter.interface.js\";\n\n/** One record's pending updates, addressed by every one of its key columns. */\nexport interface RecordUpdateGroup {\n\tkeyValues: unknown[];\n\trowUpdates: Array<{ columnName: string; value: unknown }>;\n}\n\n/** Bundles a paginated data query together with its companion COUNT query. */\nexport interface QueryBundle {\n\t/** Data query — the final bound parameter must be `limit + 1` for hasMore detection. */\n\tsql: string;\n\tvalues: unknown[];\n\t/** COUNT query that reflects only the active filters (no cursor). */\n\tcountSql: string;\n\tcountValues: unknown[];\n}\n\n/** A single row after adapter-level normalization (column → CellValue). */\nexport type NormalizedRow = Record<string, CellValue>;\n\nfunction notImplemented(method: string): never {\n\tthrow new HTTPException(501, {\n\t\tmessage: `${method} is not implemented for this database type`,\n\t});\n}\n\nexport abstract class BaseAdapter implements IDbAdapter {\n\t// =========================================================\n\t// Abstract — every concrete adapter MUST implement these\n\t// =========================================================\n\n\t/** Execute a parameterised query and return the result rows. */\n\tprotected abstract runQuery<T>(db: string, sql: string, values: unknown[]): Promise<T>;\n\n\t/**\n\t * Build a paginated data query and a companion COUNT query for getTableData().\n\t * The data query must append `limit + 1` as its final bound value so the\n\t * template method can detect whether a next page exists.\n\t */\n\tprotected abstract buildTableDataQuery(params: GetTableDataParams): QueryBundle;\n\n\t/** Map raw DB rows to NormalizedRow records. */\n\tprotected abstract normalizeRows(rawRows: unknown[]): NormalizedRow[];\n\n\t/**\n\t * Compute next/previous cursors from the final page rows.\n\t * Called after rows are trimmed to `limit` and reversed (for desc direction).\n\t */\n\tprotected abstract buildCursors(\n\t\tparams: GetTableDataParams,\n\t\trows: NormalizedRow[],\n\t\thasMore: boolean,\n\t): { nextCursor: string | null; prevCursor: string | null };\n\n\t/** Return the DB-specific quoted form of an identifier (table or column name). */\n\tprotected abstract quoteIdentifier(name: string): string;\n\n\tabstract mapToUniversalType(nativeType: string): DataTypes;\n\tabstract mapFromUniversalType(universalType: string): string;\n\n\t// =========================================================\n\t// Protected helpers — shared across all adapters\n\t// =========================================================\n\n\t/**\n\t * Wrap any thrown value in an HTTPException.\n\t * Detects connection errors for all supported databases and maps them to 503.\n\t * Concrete adapters can override to handle additional DB-specific error codes.\n\t */\n\tprotected wrapError(e: unknown): HTTPException {\n\t\tif (e instanceof HTTPException) return e;\n\n\t\tif (e instanceof Error) {\n\t\t\tconst err = e as { code?: string; errno?: number };\n\n\t\t\tconst isConnectionError =\n\t\t\t\terr.code === \"ECONNREFUSED\" ||\n\t\t\t\terr.code === \"ENOTFOUND\" ||\n\t\t\t\terr.code === \"ETIMEDOUT\" ||\n\t\t\t\terr.code === \"ER_ACCESS_DENIED_ERROR\" ||\n\t\t\t\terr.code === \"ER_BAD_HOST_ERROR\" ||\n\t\t\t\terr.code === \"ECONNRESET\" ||\n\t\t\t\terr.errno === 1045 || // MySQL ER_ACCESS_DENIED_ERROR\n\t\t\t\terr.errno === 2003 || // MySQL can't connect to server\n\t\t\t\terr.errno === 2002 || // MySQL can't connect to local server\n\t\t\t\te.message.includes(\"ECONNREFUSED\") ||\n\t\t\t\te.message.includes(\"connection refused\") ||\n\t\t\t\te.message.includes(\"timeout expired\") ||\n\t\t\t\te.message.includes(\"Connection terminated\") ||\n\t\t\t\te.message.includes(\"MongoNetworkError\") ||\n\t\t\t\te.message.includes(\"MongoServerSelectionError\") ||\n\t\t\t\te.message.includes(\"Login failed\") ||\n\t\t\t\te.message.startsWith(\"NOAUTH\") || // Redis: auth required\n\t\t\t\te.message.startsWith(\"WRONGPASS\") || // Redis: invalid credentials\n\t\t\t\te.message.startsWith(\"LOADING\") || // Redis: dataset loading\n\t\t\t\te.message.startsWith(\"BUSY\") || // Redis: server busy\n\t\t\t\te.message.startsWith(\"READONLY\") || // Redis: read-only replica\n\t\t\t\te.message.startsWith(\"CLUSTERDOWN\") || // Redis: cluster down\n\t\t\t\te.message.includes(\"Redis cluster mode is not supported\") ||\n\t\t\t\t(e instanceof DatabaseError && e.code?.startsWith(\"08\")); // PG connection exception class\n\n\t\t\tif (isConnectionError) {\n\t\t\t\treturn new HTTPException(503, { message: e.message, cause: e });\n\t\t\t}\n\n\t\t\treturn new HTTPException(500, { message: e.message, cause: e });\n\t\t}\n\n\t\treturn new HTTPException(500, { message: \"Internal server error\", cause: e });\n\t}\n\n\t/**\n\t * Resolve the key columns a record update must match on. `primaryKeys` carries\n\t * every component of a composite key; `primaryKey` is the single-column form.\n\t */\n\tprotected resolveKeyColumns(params: UpdateRecordsSchemaType): string[] {\n\t\treturn params.primaryKeys?.length ? params.primaryKeys : [params.primaryKey];\n\t}\n\n\t/**\n\t * Group updates by the record they target so each row is written once, matched\n\t * on every key column. Throws 400 when a key column is absent from the row.\n\t */\n\tprotected groupUpdatesByKey(\n\t\tparams: UpdateRecordsSchemaType,\n\t\tkeyColumns: string[],\n\t): RecordUpdateGroup[] {\n\t\tconst groups = new Map<string, RecordUpdateGroup>();\n\n\t\tfor (const update of params.updates) {\n\t\t\tconst keyValues = keyColumns.map((column) => {\n\t\t\t\tconst value = update.rowData[column];\n\t\t\t\tif (value === undefined || value === null) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: `Primary key \"${column}\" not found in row data.`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t});\n\n\t\t\tconst groupKey = JSON.stringify(keyValues.map((value) => String(value)));\n\t\t\tconst group: RecordUpdateGroup = groups.get(groupKey) ?? { keyValues, rowUpdates: [] };\n\t\t\tgroup.rowUpdates.push({ columnName: update.columnName, value: update.value });\n\t\t\tgroups.set(groupKey, group);\n\t\t}\n\n\t\treturn [...groups.values()];\n\t}\n\n\t/** Human-readable `col = value` list used in \"record not found\" errors. */\n\tprotected describeKey(keyColumns: string[], keyValues: unknown[]): string {\n\t\treturn keyColumns.map((column, i) => `${column} = ${keyValues[i]}`).join(\", \");\n\t}\n\n\tprotected assertDifferentTableName(tableName: string, newTableName: string): void {\n\t\tif (tableName === newTableName) {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: `New table name must be different from \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\t/** Encode cursor data to a URL-safe base64 string. */\n\tprotected encodeCursor(data: CursorData): string {\n\t\treturn Buffer.from(JSON.stringify(data)).toString(\"base64url\");\n\t}\n\n\t/** Decode a base64url cursor string; returns null if malformed. */\n\tprotected decodeCursor(cursor: string): CursorData | null {\n\t\ttry {\n\t\t\treturn JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf-8\"));\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Normalize a single raw row by casting each value to CellValue.\n\t * Convenience helper for use inside normalizeRows() implementations.\n\t */\n\tprotected normalizeRow(row: Record<string, unknown>): NormalizedRow {\n\t\tconst out: NormalizedRow = {};\n\t\tfor (const [k, v] of Object.entries(row)) {\n\t\t\tout[k] = v as CellValue;\n\t\t}\n\t\treturn out;\n\t}\n\n\t// =========================================================\n\t// Template Methods — shared skeleton, DB-specific steps via abstract methods\n\t// =========================================================\n\n\tasync getTableData(params: GetTableDataParams): Promise<TableDataResultSchemaType> {\n\t\ttry {\n\t\t\tconst { db, limit = 50, direction = \"asc\" } = params;\n\t\t\tconst bundle = this.buildTableDataQuery(params);\n\n\t\t\t// Total count with active filters only (no cursor)\n\t\t\tconst countRes = await this.runQuery<Record<string, unknown>[]>(\n\t\t\t\tdb,\n\t\t\t\tbundle.countSql,\n\t\t\t\tbundle.countValues,\n\t\t\t);\n\t\t\tconst total = Number(countRes[0]?.total ?? 0);\n\n\t\t\t// Fetch limit+1 rows to determine whether a next page exists\n\t\t\tlet rawRows = await this.runQuery<unknown[]>(db, bundle.sql, bundle.values);\n\t\t\tconst hasMore = rawRows.length > limit;\n\t\t\tif (hasMore) rawRows = rawRows.slice(0, limit);\n\n\t\t\tlet rows = this.normalizeRows(rawRows);\n\t\t\tif (direction === \"desc\") rows = rows.reverse();\n\n\t\t\tconst { nextCursor, prevCursor } = this.buildCursors(params, rows, hasMore);\n\n\t\t\treturn {\n\t\t\t\tdata: rows,\n\t\t\t\tmeta: {\n\t\t\t\t\tlimit,\n\t\t\t\t\ttotal,\n\t\t\t\t\thasNextPage: direction === \"asc\" ? hasMore : !!params.cursor,\n\t\t\t\t\thasPreviousPage: direction === \"asc\" ? !!params.cursor : hasMore,\n\t\t\t\t\tnextCursor,\n\t\t\t\t\tprevCursor,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync exportTableData({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<{ cols: string[]; rows: Record<string, unknown>[] }> {\n\t\ttry {\n\t\t\tconst sql = `SELECT * FROM ${this.quoteIdentifier(tableName)}`;\n\t\t\tconst rows = await this.runQuery<Record<string, unknown>[]>(db, sql, []);\n\n\t\t\tif (!rows || rows.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Table \"${tableName}\" does not exist or has no data`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst cols = Object.keys(rows[0]);\n\t\t\treturn { cols, rows };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// Default stubs — override in concrete adapters\n\t// =========================================================\n\n\tgetDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\treturn notImplemented(\"getDatabasesList\");\n\t}\n\tgetCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\treturn notImplemented(\"getCurrentDatabase\");\n\t}\n\tgetDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\treturn notImplemented(\"getDatabaseConnectionInfo\");\n\t}\n\tgetTablesList(_db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\treturn notImplemented(\"getTablesList\");\n\t}\n\tcreateTable(_params: {\n\t\ttableData: CreateTableSchemaType;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<void> {\n\t\treturn notImplemented(\"createTable\");\n\t}\n\tdeleteTable(_params: DeleteTableParams): Promise<DeleteTableResult> {\n\t\treturn notImplemented(\"deleteTable\");\n\t}\n\trenameTable(_params: RenameTableParamsSchemaType): Promise<void> {\n\t\treturn notImplemented(\"renameTable\");\n\t}\n\tgetTableSchema(_params: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\treturn notImplemented(\"getTableSchema\");\n\t}\n\tgetTableColumns(_params: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\treturn notImplemented(\"getTableColumns\");\n\t}\n\taddColumn(_params: AddColumnParamsSchemaType): Promise<void> {\n\t\treturn notImplemented(\"addColumn\");\n\t}\n\tdeleteColumn(_params: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\treturn notImplemented(\"deleteColumn\");\n\t}\n\talterColumn(_params: AlterColumnParamsSchemaType): Promise<void> {\n\t\treturn notImplemented(\"alterColumn\");\n\t}\n\trenameColumn(_params: RenameColumnParamsSchemaType): Promise<void> {\n\t\treturn notImplemented(\"renameColumn\");\n\t}\n\taddRecord(_params: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\treturn notImplemented(\"addRecord\");\n\t}\n\tupdateRecords(_params: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\treturn notImplemented(\"updateRecords\");\n\t}\n\tdeleteRecords(_params: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\treturn notImplemented(\"deleteRecords\");\n\t}\n\tforceDeleteRecords(_params: DeleteRecordParams): Promise<{ deletedCount: number }> {\n\t\treturn notImplemented(\"forceDeleteRecords\");\n\t}\n\tbulkInsertRecords(_params: BulkInsertRecordsParams): Promise<BulkInsertResult> {\n\t\treturn notImplemented(\"bulkInsertRecords\");\n\t}\n\texecuteQuery(_params: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\treturn notImplemented(\"executeQuery\");\n\t}\n}\n","import * as dbManager from \"@/db-manager.js\";\n\nexport const getDbPool: typeof dbManager.getDbPool = (database) =>\n\tdbManager.getDbPool(database);\n\nexport const getMysqlPool: typeof dbManager.getMysqlPool = (database) =>\n\tdbManager.getMysqlPool(database);\n\nexport const getMssqlPool: typeof dbManager.getMssqlPool = (database) =>\n\tdbManager.getMssqlPool(database);\n\nexport const getSqliteDb: typeof dbManager.getSqliteDb = () => dbManager.getSqliteDb();\n\nexport const getMongoClient: typeof dbManager.getMongoClient = () =>\n\tdbManager.getMongoClient();\n\nexport const getMongoDbName: typeof dbManager.getMongoDbName = () =>\n\tdbManager.getMongoDbName();\n\nexport const getMongoDb: typeof dbManager.getMongoDb = (dbName) =>\n\tdbManager.getMongoDb(dbName);\n\nexport const getRedisClient: typeof dbManager.getRedisClient = (dbIndex) =>\n\tdbManager.getRedisClient(dbIndex);\n\nexport const getIsolatedRedisClient: typeof dbManager.getIsolatedRedisClient = (dbIndex) =>\n\tdbManager.getIsolatedRedisClient(dbIndex);\n\nexport const getRedisDefaultDb: typeof dbManager.getRedisDefaultDb = () =>\n\tdbManager.getRedisDefaultDb();\n","/**\n * Mongo reports only databases that physically exist, so a freshly created\n * (empty) database never appears in `listDatabases`. Filtering system databases\n * therefore has to re-add the connected database explicitly, otherwise a user\n * connected to an empty database sees an empty selector — or, worse, a fallback\n * that shows exactly the `admin`/`config`/`local` entries we set out to hide.\n */\n\nconst SYSTEM_DATABASES = new Set([\"admin\", \"config\", \"local\"]);\n\nexport interface MongoDatabaseSummary {\n\tname: string;\n\tsizeOnDisk?: number;\n}\n\n/**\n * Hide Mongo's system databases while keeping the connected database visible,\n * whether or not `listDatabases` reported it.\n *\n * @param databases - Raw entries from `admin().listDatabases()`\n * @param currentDb - The database the connection string points at\n */\nexport const visibleMongoDatabases = (\n\tdatabases: readonly MongoDatabaseSummary[],\n\tcurrentDb: string,\n): MongoDatabaseSummary[] => {\n\tconst visible = databases.filter(\n\t\t(db) => !SYSTEM_DATABASES.has(db.name) || db.name === currentDb,\n\t);\n\n\tif (!currentDb || visible.some((db) => db.name === currentDb)) return visible;\n\treturn [...visible, { name: currentDb, sizeOnDisk: 0 }];\n};\n","/**\n * Parse DATABASE_URL to extract host and port\n */\nexport function parseDatabaseUrl(): { host: string; port: number } {\n\tconst databaseUrl = process.env.DATABASE_URL;\n\n\tif (!databaseUrl) {\n\t\treturn { host: \"localhost\", port: 5432 };\n\t}\n\n\ttry {\n\t\tconst url = new URL(databaseUrl);\n\t\tconst protocol = url.protocol.replace(\":\", \"\");\n\t\tconst defaultPort =\n\t\t\tprotocol === \"mongodb\" || protocol === \"mongodb+srv\"\n\t\t\t\t? 27017\n\t\t\t\t: protocol === \"mssql\" || protocol === \"sqlserver\"\n\t\t\t\t\t? 1433\n\t\t\t\t\t: protocol === \"mysql\" || protocol === \"mysql2\"\n\t\t\t\t\t\t? 3306\n\t\t\t\t\t\t: 5432;\n\t\treturn {\n\t\t\thost: url.hostname || \"localhost\",\n\t\t\tport: Number.parseInt(url.port, 10) || defaultPort,\n\t\t};\n\t} catch (error) {\n\t\tconsole.error(\"Failed to parse DATABASE_URL:\", error);\n\t\treturn { host: \"localhost\", port: 5432 };\n\t}\n}\n","import type { FilterType, SortDirection, SortType } from \"@db-studio/shared/types\";\nimport { coerceObjectId, isValidObjectId } from \"@/db-manager.js\";\n\nconst escapeRegex = (value: string) => value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\nconst parseFilterValue = (raw: string): unknown => {\n\tconst trimmed = raw.trim();\n\tif (trimmed === \"null\") return null;\n\tif (trimmed === \"true\") return true;\n\tif (trimmed === \"false\") return false;\n\tconst asNumber = Number(trimmed);\n\tif (!Number.isNaN(asNumber) && trimmed !== \"\") return asNumber;\n\tif (isValidObjectId(trimmed)) return coerceObjectId(trimmed);\n\treturn trimmed;\n};\n\nexport function buildMatchStage(filters: FilterType[]): Record<string, unknown> {\n\tif (!filters || filters.length === 0) return {};\n\tconst andConditions: Record<string, unknown>[] = [];\n\n\tfor (const filter of filters) {\n\t\tconst field = filter.columnName;\n\t\tconst value = parseFilterValue(filter.value);\n\t\tconst op = filter.operator.toLowerCase();\n\t\tif (!field) continue;\n\n\t\tswitch (op) {\n\t\t\tcase \"=\":\n\t\t\t\tandConditions.push({ [field]: value });\n\t\t\t\tbreak;\n\t\t\tcase \"!=\":\n\t\t\t\tandConditions.push({ [field]: { $ne: value } });\n\t\t\t\tbreak;\n\t\t\tcase \">\":\n\t\t\t\tandConditions.push({ [field]: { $gt: value } });\n\t\t\t\tbreak;\n\t\t\tcase \">=\":\n\t\t\t\tandConditions.push({ [field]: { $gte: value } });\n\t\t\t\tbreak;\n\t\t\tcase \"<\":\n\t\t\t\tandConditions.push({ [field]: { $lt: value } });\n\t\t\t\tbreak;\n\t\t\tcase \"<=\":\n\t\t\t\tandConditions.push({ [field]: { $lte: value } });\n\t\t\t\tbreak;\n\t\t\tcase \"is\":\n\t\t\t\tandConditions.push({ [field]: value });\n\t\t\t\tbreak;\n\t\t\tcase \"is not\":\n\t\t\t\tandConditions.push({ [field]: { $ne: value } });\n\t\t\t\tbreak;\n\t\t\tcase \"like\":\n\t\t\t\tandConditions.push({ [field]: { $regex: escapeRegex(String(value)), $options: \"\" } });\n\t\t\t\tbreak;\n\t\t\tcase \"not like\":\n\t\t\t\tandConditions.push({\n\t\t\t\t\t[field]: { $not: { $regex: escapeRegex(String(value)), $options: \"\" } },\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"ilike\":\n\t\t\t\tandConditions.push({ [field]: { $regex: escapeRegex(String(value)), $options: \"i\" } });\n\t\t\t\tbreak;\n\t\t\tcase \"not ilike\":\n\t\t\t\tandConditions.push({\n\t\t\t\t\t[field]: { $not: { $regex: escapeRegex(String(value)), $options: \"i\" } },\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tandConditions.push({ [field]: value });\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn andConditions.length ? { $and: andConditions } : {};\n}\n\nexport function buildSortStage(\n\tsort: string | SortType[] | undefined,\n\torder?: SortDirection,\n): Record<string, 1 | -1> {\n\tif (!sort) return { _id: 1 };\n\tif (Array.isArray(sort)) {\n\t\tif (sort.length === 0) return { _id: 1 };\n\t\treturn Object.fromEntries(\n\t\t\tsort.map((s) => [s.columnName, s.direction === \"desc\" ? -1 : 1]),\n\t\t);\n\t}\n\tif (typeof sort === \"string\" && sort.length > 0) {\n\t\treturn { [sort]: order === \"desc\" ? -1 : 1 };\n\t}\n\treturn { _id: 1 };\n}\n\nexport function encodeMongoCursor(offset: number): string {\n\treturn Buffer.from(JSON.stringify({ offset })).toString(\"base64url\");\n}\n\nexport function decodeMongoCursor(cursor?: string): number {\n\tif (!cursor) return 0;\n\ttry {\n\t\tconst parsed = JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf-8\")) as {\n\t\t\toffset?: number;\n\t\t};\n\t\treturn typeof parsed.offset === \"number\" ? parsed.offset : 0;\n\t} catch {\n\t\treturn 0;\n\t}\n}\n","import type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tTableDataResultSchemaType,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getMongoClient, getMongoDb, getMongoDbName } from \"@/adapters/connections.js\";\nimport { coerceObjectId, isValidObjectId } from \"@/db-manager.js\";\nimport { visibleMongoDatabases } from \"@/utils/mongo-database-visibility.js\";\nimport { parseDatabaseUrl } from \"@/utils/parse-database-url.js\";\nimport {\n\tbuildMatchStage,\n\tbuildSortStage,\n\tdecodeMongoCursor,\n\tencodeMongoCursor,\n} from \"./mongo.pipeline-builder.js\";\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst normalizeValue = (value: unknown): unknown => {\n\tif (value instanceof Date) return value.toISOString();\n\tif (typeof value === \"bigint\") return value.toString();\n\tif (value && typeof value === \"object\") {\n\t\tif (\"_bsontype\" in value && (value as { _bsontype?: string })._bsontype === \"ObjectId\") {\n\t\t\treturn (value as unknown as { toHexString: () => string }).toHexString();\n\t\t}\n\t\tif (Array.isArray(value)) return value.map((item) => normalizeValue(item));\n\t\treturn Object.fromEntries(\n\t\t\tObject.entries(value as Record<string, unknown>).map(([k, v]) => [k, normalizeValue(v)]),\n\t\t);\n\t}\n\treturn value;\n};\n\nconst normalizeDoc = (doc: unknown): Record<string, unknown> =>\n\tnormalizeValue(doc) as Record<string, unknown>;\n\nconst inferValueType = (value: unknown): DataTypes => {\n\tif (value instanceof Date) return \"date\";\n\tif (value && typeof value === \"object\") {\n\t\tif (Array.isArray(value)) return \"array\";\n\t\tif (\"_bsontype\" in value) return \"text\";\n\t\treturn \"json\";\n\t}\n\tif (typeof value === \"boolean\") return \"boolean\";\n\tif (typeof value === \"number\" || typeof value === \"bigint\") return \"number\";\n\treturn \"text\";\n};\n\nconst dataTypeLabel = (dt: DataTypes): string => {\n\tswitch (dt) {\n\t\tcase \"number\":\n\t\t\treturn \"numeric\";\n\t\tcase \"boolean\":\n\t\t\treturn \"boolean\";\n\t\tcase \"json\":\n\t\t\treturn \"json\";\n\t\tcase \"date\":\n\t\t\treturn \"date\";\n\t\tcase \"array\":\n\t\t\treturn \"array\";\n\t\tcase \"enum\":\n\t\t\treturn \"enum\";\n\t\tdefault:\n\t\t\treturn \"text\";\n\t}\n};\n\nconst canCoerce = (value: unknown): boolean =>\n\ttypeof value === \"string\" && isValidObjectId(value);\n\nconst toMongoId = (value: unknown) => coerceObjectId(value as string);\n\nconst formatBytes = (bytes: number): string => {\n\tif (!Number.isFinite(bytes)) return \"n/a\";\n\tconst units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n\tlet v = bytes;\n\tlet i = 0;\n\twhile (v >= 1024 && i < units.length - 1) {\n\t\tv /= 1024;\n\t\ti++;\n\t}\n\treturn `${v.toFixed(1)} ${units[i]}`;\n};\n\nconst MONGO_BSON_TYPES = new Set([\n\t\"double\",\n\t\"string\",\n\t\"object\",\n\t\"array\",\n\t\"binData\",\n\t\"undefined\",\n\t\"objectId\",\n\t\"bool\",\n\t\"date\",\n\t\"null\",\n\t\"regex\",\n\t\"dbPointer\",\n\t\"javascript\",\n\t\"symbol\",\n\t\"javascriptWithScope\",\n\t\"int\",\n\t\"timestamp\",\n\t\"long\",\n\t\"decimal\",\n\t\"minKey\",\n\t\"maxKey\",\n]);\n\nconst mapBsonType = (rawType: string): string => {\n\tconst n = rawType.trim();\n\tif (MONGO_BSON_TYPES.has(n)) return n;\n\tswitch (n.toLowerCase()) {\n\t\tcase \"boolean\":\n\t\t\treturn \"bool\";\n\t\tcase \"objectid\":\n\t\t\treturn \"objectId\";\n\t\tcase \"binary\":\n\t\t\treturn \"binData\";\n\t\tdefault:\n\t\t\treturn n;\n\t}\n};\n\nconst inferBsonType = (value: unknown): string => {\n\tif (value === null || value === undefined) return \"null\";\n\tif (value instanceof Date) return \"date\";\n\tif (typeof value === \"boolean\") return \"bool\";\n\tif (typeof value === \"number\") return Number.isInteger(value) ? \"int\" : \"double\";\n\tif (typeof value === \"bigint\") return \"long\";\n\tif (Array.isArray(value)) return \"array\";\n\tif (typeof value === \"object\") {\n\t\tconst bson = (value as { _bsontype?: string })._bsontype;\n\t\tif (bson === \"ObjectId\") return \"objectId\";\n\t\tif (bson === \"Decimal128\") return \"decimal\";\n\t\tif (bson === \"Binary\") return \"binData\";\n\t\tif (bson === \"Timestamp\") return \"timestamp\";\n\t\tif (bson) return bson.toLowerCase();\n\t\treturn \"object\";\n\t}\n\treturn \"string\";\n};\n\nconst resolveFieldDefault = (\n\tdefaultValue: string | null | undefined,\n\tcolumnType: string,\n): unknown => {\n\tif (defaultValue !== undefined && defaultValue !== null && defaultValue.trim() !== \"\") {\n\t\ttry {\n\t\t\treturn JSON.parse(defaultValue);\n\t\t} catch {\n\t\t\treturn defaultValue;\n\t\t}\n\t}\n\tswitch (columnType) {\n\t\tcase \"string\":\n\t\t\treturn \"\";\n\t\tcase \"int\":\n\t\tcase \"long\":\n\t\tcase \"double\":\n\t\tcase \"decimal\":\n\t\t\treturn 0;\n\t\tcase \"bool\":\n\t\t\treturn false;\n\t\tcase \"array\":\n\t\t\treturn [];\n\t\tcase \"object\":\n\t\t\treturn {};\n\t\tcase \"date\":\n\t\t\treturn new Date();\n\t\tdefault:\n\t\t\treturn null;\n\t}\n};\n\nconst normalizeIdFilter = (filter: Record<string, unknown>): Record<string, unknown> => {\n\tif (filter._id && typeof filter._id === \"string\") {\n\t\treturn { ...filter, _id: toMongoId(filter._id) };\n\t}\n\tif (filter._id && typeof filter._id === \"object\") {\n\t\tconst obj = filter._id as Record<string, unknown>;\n\t\tif (Array.isArray(obj.$in)) {\n\t\t\treturn {\n\t\t\t\t...filter,\n\t\t\t\t_id: {\n\t\t\t\t\t...obj,\n\t\t\t\t\t$in: obj.$in.map((v) => (typeof v === \"string\" ? toMongoId(v) : v)),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tif (Array.isArray(obj.$nin)) {\n\t\t\treturn {\n\t\t\t\t...filter,\n\t\t\t\t_id: {\n\t\t\t\t\t...obj,\n\t\t\t\t\t$nin: obj.$nin.map((v) => (typeof v === \"string\" ? toMongoId(v) : v)),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\treturn filter;\n};\n\ntype MongoQueryPayload = {\n\tcollection: string;\n\toperation:\n\t\t| \"find\"\n\t\t| \"aggregate\"\n\t\t| \"insertOne\"\n\t\t| \"insertMany\"\n\t\t| \"updateOne\"\n\t\t| \"updateMany\"\n\t\t| \"deleteOne\"\n\t\t| \"deleteMany\"\n\t\t| \"count\";\n\tfilter?: Record<string, unknown>;\n\tpipeline?: Record<string, unknown>[];\n\tdocument?: Record<string, unknown> | Record<string, unknown>[];\n\tupdate?: Record<string, unknown>;\n\toptions?: Record<string, unknown>;\n\tsort?: Record<string, 1 | -1>;\n\tlimit?: number;\n\tskip?: number;\n};\n\n// ---------------------------------------------------------------------------\n// MongoAdapter\n// ---------------------------------------------------------------------------\n\nexport class MongoAdapter extends BaseAdapter {\n\t// -----------------------------------------------------------------------\n\t// Abstract stubs — MongoDB does not use SQL\n\t// -----------------------------------------------------------------------\n\n\tprotected runQuery<T>(): Promise<T> {\n\t\tthrow new HTTPException(501, { message: \"runQuery is not supported for MongoDB\" });\n\t}\n\n\tprotected buildTableDataQuery(_params: GetTableDataParams): QueryBundle {\n\t\tthrow new HTTPException(501, {\n\t\t\tmessage: \"buildTableDataQuery is not supported for MongoDB\",\n\t\t});\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn rawRows.map((row) => this.normalizeRow(normalizeDoc(row)));\n\t}\n\n\tprotected buildCursors(): { nextCursor: string | null; prevCursor: string | null } {\n\t\treturn { nextCursor: null, prevCursor: null };\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn name;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Type mapping\n\t// -----------------------------------------------------------------------\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\tswitch (nativeType.toLowerCase()) {\n\t\t\tcase \"int\":\n\t\t\tcase \"long\":\n\t\t\tcase \"double\":\n\t\t\tcase \"decimal\":\n\t\t\t\treturn \"number\";\n\t\t\tcase \"bool\":\n\t\t\t\treturn \"boolean\";\n\t\t\tcase \"date\":\n\t\t\t\treturn \"date\";\n\t\t\tcase \"array\":\n\t\t\t\treturn \"array\";\n\t\t\tcase \"object\":\n\t\t\t\treturn \"json\";\n\t\t\tdefault:\n\t\t\t\treturn \"text\";\n\t\t}\n\t}\n\n\tmapFromUniversalType(universalType: string): string {\n\t\tswitch (universalType) {\n\t\t\tcase \"number\":\n\t\t\t\treturn \"double\";\n\t\t\tcase \"boolean\":\n\t\t\t\treturn \"bool\";\n\t\t\tcase \"date\":\n\t\t\t\treturn \"date\";\n\t\t\tcase \"array\":\n\t\t\t\treturn \"array\";\n\t\t\tcase \"json\":\n\t\t\t\treturn \"object\";\n\t\t\tdefault:\n\t\t\t\treturn \"string\";\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// wrapError override — adds MongoDB-specific connection error names\n\t// -----------------------------------------------------------------------\n\n\tprotected override wrapError(e: unknown): HTTPException {\n\t\tif (e instanceof HTTPException) return e;\n\t\tif (e instanceof Error) {\n\t\t\tconst name = (e as { name?: string }).name ?? \"\";\n\t\t\tif (\n\t\t\t\tname === \"MongoNetworkError\" ||\n\t\t\t\tname === \"MongoServerSelectionError\" ||\n\t\t\t\tname === \"MongoTopologyClosedError\"\n\t\t\t) {\n\t\t\t\treturn new HTTPException(503, { message: e.message, cause: e });\n\t\t\t}\n\t\t}\n\t\treturn super.wrapError(e);\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// getTableData — full override (skip/limit pagination)\n\t// -----------------------------------------------------------------------\n\n\toverride async getTableData(params: GetTableDataParams): Promise<TableDataResultSchemaType> {\n\t\ttry {\n\t\t\tconst { tableName, db, cursor, limit, direction = \"asc\", sort, order, filters } = params;\n\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst filterObj = buildMatchStage(filters ?? []);\n\t\t\tconst sortObj = buildSortStage(sort ?? \"\", order);\n\n\t\t\tconst safeLimit = limit && limit > 0 ? limit : 50;\n\t\t\tconst decodedOffset = decodeMongoCursor(cursor);\n\t\t\tconst offset = Number.isFinite(decodedOffset) && decodedOffset >= 0 ? decodedOffset : 0;\n\t\t\tconst skip = direction === \"desc\" ? Math.max(offset - safeLimit, 0) : offset;\n\n\t\t\tconst [total, rows] = await Promise.all([\n\t\t\t\tcollection.countDocuments(filterObj),\n\t\t\t\tcollection.find(filterObj).sort(sortObj).skip(skip).limit(safeLimit).toArray(),\n\t\t\t]);\n\n\t\t\tconst normalizedRows = rows.map((row) => normalizeDoc(row));\n\t\t\tconst nextOffset = skip + safeLimit;\n\t\t\tconst prevOffset = Math.max(skip - safeLimit, 0);\n\n\t\t\treturn {\n\t\t\t\tdata: normalizedRows,\n\t\t\t\tmeta: {\n\t\t\t\t\tlimit: safeLimit,\n\t\t\t\t\ttotal,\n\t\t\t\t\thasNextPage: nextOffset < total,\n\t\t\t\t\thasPreviousPage: skip > 0,\n\t\t\t\t\tnextCursor: nextOffset < total ? encodeMongoCursor(nextOffset) : null,\n\t\t\t\t\tprevCursor: skip > 0 ? encodeMongoCursor(prevOffset) : null,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// exportTableData — full override (no SELECT * in Mongo)\n\t// -----------------------------------------------------------------------\n\n\toverride async exportTableData({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<{ cols: string[]; rows: Record<string, unknown>[] }> {\n\t\ttry {\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst rows = await collection.find({}).limit(10000).toArray();\n\t\t\t// Nested documents stay nested: the JSON export needs the real structure,\n\t\t\t// and `getExportFile` flattens them for the CSV/XLSX sheet writer.\n\t\t\tconst normalized = rows.map((row) => normalizeDoc(row));\n\t\t\tconst cols = Array.from(new Set(normalized.flatMap((row) => Object.keys(row))));\n\t\t\treturn { cols, rows: normalized };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Database operations\n\t// -----------------------------------------------------------------------\n\n\toverride async getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst client = await getMongoClient();\n\t\t\tconst admin = client.db().admin();\n\t\t\tconst result = await admin.listDatabases();\n\t\t\tconst databases = result.databases ?? [];\n\t\t\tif (!databases[0]) {\n\t\t\t\tthrow new HTTPException(500, { message: \"No databases returned from MongoDB\" });\n\t\t\t}\n\t\t\treturn visibleMongoDatabases(databases, getMongoDbName()).map((db) => ({\n\t\t\t\tname: db.name,\n\t\t\t\tsize: formatBytes(db.sizeOnDisk ?? 0),\n\t\t\t\towner: \"n/a\",\n\t\t\t\tencoding: \"n/a\",\n\t\t\t}));\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\treturn { db: getMongoDbName() };\n\t}\n\n\toverride async getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\ttry {\n\t\t\tconst client = await getMongoClient();\n\t\t\tconst admin = client.db().admin();\n\t\t\tconst urlDefaults = parseDatabaseUrl();\n\t\t\tlet serverStatus: {\n\t\t\t\tversion?: string;\n\t\t\t\tconnections?: { current?: number; available?: number };\n\t\t\t} = {};\n\t\t\ttry {\n\t\t\t\tserverStatus = await admin.serverStatus();\n\t\t\t} catch (error) {\n\t\t\t\tconsole.warn(\"Failed to read MongoDB serverStatus:\", error);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\thost: urlDefaults.host,\n\t\t\t\tport: urlDefaults.port,\n\t\t\t\tuser: \"n/a\",\n\t\t\t\tdatabase: getMongoDbName(),\n\t\t\t\tversion: serverStatus.version ?? \"unknown\",\n\t\t\t\tactive_connections: serverStatus.connections?.current ?? 0,\n\t\t\t\tmax_connections:\n\t\t\t\t\t(serverStatus.connections?.current ?? 0) +\n\t\t\t\t\t(serverStatus.connections?.available ?? 0),\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Table operations\n\t// -----------------------------------------------------------------------\n\n\toverride async getTablesList(db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collections = await mongoDb.listCollections().toArray();\n\t\t\tconst results: TableInfoSchemaType[] = [];\n\t\t\tfor (const col of collections) {\n\t\t\t\tconst rowCount = await mongoDb.collection(col.name).estimatedDocumentCount();\n\t\t\t\tresults.push({ tableName: col.name, rowCount });\n\t\t\t}\n\t\t\treturn results;\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async createTable({\n\t\ttableData,\n\t\tdb,\n\t}: {\n\t\ttableData: CreateTableSchemaType;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<void> {\n\t\ttry {\n\t\t\tconst tableName = tableData?.tableName ?? \"\";\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collections = await mongoDb.listCollections({ name: tableName }).toArray();\n\t\t\tif (collections.length > 0) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Collection \"${tableName}\" already exists`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst fields = tableData?.fields ?? [];\n\t\t\tif (fields.length === 0) {\n\t\t\t\tawait mongoDb.createCollection(tableName);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst properties: Record<string, unknown> = {};\n\t\t\tconst required: string[] = [];\n\t\t\tfor (const field of fields) {\n\t\t\t\tconst bsonType = mapBsonType(field.columnType);\n\t\t\t\tif (!MONGO_BSON_TYPES.has(bsonType)) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: `Unsupported MongoDB BSON type \"${field.columnType}\" for field \"${field.columnName}\"`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (field.isArray) {\n\t\t\t\t\tproperties[field.columnName] = {\n\t\t\t\t\t\tbsonType: \"array\",\n\t\t\t\t\t\t...(bsonType !== \"array\" ? { items: { bsonType } } : {}),\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tproperties[field.columnName] = { bsonType };\n\t\t\t\t}\n\t\t\t\tif (!field.isNullable) required.push(field.columnName);\n\t\t\t}\n\n\t\t\tawait mongoDb.createCollection(tableName, {\n\t\t\t\tvalidator: {\n\t\t\t\t\t$jsonSchema: {\n\t\t\t\t\t\tbsonType: \"object\",\n\t\t\t\t\t\trequired,\n\t\t\t\t\t\tproperties,\n\t\t\t\t\t\tadditionalProperties: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tvalidationAction: \"error\",\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async deleteTable({\n\t\ttableName,\n\t\tdb,\n\t}: DeleteTableParams): Promise<DeleteTableResult> {\n\t\ttry {\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst rowCount = await collection.estimatedDocumentCount();\n\t\t\tawait collection.drop();\n\t\t\treturn { deletedCount: rowCount, fkViolation: false, relatedRecords: [] };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async renameTable(params: RenameTableParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, newTableName, db } = params;\n\t\t\tthis.assertDifferentTableName(tableName, newTableName);\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst existing = await mongoDb.listCollections({ name: tableName }).toArray();\n\t\t\tif (existing.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Collection \"${tableName}\" does not exist`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst target = await mongoDb.listCollections({ name: newTableName }).toArray();\n\t\t\tif (target.length > 0) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Collection \"${newTableName}\" already exists`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait mongoDb.collection(tableName).rename(newTableName);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async getTableSchema({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\ttry {\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collections = await mongoDb.listCollections({ name: tableName }).toArray();\n\t\t\tif (collections.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Collection \"${tableName}\" does not exist`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst docs = await collection.find({}).limit(200).toArray();\n\t\t\tconst totalDocs = await collection.estimatedDocumentCount();\n\n\t\t\tconst fieldTypes = new Map<string, Set<string>>();\n\t\t\tconst fieldPresence = new Map<string, number>();\n\t\t\tfor (const doc of docs) {\n\t\t\t\tfor (const [key, value] of Object.entries(doc)) {\n\t\t\t\t\tconst bsonType = inferBsonType(value);\n\t\t\t\t\tif (!fieldTypes.has(key)) {\n\t\t\t\t\t\tfieldTypes.set(key, new Set());\n\t\t\t\t\t\tfieldPresence.set(key, 0);\n\t\t\t\t\t}\n\t\t\t\t\tfieldTypes.get(key)?.add(bsonType);\n\t\t\t\t\tfieldPresence.set(key, (fieldPresence.get(key) ?? 0) + 1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst properties: Record<string, unknown> = {};\n\t\t\tconst required: string[] = [];\n\t\t\tfor (const [field, types] of fieldTypes.entries()) {\n\t\t\t\tconst presence = fieldPresence.get(field) ?? 0;\n\t\t\t\tconst typeList = Array.from(types).filter((t) => t !== \"null\");\n\t\t\t\tconst isNullable = types.has(\"null\") || presence < docs.length;\n\t\t\t\tif (presence === docs.length && docs.length > 0 && !isNullable) required.push(field);\n\t\t\t\tproperties[field] =\n\t\t\t\t\ttypeList.length === 1\n\t\t\t\t\t\t? { bsonType: isNullable ? [typeList[0], \"null\"] : typeList[0] }\n\t\t\t\t\t\t: { bsonType: isNullable ? [...typeList, \"null\"] : typeList };\n\t\t\t}\n\n\t\t\tconst schema = {\n\t\t\t\tcollection: tableName,\n\t\t\t\testimatedDocumentCount: totalDocs,\n\t\t\t\tsampledDocuments: docs.length,\n\t\t\t\tjsonSchema: {\n\t\t\t\t\tbsonType: \"object\",\n\t\t\t\t\trequired: required.length > 0 ? required : undefined,\n\t\t\t\t\tproperties,\n\t\t\t\t},\n\t\t\t};\n\t\t\treturn JSON.stringify(schema, null, 2);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Column operations\n\t// -----------------------------------------------------------------------\n\n\toverride async getTableColumns({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst documents = await collection.find({}).limit(200).toArray();\n\t\t\tconst totalDocs = documents.length;\n\n\t\t\tconst columnMap = new Map<\n\t\t\t\tstring,\n\t\t\t\t{ types: Set<DataTypes>; nullable: boolean; presentCount: number }\n\t\t\t>();\n\n\t\t\tconst ensureColumn = (columnName: string, value: unknown) => {\n\t\t\t\tconst dt = inferValueType(value);\n\t\t\t\tif (!columnMap.has(columnName)) {\n\t\t\t\t\tcolumnMap.set(columnName, {\n\t\t\t\t\t\ttypes: new Set([dt]),\n\t\t\t\t\t\tnullable: false,\n\t\t\t\t\t\tpresentCount: 1,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tconst entry = columnMap.get(columnName)!;\n\t\t\t\t\tentry.types.add(dt);\n\t\t\t\t\tentry.presentCount += 1;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfor (const doc of documents) {\n\t\t\t\tfor (const [key, value] of Object.entries(doc)) {\n\t\t\t\t\tif (value === null || value === undefined) {\n\t\t\t\t\t\tif (!columnMap.has(key)) {\n\t\t\t\t\t\t\tcolumnMap.set(key, {\n\t\t\t\t\t\t\t\ttypes: new Set([\"text\"]),\n\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\tpresentCount: 1,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst entry = columnMap.get(key)!;\n\t\t\t\t\t\t\tentry.nullable = true;\n\t\t\t\t\t\t\tentry.presentCount += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tensureColumn(key, value);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (totalDocs > 0) {\n\t\t\t\tfor (const entry of columnMap.values()) {\n\t\t\t\t\tif (entry.presentCount < totalDocs) entry.nullable = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!columnMap.has(\"_id\")) {\n\t\t\t\tcolumnMap.set(\"_id\", {\n\t\t\t\t\ttypes: new Set([\"text\"]),\n\t\t\t\t\tnullable: false,\n\t\t\t\t\tpresentCount: totalDocs,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn Array.from(columnMap.entries()).map(([columnName, meta]) => {\n\t\t\t\tconst dt = (meta.types.values().next().value ?? \"text\") as DataTypes;\n\t\t\t\treturn {\n\t\t\t\t\tcolumnName,\n\t\t\t\t\tdataType: dt,\n\t\t\t\t\tdataTypeLabel: dataTypeLabel(dt) as ColumnInfoSchemaType[\"dataTypeLabel\"],\n\t\t\t\t\tisNullable: meta.nullable,\n\t\t\t\t\tcolumnDefault: null,\n\t\t\t\t\tisPrimaryKey: columnName === \"_id\",\n\t\t\t\t\tisForeignKey: false,\n\t\t\t\t\treferencedTable: null,\n\t\t\t\t\treferencedColumn: null,\n\t\t\t\t\tenumValues: null,\n\t\t\t\t};\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async addColumn(params: AddColumnParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, columnName, columnType, defaultValue, isNullable, db } = params;\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collections = await mongoDb.listCollections({ name: tableName }).toArray();\n\t\t\tif (collections.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Collection \"${tableName}\" does not exist`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst conflict = await mongoDb\n\t\t\t\t.collection(tableName)\n\t\t\t\t.findOne({ [columnName]: { $exists: true } });\n\t\t\tif (conflict) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Field \"${columnName}\" already exists in collection \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst resolvedDefault = resolveFieldDefault(defaultValue, columnType);\n\t\t\tawait mongoDb\n\t\t\t\t.collection(tableName)\n\t\t\t\t.updateMany({}, { $set: { [columnName]: resolvedDefault } });\n\n\t\t\tconst collInfo = collections[0] as {\n\t\t\t\toptions?: {\n\t\t\t\t\tvalidator?: {\n\t\t\t\t\t\t$jsonSchema?: {\n\t\t\t\t\t\t\tproperties?: Record<string, unknown>;\n\t\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tconst existingSchema = collInfo.options?.validator?.$jsonSchema ?? {};\n\t\t\tconst properties: Record<string, unknown> = {\n\t\t\t\t...((existingSchema.properties as Record<string, unknown>) ?? {}),\n\t\t\t\t[columnName]: { bsonType: isNullable ? [columnType, \"null\"] : columnType },\n\t\t\t};\n\t\t\tconst required: string[] = [...(existingSchema.required ?? [])];\n\t\t\tif (!isNullable && !required.includes(columnName)) required.push(columnName);\n\n\t\t\tawait mongoDb.command({\n\t\t\t\tcollMod: tableName,\n\t\t\t\tvalidator: {\n\t\t\t\t\t$jsonSchema: {\n\t\t\t\t\t\t...existingSchema,\n\t\t\t\t\t\tbsonType: \"object\",\n\t\t\t\t\t\tproperties,\n\t\t\t\t\t\t...(required.length > 0 ? { required } : {}),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tvalidationAction: \"warn\",\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async deleteColumn({\n\t\ttableName,\n\t\tcolumnName,\n\t\tdb,\n\t}: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\ttry {\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst result = await collection.updateMany({}, { $unset: { [columnName]: \"\" } });\n\t\t\treturn { deletedCount: result.modifiedCount };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async alterColumn(params: AlterColumnParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, columnName, columnType, isNullable, db } = params;\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collections = await mongoDb.listCollections({ name: tableName }).toArray();\n\t\t\tif (collections.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Collection \"${tableName}\" does not exist`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (columnName === \"_id\") {\n\t\t\t\tthrow new HTTPException(400, { message: 'Cannot alter the \"_id\" field' });\n\t\t\t}\n\n\t\t\tconst collInfo = collections[0] as {\n\t\t\t\toptions?: {\n\t\t\t\t\tvalidator?: {\n\t\t\t\t\t\t$jsonSchema?: {\n\t\t\t\t\t\t\tproperties?: Record<string, unknown>;\n\t\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tconst existingSchema = collInfo.options?.validator?.$jsonSchema ?? {};\n\t\t\tconst properties: Record<string, unknown> = {\n\t\t\t\t...((existingSchema.properties as Record<string, unknown>) ?? {}),\n\t\t\t};\n\t\t\tconst required: string[] = [...(existingSchema.required ?? [])];\n\n\t\t\tproperties[columnName] = {\n\t\t\t\tbsonType: isNullable ? [columnType, \"null\"] : columnType,\n\t\t\t};\n\n\t\t\tconst reqIndex = required.indexOf(columnName);\n\t\t\tif (!isNullable && reqIndex === -1) required.push(columnName);\n\t\t\telse if (isNullable && reqIndex !== -1) required.splice(reqIndex, 1);\n\n\t\t\tawait mongoDb.command({\n\t\t\t\tcollMod: tableName,\n\t\t\t\tvalidator: {\n\t\t\t\t\t$jsonSchema: {\n\t\t\t\t\t\t...existingSchema,\n\t\t\t\t\t\tbsonType: \"object\",\n\t\t\t\t\t\tproperties,\n\t\t\t\t\t\t...(required.length > 0 ? { required } : {}),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tvalidationAction: \"warn\",\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async renameColumn(params: RenameColumnParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, columnName, newColumnName, db } = params;\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collections = await mongoDb.listCollections({ name: tableName }).toArray();\n\t\t\tif (collections.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Collection \"${tableName}\" does not exist`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (columnName === \"_id\") {\n\t\t\t\tthrow new HTTPException(400, { message: 'Cannot rename the \"_id\" field' });\n\t\t\t}\n\n\t\t\tconst sample = await mongoDb\n\t\t\t\t.collection(tableName)\n\t\t\t\t.findOne({ [columnName]: { $exists: true } });\n\t\t\tif (!sample) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Field \"${columnName}\" does not exist in collection \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst conflict = await mongoDb\n\t\t\t\t.collection(tableName)\n\t\t\t\t.findOne({ [newColumnName]: { $exists: true } });\n\t\t\tif (conflict) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Field \"${newColumnName}\" already exists in collection \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait mongoDb\n\t\t\t\t.collection(tableName)\n\t\t\t\t.updateMany(\n\t\t\t\t\t{ [columnName]: { $exists: true } },\n\t\t\t\t\t{ $rename: { [columnName]: newColumnName } },\n\t\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Record operations\n\t// -----------------------------------------------------------------------\n\n\toverride async addRecord({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\ttry {\n\t\t\tconst { tableName, data } = params;\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst payload = normalizeDoc(data);\n\t\t\tif (payload._id === \"\" || payload._id === null) delete payload._id;\n\t\t\tconst result = await collection.insertOne(payload);\n\t\t\tif (!result.insertedId) {\n\t\t\t\tthrow new HTTPException(500, {\n\t\t\t\t\tmessage: `Failed to insert record into \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { insertedCount: 1 };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async updateRecords({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\ttry {\n\t\t\tconst { tableName } = params;\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\n\t\t\tlet totalUpdated = 0;\n\t\t\tconst keyColumns = this.resolveKeyColumns(params).map((column) => column || \"_id\");\n\t\t\tconst groups = this.groupUpdatesByKey(\n\t\t\t\t{ ...params, primaryKeys: keyColumns },\n\t\t\t\tkeyColumns,\n\t\t\t);\n\n\t\t\tfor (const { keyValues, rowUpdates } of groups) {\n\t\t\t\t// MongoDB rejects $set on the immutable _id field, so surface it as a\n\t\t\t\t// client error instead of letting the driver fail mid-write.\n\t\t\t\tif (rowUpdates.some((update) => update.columnName === \"_id\")) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: 'The \"_id\" field is immutable and cannot be updated.',\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst updateSet: Record<string, unknown> = {};\n\t\t\t\tfor (const update of rowUpdates) updateSet[update.columnName] = update.value;\n\n\t\t\t\tconst filter: Record<string, unknown> = {};\n\t\t\t\tkeyColumns.forEach((column, i) => {\n\t\t\t\t\tconst value = keyValues[i];\n\t\t\t\t\tfilter[column] = column === \"_id\" && canCoerce(value) ? toMongoId(value) : value;\n\t\t\t\t});\n\n\t\t\t\tconst result = await collection.updateOne(filter, { $set: updateSet });\n\t\t\t\tif (result.matchedCount === 0) {\n\t\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\t\tmessage: `Record with ${this.describeKey(keyColumns, keyValues)} not found in \"${tableName}\"`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\ttotalUpdated += result.modifiedCount;\n\t\t\t}\n\n\t\t\treturn { updatedCount: totalUpdated };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async deleteRecords(params: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\ttry {\n\t\t\tconst { tableName, primaryKeys, db } = params;\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst pkColumn = primaryKeys[0]?.columnName ?? \"_id\";\n\t\t\tconst pkValues = primaryKeys.map((pk) =>\n\t\t\t\tpkColumn === \"_id\" && canCoerce(pk.value) ? toMongoId(pk.value) : pk.value,\n\t\t\t);\n\t\t\tconst result = await collection.deleteMany({ [pkColumn]: { $in: pkValues } });\n\t\t\treturn {\n\t\t\t\tdeletedCount: result.deletedCount ?? 0,\n\t\t\t\tfkViolation: false,\n\t\t\t\trelatedRecords: [],\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async forceDeleteRecords(\n\t\tparams: DeleteRecordParams,\n\t): Promise<{ deletedCount: number }> {\n\t\tconst result = await this.deleteRecords(params);\n\t\treturn { deletedCount: result.deletedCount };\n\t}\n\n\toverride async bulkInsertRecords(\n\t\tparams: BulkInsertRecordsParams,\n\t): Promise<BulkInsertResult> {\n\t\ttry {\n\t\t\tconst { tableName, records, db } = params;\n\t\t\tif (!records || records.length === 0) {\n\t\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\t\t\t}\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst docs = records.map((record) => {\n\t\t\t\tconst normalized = normalizeDoc(record);\n\t\t\t\tif (normalized._id === \"\" || normalized._id === null) delete normalized._id;\n\t\t\t\treturn normalized;\n\t\t\t});\n\t\t\tconst result = await collection.insertMany(docs, { ordered: false });\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `Successfully inserted ${result.insertedCount} record${result.insertedCount !== 1 ? \"s\" : \"\"}`,\n\t\t\t\tsuccessCount: result.insertedCount,\n\t\t\t\tfailureCount: records.length - result.insertedCount,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Query execution\n\t// -----------------------------------------------------------------------\n\n\toverride async executeQuery({\n\t\tquery,\n\t\tdb,\n\t}: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\ttry {\n\t\t\tif (!query?.trim()) {\n\t\t\t\tthrow new HTTPException(400, { message: \"Query is required\" });\n\t\t\t}\n\n\t\t\tlet payload: MongoQueryPayload;\n\t\t\ttry {\n\t\t\t\tpayload = JSON.parse(query) as MongoQueryPayload;\n\t\t\t} catch {\n\t\t\t\tthrow new HTTPException(400, { message: \"Mongo query must be valid JSON\" });\n\t\t\t}\n\n\t\t\tif (!payload.collection || !payload.operation) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: \"Mongo query must include collection and operation\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(payload.collection);\n\n\t\t\tconst startTime = performance.now();\n\t\t\tlet rows: Record<string, unknown>[] = [];\n\t\t\tlet rowCount = 0;\n\t\t\tlet message: string | undefined;\n\n\t\t\tswitch (payload.operation) {\n\t\t\t\tcase \"find\": {\n\t\t\t\t\tconst filter = normalizeIdFilter(payload.filter ?? {});\n\t\t\t\t\tconst cursor = collection.find(filter, payload.options ?? {});\n\t\t\t\t\tcursor.sort(payload.sort ?? buildSortStage(\"\", undefined));\n\t\t\t\t\tif (payload.skip) cursor.skip(payload.skip);\n\t\t\t\t\tif (payload.limit) cursor.limit(payload.limit);\n\t\t\t\t\trows = await cursor.toArray();\n\t\t\t\t\trowCount = rows.length;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"aggregate\": {\n\t\t\t\t\trows = await collection\n\t\t\t\t\t\t.aggregate(payload.pipeline ?? [], payload.options ?? {})\n\t\t\t\t\t\t.toArray();\n\t\t\t\t\trowCount = rows.length;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"insertOne\": {\n\t\t\t\t\tconst doc = payload.document as Record<string, unknown> | undefined;\n\t\t\t\t\tif (!doc) throw new HTTPException(400, { message: \"document is required\" });\n\t\t\t\t\tconst result = await collection.insertOne(doc);\n\t\t\t\t\trowCount = result.insertedId ? 1 : 0;\n\t\t\t\t\tmessage = \"OK\";\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"insertMany\": {\n\t\t\t\t\tconst docs = payload.document as Record<string, unknown>[] | undefined;\n\t\t\t\t\tif (!Array.isArray(docs))\n\t\t\t\t\t\tthrow new HTTPException(400, { message: \"document array is required\" });\n\t\t\t\t\tconst result = await collection.insertMany(docs);\n\t\t\t\t\trowCount = result.insertedCount ?? 0;\n\t\t\t\t\tmessage = \"OK\";\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"updateOne\": {\n\t\t\t\t\tconst filter = normalizeIdFilter(payload.filter ?? {});\n\t\t\t\t\tif (!payload.update) throw new HTTPException(400, { message: \"update is required\" });\n\t\t\t\t\tconst result = await collection.updateOne(\n\t\t\t\t\t\tfilter,\n\t\t\t\t\t\tpayload.update,\n\t\t\t\t\t\tpayload.options ?? {},\n\t\t\t\t\t);\n\t\t\t\t\trowCount = result.matchedCount ?? 0;\n\t\t\t\t\tmessage = `OK (${result.modifiedCount ?? 0} modified)`;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"updateMany\": {\n\t\t\t\t\tconst filter = normalizeIdFilter(payload.filter ?? {});\n\t\t\t\t\tif (!payload.update) throw new HTTPException(400, { message: \"update is required\" });\n\t\t\t\t\tconst result = await collection.updateMany(\n\t\t\t\t\t\tfilter,\n\t\t\t\t\t\tpayload.update,\n\t\t\t\t\t\tpayload.options ?? {},\n\t\t\t\t\t);\n\t\t\t\t\trowCount = result.matchedCount ?? 0;\n\t\t\t\t\tmessage = `OK (${result.modifiedCount ?? 0} modified)`;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"deleteOne\": {\n\t\t\t\t\tconst filter = normalizeIdFilter(payload.filter ?? {});\n\t\t\t\t\tconst result = await collection.deleteOne(filter, payload.options ?? {});\n\t\t\t\t\trowCount = result.deletedCount ?? 0;\n\t\t\t\t\tmessage = \"OK\";\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"deleteMany\": {\n\t\t\t\t\tconst filter = normalizeIdFilter(payload.filter ?? {});\n\t\t\t\t\tconst result = await collection.deleteMany(filter, payload.options ?? {});\n\t\t\t\t\trowCount = result.deletedCount ?? 0;\n\t\t\t\t\tmessage = \"OK\";\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"count\": {\n\t\t\t\t\tconst filter = normalizeIdFilter(payload.filter ?? {});\n\t\t\t\t\trowCount = await collection.countDocuments(filter);\n\t\t\t\t\trows = [{ count: rowCount }];\n\t\t\t\t\tmessage = \"OK\";\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new HTTPException(400, { message: \"Unsupported Mongo operation\" });\n\t\t\t}\n\n\t\t\tconst duration = performance.now() - startTime;\n\t\t\tconst normalizedRows = rows.map((row) => normalizeDoc(row));\n\t\t\tconst columns = normalizedRows[0] ? Object.keys(normalizedRows[0]) : [];\n\n\t\t\treturn { columns, rows: normalizedRows, rowCount, duration, message };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n}\n","import { z } from \"zod\";\n\nexport const databaseSchema = z.object({\n\tdb: z.string(\"Database name is required\"),\n});\n\nexport type DatabaseSchemaType = z.infer<typeof databaseSchema>;\n\nexport const DATABASE_TYPES = [\"pg\", \"mysql\", \"mssql\", \"mongodb\", \"sqlite\", \"redis\"] as const;\n\nexport const databaseTypeSchema = z.enum(DATABASE_TYPES, {\n\tmessage: \"Invalid database type\",\n});\nexport type DatabaseTypeSchema = z.infer<typeof databaseTypeSchema>;\n\nexport const currentDatabaseSchema = databaseSchema.extend({\n\tdbType: databaseTypeSchema,\n});\nexport type CurrentDatabaseSchemaType = z.infer<typeof currentDatabaseSchema>;\n\nexport const databaseTypeParamSchema = z.object({\n\tdbType: databaseTypeSchema,\n});\n\nexport const tableNameSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n});\n\nexport type TableNameSchemaType = z.infer<typeof tableNameSchema>;\n","import { z } from \"zod\";\nimport { databaseSchema, tableNameSchema } from \"./database.types\";\n\nexport const addColumnSchema = z.object({\n\tcolumnName: z.string(\"Column name is required\"),\n\tcolumnType: z.string(\"Column type is required\"),\n\tdefaultValue: z.string().optional(),\n\tisPrimaryKey: z.boolean().default(false),\n\tisNullable: z.boolean().default(false),\n\tisUnique: z.boolean().default(false),\n\tisIdentity: z.boolean().default(false),\n\tisArray: z.boolean().default(false),\n});\n\nexport type AddColumnSchemaType = z.infer<typeof addColumnSchema>;\n\nexport const addColumnParamSchema = tableNameSchema;\n\nexport type AddColumnParamSchemaType = z.infer<typeof addColumnParamSchema>;\n\nexport const addColumnParamsSchema = z.object({\n\tdb: databaseSchema.shape.db,\n\ttableName: tableNameSchema.shape.tableName,\n\tcolumnName: addColumnSchema.shape.columnName,\n\tcolumnType: addColumnSchema.shape.columnType,\n\tdefaultValue: addColumnSchema.shape.defaultValue,\n\tisPrimaryKey: addColumnSchema.shape.isPrimaryKey,\n\tisNullable: addColumnSchema.shape.isNullable,\n\tisUnique: addColumnSchema.shape.isUnique,\n\tisIdentity: addColumnSchema.shape.isIdentity,\n\tisArray: addColumnSchema.shape.isArray,\n});\n\nexport type AddColumnParamsSchemaType = z.infer<typeof addColumnParamsSchema>;\n","import { z } from \"zod\";\n\nexport const addRecordSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n\tdata: z.record(z.string(\"Column name is required\"), z.any()),\n});\n\nexport type AddRecordSchemaType = z.infer<typeof addRecordSchema>;\n","import { z } from \"zod\";\n\nexport const AI_PROVIDERS = [\"gemini\", \"openai\", \"anthropic\", \"grok\", \"openrouter\"] as const;\nexport const aiProviderSchema = z.enum(AI_PROVIDERS);\nexport type AiProvider = z.infer<typeof aiProviderSchema>;\n\nexport const AI_PROVIDER_OPTIONS: ReadonlyArray<{\n\tid: AiProvider;\n\tlabel: string;\n\tmodels: ReadonlyArray<{ id: string; label: string }>;\n}> = [\n\t{\n\t\tid: \"gemini\",\n\t\tlabel: \"Google Gemini\",\n\t\tmodels: [\n\t\t\t{ id: \"gemini-3-flash-preview\", label: \"Gemini 3 Flash\" },\n\t\t\t{ id: \"gemini-2.5-pro\", label: \"Gemini 2.5 Pro\" },\n\t\t],\n\t},\n\t{\n\t\tid: \"openai\",\n\t\tlabel: \"OpenAI\",\n\t\tmodels: [\n\t\t\t{ id: \"gpt-5.2\", label: \"GPT-5.2\" },\n\t\t\t{ id: \"gpt-5-mini\", label: \"GPT-5 mini\" },\n\t\t],\n\t},\n\t{\n\t\tid: \"anthropic\",\n\t\tlabel: \"Anthropic\",\n\t\tmodels: [\n\t\t\t{ id: \"claude-sonnet-4-6\", label: \"Claude Sonnet 4.6\" },\n\t\t\t{ id: \"claude-haiku-4-5\", label: \"Claude Haiku 4.5\" },\n\t\t],\n\t},\n\t{\n\t\tid: \"grok\",\n\t\tlabel: \"xAI Grok\",\n\t\tmodels: [\n\t\t\t{ id: \"grok-4.6\", label: \"Grok 4.6\" },\n\t\t\t{ id: \"grok-4.5\", label: \"Grok 4.5\" },\n\t\t],\n\t},\n\t{\n\t\tid: \"openrouter\",\n\t\tlabel: \"OpenRouter\",\n\t\tmodels: [\n\t\t\t{ id: \"openai/gpt-5.2\", label: \"GPT-5.2 via OpenRouter\" },\n\t\t\t{ id: \"anthropic/claude-sonnet-4.6\", label: \"Claude Sonnet 4.6 via OpenRouter\" },\n\t\t],\n\t},\n];\n\nexport const getDefaultAiModel = (provider: AiProvider): string =>\n\tAI_PROVIDER_OPTIONS.find((option) => option.id === provider)?.models[0]?.id ??\n\t\"gemini-3-flash-preview\";\n","import { z } from \"zod\";\nimport { databaseSchema } from \"./database.types\";\n\nexport const deleteColumnQuerySchema = databaseSchema.extend({\n\tcascade: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform((val) => val === \"true\"),\n});\n\nexport type DeleteColumnQuerySchemaType = z.infer<typeof deleteColumnQuerySchema>;\n\nexport const deleteColumnParamSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n\tcolumnName: z.string(\"Column name is required\"),\n});\n\nexport const deleteColumnParamsSchema = z.object({\n\tdb: databaseSchema.shape.db,\n\ttableName: deleteColumnParamSchema.shape.tableName,\n\tcolumnName: deleteColumnParamSchema.shape.columnName,\n\tcascade: z.boolean().optional(),\n});\n\nexport type DeleteColumnParamsSchemaType = z.infer<typeof deleteColumnParamsSchema>;\n\nexport const deleteColumnSuccessResponseSchema = z.object({\n\tmessage: z.string(\"Message is required\"),\n\ttableName: z.string(\"Table name is required\"),\n\tcolumnName: z.string(\"Column name is required\"),\n\tdeletedCount: z.number(\"Deleted count is required\").default(0),\n});\n\nexport type DeleteColumnResponseType = z.infer<typeof deleteColumnSuccessResponseSchema>;\n","import { z } from \"zod\";\nimport { databaseSchema } from \"./database.types\";\nimport { deleteColumnParamSchema } from \"./delete-column.types\";\n\nexport const alterColumnSchema = z.object({\n\tcolumnType: z.string(\"Column type is required\"),\n\tisNullable: z.boolean(),\n\tdefaultValue: z.string().nullable().optional(),\n});\n\nexport type AlterColumnSchemaType = z.infer<typeof alterColumnSchema>;\n\nexport const alterColumnParamSchema = deleteColumnParamSchema;\n\nexport type AlterColumnParamSchemaType = z.infer<typeof alterColumnParamSchema>;\n\nexport const alterColumnParamsSchema = z.object({\n\tdb: databaseSchema.shape.db,\n\ttableName: deleteColumnParamSchema.shape.tableName,\n\tcolumnName: deleteColumnParamSchema.shape.columnName,\n\tcolumnType: alterColumnSchema.shape.columnType,\n\tisNullable: alterColumnSchema.shape.isNullable,\n\tdefaultValue: alterColumnSchema.shape.defaultValue,\n});\n\nexport type AlterColumnParamsSchemaType = z.infer<typeof alterColumnParamsSchema>;\n","/**\n * Standard API success response wrapper type\n * Used by both server and client\n */\nexport type BaseResponse<T> = {\n\tdata: T;\n\tmessage?: string;\n};\n\n/**\n * Standard API error response type\n */\nexport type ApiError = {\n\terror: string;\n\tdetails?: string;\n};\n","import { z } from \"zod\";\nimport type { DatabaseSchemaType } from \"./database.types\";\n\nexport type BulkInsertRecordsParams = {\n\ttableName: string;\n\trecords: Record<string, unknown>[];\n\tdb: DatabaseSchemaType[\"db\"];\n};\n\nexport type BulkInsertResult = {\n\tsuccess: boolean;\n\tmessage: string;\n\tsuccessCount: number;\n\tfailureCount: number;\n\terrors?: Array<{ recordIndex: number; error: string }>;\n};\n\nexport const bulkInsertRecordsSchema = z.object({\n\ttableName: z.string().min(1, \"Table name is required\"),\n\trecords: z.array(z.record(z.string(), z.any())).min(1, \"At least one record is required\"),\n});\n","import { z } from \"zod\";\nimport { aiProviderSchema, getDefaultAiModel } from \"./ai-provider.types.js\";\nimport { databaseSchema } from \"./database.types.js\";\n\n// Legacy UI message part schema. Current TanStack AI clients serialize messages\n// to the AG-UI wire format (`content` / `toolCalls`) before sending them.\nconst messagePart = z\n\t.object({\n\t\ttype: z.string(),\n\t\tcontent: z.string().optional(),\n\t})\n\t.passthrough();\n\n// `fetchServerSentEvents` wraps extra body under `data`. Accept both the current\n// AG-UI wire messages and legacy UI messages so older clients remain compatible.\nconst chatBodySchema = z.object({\n\tprovider: aiProviderSchema.optional().default(\"gemini\"),\n\t// Left optional here: a fixed default would pair, say, `provider: \"openai\"`\n\t// with a Gemini model and the proxy would reject the combination with a 400.\n\t// The default is resolved from the parsed provider in the transform below.\n\tmodel: z.string().min(1).optional(),\n\tmessages: z.array(\n\t\tz\n\t\t\t.object({\n\t\t\t\tid: z.string(),\n\t\t\t\trole: z.enum([\"user\", \"assistant\", \"system\", \"tool\", \"reasoning\"]),\n\t\t\t\tcontent: z.union([z.string(), z.null(), z.array(z.unknown())]).optional(),\n\t\t\t\tparts: z.array(messagePart).optional(),\n\t\t\t})\n\t\t\t.passthrough(),\n\t),\n\tdata: z.object({\n\t\tconversationId: z.string().optional(),\n\t\tdb: databaseSchema.shape.db,\n\t\tincludeSchema: z.boolean().optional().default(true),\n\t}),\n});\n\nexport const chatSchema = chatBodySchema.transform((body) => ({\n\t...body,\n\tmodel: body.model ?? getDefaultAiModel(body.provider),\n}));\n","export type Args = {\n\tenv?: string;\n\tport?: string;\n\tdatabaseUrl?: string;\n\tvarName?: string;\n\topen?: boolean;\n\tstatus?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n};\n","import { z } from \"zod\";\n\nconst dataTypes = [\"text\", \"boolean\", \"number\", \"enum\", \"json\", \"date\", \"array\"] as const;\n\nexport const dataTypesSchema = z.enum(dataTypes);\nexport type DataTypes = z.infer<typeof dataTypesSchema>;\n\nexport const DataTypes = {\n\ttext: \"text\",\n\tboolean: \"boolean\",\n\tnumber: \"number\",\n\tenum: \"enum\",\n\tjson: \"json\",\n\tdate: \"date\",\n\tarray: \"array\",\n} as const satisfies Record<DataTypes, string>;\n\nconst standardizedDataTypes = [\n\t// PostgreSQL numeric types\n\t\"int\",\n\t\"bigint\",\n\t\"smallint\",\n\t\"numeric\",\n\t\"float\",\n\t\"double\",\n\t\"money\",\n\t// MySQL numeric types\n\t\"tinyint\",\n\t\"mediumint\",\n\t\"bit\",\n\t// Boolean\n\t\"boolean\",\n\t// Text types (shared)\n\t\"text\",\n\t\"varchar\",\n\t\"char\",\n\t// MySQL text types\n\t\"tinytext\",\n\t\"mediumtext\",\n\t\"longtext\",\n\t// JSON types\n\t\"json\",\n\t\"jsonb\",\n\t\"xml\",\n\t// UUID\n\t\"uuid\",\n\t// Date/Time types (shared)\n\t\"date\",\n\t\"time\",\n\t\"timestamp\",\n\t// PostgreSQL date/time\n\t\"timestamptz\",\n\t\"interval\",\n\t// MySQL date/time\n\t\"datetime\",\n\t\"year\",\n\t// PostgreSQL binary/network/geometric types\n\t\"bytea\",\n\t\"inet\",\n\t\"cidr\",\n\t\"macaddr\",\n\t\"macaddr8\",\n\t\"point\",\n\t\"line\",\n\t\"polygon\",\n\t// MySQL binary types\n\t\"binary\",\n\t\"varbinary\",\n\t\"blob\",\n\t\"tinyblob\",\n\t\"mediumblob\",\n\t\"longblob\",\n\t// Complex types (shared)\n\t\"array\",\n\t\"enum\",\n\t// MySQL set type\n\t\"set\",\n] as const;\n\nexport const standardizedDataTypeSchema = z.enum(standardizedDataTypes);\n\nexport const columnInfoSchema = z.object({\n\tcolumnName: z.string(),\n\tdataType: dataTypesSchema,\n\tdataTypeLabel: standardizedDataTypeSchema,\n\tisNullable: z.boolean(),\n\tcolumnDefault: z.string().nullable(),\n\tisPrimaryKey: z.boolean(),\n\tisForeignKey: z.boolean(),\n\treferencedTable: z.string().nullable(),\n\treferencedColumn: z.string().nullable(),\n\tenumValues: z.array(z.string()).nullable(),\n});\n\nexport type ColumnInfoSchemaType = z.infer<typeof columnInfoSchema>;\n","import { DataTypes } from \"./column-info.types.js\";\n\n/**\n * Maps PostgreSQL data types to generic DataType enum\n */\nexport function mapPostgresToDataType(pgType: string): DataTypes {\n\tconst normalized = pgType?.toLowerCase().trim() || \"\";\n\n\t// Handle array types and date/time types\n\tif (\n\t\tnormalized.includes(\"[]\") ||\n\t\tnormalized === \"date\" ||\n\t\tnormalized === \"time\" ||\n\t\tnormalized === \"time without time zone\" ||\n\t\tnormalized.startsWith(\"time(\") ||\n\t\tnormalized === \"timestamp\" ||\n\t\tnormalized === \"timestamp without time zone\" ||\n\t\tnormalized.startsWith(\"timestamp(\") ||\n\t\tnormalized === \"timestamp with time zone\" ||\n\t\tnormalized === \"timestamptz\" ||\n\t\tnormalized.startsWith(\"timestamp with time zone(\")\n\t) {\n\t\treturn DataTypes.date;\n\t}\n\n\t// Numeric types\n\tif (\n\t\tnormalized === \"integer\" ||\n\t\tnormalized === \"int\" ||\n\t\tnormalized === \"int4\" ||\n\t\tnormalized === \"bigint\" ||\n\t\tnormalized === \"int8\" ||\n\t\tnormalized === \"smallint\" ||\n\t\tnormalized === \"int2\" ||\n\t\tnormalized === \"decimal\" ||\n\t\tnormalized.startsWith(\"decimal(\") ||\n\t\tnormalized === \"numeric\" ||\n\t\tnormalized.startsWith(\"numeric(\") ||\n\t\tnormalized === \"real\" ||\n\t\tnormalized === \"float4\" ||\n\t\tnormalized === \"double precision\" ||\n\t\tnormalized === \"float8\" ||\n\t\tnormalized === \"float\" ||\n\t\tnormalized === \"serial\" ||\n\t\tnormalized === \"serial4\" ||\n\t\tnormalized === \"bigserial\" ||\n\t\tnormalized === \"serial8\" ||\n\t\tnormalized === \"money\"\n\t) {\n\t\treturn DataTypes.number;\n\t}\n\n\t// Boolean\n\tif (normalized === \"boolean\" || normalized === \"bool\") {\n\t\treturn DataTypes.boolean;\n\t}\n\n\t// JSON types\n\tif (normalized === \"json\" || normalized === \"jsonb\") {\n\t\treturn DataTypes.json;\n\t}\n\n\t// Enum types and long text types\n\tif (\n\t\tnormalized.startsWith(\"user-defined\") ||\n\t\tnormalized === \"enum\" ||\n\t\tnormalized === \"text\" ||\n\t\tnormalized === \"xml\"\n\t) {\n\t\treturn DataTypes.text;\n\t}\n\n\t// Short string types (varchar, char, uuid, etc.)\n\tif (\n\t\tnormalized === \"character varying\" ||\n\t\tnormalized.startsWith(\"varchar\") ||\n\t\tnormalized.startsWith(\"character varying(\") ||\n\t\tnormalized === \"character\" ||\n\t\tnormalized.startsWith(\"char\") ||\n\t\tnormalized.startsWith(\"character(\") ||\n\t\tnormalized === \"bpchar\" ||\n\t\tnormalized === \"uuid\" ||\n\t\tnormalized === \"interval\" ||\n\t\tnormalized.startsWith(\"interval\") ||\n\t\tnormalized === \"bytea\" ||\n\t\tnormalized === \"point\" ||\n\t\tnormalized === \"line\" ||\n\t\tnormalized === \"polygon\" ||\n\t\tnormalized === \"inet\" ||\n\t\tnormalized === \"cidr\" ||\n\t\tnormalized === \"macaddr\" ||\n\t\tnormalized === \"macaddr8\"\n\t) {\n\t\treturn DataTypes.text;\n\t}\n\n\t// Default to short for unrecognized types\n\treturn DataTypes.text;\n}\n\n/**\n * Standardized data type labels\n */\nexport const StandardizedDataType = {\n\t// PostgreSQL numeric types\n\tint: \"int\",\n\tbigint: \"bigint\",\n\tsmallint: \"smallint\",\n\tnumeric: \"numeric\",\n\tfloat: \"float\",\n\tdouble: \"double\",\n\tmoney: \"money\",\n\t// MySQL numeric types\n\ttinyint: \"tinyint\",\n\tmediumint: \"mediumint\",\n\tbit: \"bit\",\n\t// Boolean\n\tboolean: \"boolean\",\n\t// Text types (shared)\n\ttext: \"text\",\n\tvarchar: \"varchar\",\n\tchar: \"char\",\n\t// MySQL text types\n\ttinytext: \"tinytext\",\n\tmediumtext: \"mediumtext\",\n\tlongtext: \"longtext\",\n\t// JSON types\n\tjson: \"json\",\n\tjsonb: \"jsonb\",\n\txml: \"xml\",\n\t// UUID\n\tuuid: \"uuid\",\n\t// Date/Time types (shared)\n\tdate: \"date\",\n\ttime: \"time\",\n\ttimestamp: \"timestamp\",\n\t// PostgreSQL date/time\n\ttimestamptz: \"timestamptz\",\n\tinterval: \"interval\",\n\t// MySQL date/time\n\tdatetime: \"datetime\",\n\tyear: \"year\",\n\t// PostgreSQL binary/network/geometric types\n\tbytea: \"bytea\",\n\tinet: \"inet\",\n\tcidr: \"cidr\",\n\tmacaddr: \"macaddr\",\n\tmacaddr8: \"macaddr8\",\n\tpoint: \"point\",\n\tline: \"line\",\n\tpolygon: \"polygon\",\n\t// MySQL binary types\n\tbinary: \"binary\",\n\tvarbinary: \"varbinary\",\n\tblob: \"blob\",\n\ttinyblob: \"tinyblob\",\n\tmediumblob: \"mediumblob\",\n\tlongblob: \"longblob\",\n\t// Complex types (shared)\n\tarray: \"array\",\n\tenum: \"enum\",\n\t// MySQL set type\n\tset: \"set\",\n} as const;\n\nexport type StandardizedDataType =\n\t(typeof StandardizedDataType)[keyof typeof StandardizedDataType];\n\n/**\n * Maps PostgreSQL data types to standardized display labels\n */\nexport function standardizeDataTypeLabel(\n\tpgType: string | null | undefined,\n): StandardizedDataType {\n\tif (!pgType) {\n\t\treturn StandardizedDataType.text; // Default fallback\n\t}\n\tconst normalized = pgType.toLowerCase().trim();\n\n\t// Numeric types\n\tif (\n\t\tnormalized === \"integer\" ||\n\t\tnormalized === \"int\" ||\n\t\tnormalized === \"int4\" ||\n\t\tnormalized === \"serial\" ||\n\t\tnormalized === \"serial4\"\n\t) {\n\t\treturn StandardizedDataType.int;\n\t}\n\n\tif (\n\t\tnormalized === \"bigint\" ||\n\t\tnormalized === \"int8\" ||\n\t\tnormalized === \"bigserial\" ||\n\t\tnormalized === \"serial8\"\n\t) {\n\t\treturn StandardizedDataType.bigint;\n\t}\n\n\tif (normalized === \"smallint\" || normalized === \"int2\") {\n\t\treturn StandardizedDataType.smallint;\n\t}\n\n\tif (\n\t\tnormalized === \"decimal\" ||\n\t\tnormalized.startsWith(\"decimal(\") ||\n\t\tnormalized === \"numeric\" ||\n\t\tnormalized.startsWith(\"numeric(\")\n\t) {\n\t\treturn StandardizedDataType.numeric;\n\t}\n\n\tif (normalized === \"real\" || normalized === \"float4\") {\n\t\treturn StandardizedDataType.float;\n\t}\n\n\tif (normalized === \"double precision\" || normalized === \"float8\" || normalized === \"float\") {\n\t\treturn StandardizedDataType.double;\n\t}\n\n\tif (normalized === \"money\") {\n\t\treturn StandardizedDataType.money;\n\t}\n\n\t// Boolean\n\tif (normalized === \"boolean\" || normalized === \"bool\") {\n\t\treturn StandardizedDataType.boolean;\n\t}\n\n\t// Text types\n\tif (normalized === \"text\") {\n\t\treturn StandardizedDataType.text;\n\t}\n\n\tif (\n\t\tnormalized === \"character varying\" ||\n\t\tnormalized.startsWith(\"varchar\") ||\n\t\tnormalized.startsWith(\"character varying(\")\n\t) {\n\t\treturn StandardizedDataType.varchar;\n\t}\n\n\tif (\n\t\tnormalized === \"character\" ||\n\t\tnormalized.startsWith(\"char\") ||\n\t\tnormalized.startsWith(\"character(\") ||\n\t\tnormalized === \"bpchar\"\n\t) {\n\t\treturn StandardizedDataType.char;\n\t}\n\n\t// JSON types\n\tif (normalized === \"json\") {\n\t\treturn StandardizedDataType.json;\n\t}\n\n\tif (normalized === \"jsonb\") {\n\t\treturn StandardizedDataType.jsonb;\n\t}\n\n\tif (normalized === \"xml\") {\n\t\treturn StandardizedDataType.xml;\n\t}\n\n\t// UUID\n\tif (normalized === \"uuid\") {\n\t\treturn StandardizedDataType.uuid;\n\t}\n\n\t// Date/Time types\n\tif (normalized === \"date\") {\n\t\treturn StandardizedDataType.date;\n\t}\n\n\tif (\n\t\tnormalized === \"time\" ||\n\t\tnormalized === \"time without time zone\" ||\n\t\tnormalized.startsWith(\"time(\")\n\t) {\n\t\treturn StandardizedDataType.time;\n\t}\n\n\tif (\n\t\tnormalized === \"timestamp\" ||\n\t\tnormalized === \"timestamp without time zone\" ||\n\t\tnormalized.startsWith(\"timestamp(\")\n\t) {\n\t\treturn StandardizedDataType.timestamp;\n\t}\n\n\tif (\n\t\tnormalized === \"timestamp with time zone\" ||\n\t\tnormalized === \"timestamptz\" ||\n\t\tnormalized.startsWith(\"timestamp with time zone(\")\n\t) {\n\t\treturn StandardizedDataType.timestamptz;\n\t}\n\n\tif (normalized === \"interval\" || normalized.startsWith(\"interval\")) {\n\t\treturn StandardizedDataType.interval;\n\t}\n\n\t// Binary\n\tif (normalized === \"bytea\") {\n\t\treturn StandardizedDataType.bytea;\n\t}\n\n\t// Network types\n\tif (normalized === \"inet\") {\n\t\treturn StandardizedDataType.inet;\n\t}\n\n\tif (normalized === \"cidr\") {\n\t\treturn StandardizedDataType.cidr;\n\t}\n\n\tif (normalized === \"macaddr\") {\n\t\treturn StandardizedDataType.macaddr;\n\t}\n\n\tif (normalized === \"macaddr8\") {\n\t\treturn StandardizedDataType.macaddr8;\n\t}\n\n\t// Geometric types\n\tif (normalized === \"point\") {\n\t\treturn StandardizedDataType.point;\n\t}\n\n\tif (normalized === \"line\") {\n\t\treturn StandardizedDataType.line;\n\t}\n\n\tif (normalized === \"polygon\") {\n\t\treturn StandardizedDataType.polygon;\n\t}\n\n\t// Array types\n\t// todo: handle array types\n\tif (normalized.startsWith(\"array\") || normalized.includes(\"[]\")) {\n\t\treturn StandardizedDataType.text;\n\t}\n\n\t// User-defined types (enums)\n\tif (normalized.startsWith(\"user-defined\") || normalized === \"enum\") {\n\t\treturn StandardizedDataType.enum;\n\t}\n\n\t// Default: return the original type\n\treturn StandardizedDataType.text;\n}\n\n/**\n * Maps MySQL data types to generic DataType enum (used for cell rendering)\n * @param mysqlDataType - The DATA_TYPE field from information_schema.COLUMNS\n * @param columnType - The COLUMN_TYPE field (e.g., \"tinyint(1)\", \"enum('a','b')\") for finer mapping\n */\nexport function mapMysqlToDataType(mysqlDataType: string, columnType?: string): DataTypes {\n\tconst normalized = mysqlDataType?.toLowerCase().trim() || \"\";\n\tconst fullType = columnType?.toLowerCase().trim() || \"\";\n\n\t// tinyint(1) is MySQL's boolean convention\n\tif (normalized === \"tinyint\" && fullType === \"tinyint(1)\") {\n\t\treturn DataTypes.boolean;\n\t}\n\n\t// Numeric types\n\tif (\n\t\tnormalized === \"tinyint\" ||\n\t\tnormalized === \"smallint\" ||\n\t\tnormalized === \"mediumint\" ||\n\t\tnormalized === \"int\" ||\n\t\tnormalized === \"integer\" ||\n\t\tnormalized === \"bigint\" ||\n\t\tnormalized === \"decimal\" ||\n\t\tnormalized === \"numeric\" ||\n\t\tnormalized === \"float\" ||\n\t\tnormalized === \"double\" ||\n\t\tnormalized === \"real\" ||\n\t\tnormalized === \"bit\"\n\t) {\n\t\treturn DataTypes.number;\n\t}\n\n\t// Boolean (explicit)\n\tif (normalized === \"boolean\" || normalized === \"bool\") {\n\t\treturn DataTypes.boolean;\n\t}\n\n\t// Date/time types\n\tif (\n\t\tnormalized === \"date\" ||\n\t\tnormalized === \"datetime\" ||\n\t\tnormalized === \"timestamp\" ||\n\t\tnormalized === \"time\" ||\n\t\tnormalized === \"year\"\n\t) {\n\t\treturn DataTypes.date;\n\t}\n\n\t// JSON\n\tif (normalized === \"json\") {\n\t\treturn DataTypes.json;\n\t}\n\n\t// Enum and set (set behaves like enum for display)\n\tif (normalized === \"enum\" || normalized === \"set\") {\n\t\treturn DataTypes.enum;\n\t}\n\n\t// All text and binary types default to text\n\treturn DataTypes.text;\n}\n\n/**\n * Maps MySQL data types to standardized display labels\n * @param mysqlDataType - The DATA_TYPE field from information_schema.COLUMNS\n * @param columnType - The COLUMN_TYPE field (e.g., \"tinyint(1)\") for finer mapping\n */\nexport function standardizeMysqlDataTypeLabel(\n\tmysqlDataType: string,\n\tcolumnType?: string,\n): StandardizedDataType {\n\tif (!mysqlDataType) {\n\t\treturn StandardizedDataType.text;\n\t}\n\tconst normalized = mysqlDataType.toLowerCase().trim();\n\tconst fullType = columnType?.toLowerCase().trim() || \"\";\n\n\t// tinyint(1) is MySQL's boolean convention\n\tif (normalized === \"tinyint\" && fullType === \"tinyint(1)\")\n\t\treturn StandardizedDataType.boolean;\n\n\t// Numeric types\n\tif (normalized === \"tinyint\") return StandardizedDataType.tinyint;\n\tif (normalized === \"smallint\") return StandardizedDataType.smallint;\n\tif (normalized === \"mediumint\") return StandardizedDataType.mediumint;\n\tif (normalized === \"int\" || normalized === \"integer\") return StandardizedDataType.int;\n\tif (normalized === \"bigint\") return StandardizedDataType.bigint;\n\tif (normalized === \"decimal\" || normalized === \"numeric\")\n\t\treturn StandardizedDataType.numeric;\n\tif (normalized === \"float\" || normalized === \"real\") return StandardizedDataType.float;\n\tif (normalized === \"double\") return StandardizedDataType.double;\n\tif (normalized === \"bit\") return StandardizedDataType.bit;\n\n\t// Boolean\n\tif (normalized === \"boolean\" || normalized === \"bool\") return StandardizedDataType.boolean;\n\n\t// Text types\n\tif (normalized === \"char\") return StandardizedDataType.char;\n\tif (normalized === \"varchar\") return StandardizedDataType.varchar;\n\tif (normalized === \"tinytext\") return StandardizedDataType.tinytext;\n\tif (normalized === \"text\") return StandardizedDataType.text;\n\tif (normalized === \"mediumtext\") return StandardizedDataType.mediumtext;\n\tif (normalized === \"longtext\") return StandardizedDataType.longtext;\n\n\t// Binary types\n\tif (normalized === \"binary\") return StandardizedDataType.binary;\n\tif (normalized === \"varbinary\") return StandardizedDataType.varbinary;\n\tif (normalized === \"tinyblob\") return StandardizedDataType.tinyblob;\n\tif (normalized === \"blob\") return StandardizedDataType.blob;\n\tif (normalized === \"mediumblob\") return StandardizedDataType.mediumblob;\n\tif (normalized === \"longblob\") return StandardizedDataType.longblob;\n\n\t// JSON\n\tif (normalized === \"json\") return StandardizedDataType.json;\n\n\t// Date/time types\n\tif (normalized === \"date\") return StandardizedDataType.date;\n\tif (normalized === \"time\") return StandardizedDataType.time;\n\tif (normalized === \"datetime\") return StandardizedDataType.datetime;\n\tif (normalized === \"timestamp\") return StandardizedDataType.timestamp;\n\tif (normalized === \"year\") return StandardizedDataType.year;\n\n\t// Complex types\n\tif (normalized === \"enum\") return StandardizedDataType.enum;\n\tif (normalized === \"set\") return StandardizedDataType.set;\n\n\t// Default\n\treturn StandardizedDataType.text;\n}\n\n/**\n * Maps SQL Server data types to generic DataType enum (used for cell rendering)\n * @param mssqlDataType - The data type from sys.columns or information_schema.columns\n */\nexport function mapMssqlToDataType(mssqlDataType: string): DataTypes {\n\tconst normalized = mssqlDataType?.toLowerCase().trim() || \"\";\n\n\t// Numeric types\n\tif (\n\t\tnormalized === \"tinyint\" ||\n\t\tnormalized === \"smallint\" ||\n\t\tnormalized === \"int\" ||\n\t\tnormalized === \"bigint\" ||\n\t\tnormalized === \"decimal\" ||\n\t\tnormalized === \"numeric\" ||\n\t\tnormalized === \"float\" ||\n\t\tnormalized === \"real\" ||\n\t\tnormalized === \"money\" ||\n\t\tnormalized === \"smallmoney\"\n\t) {\n\t\treturn DataTypes.number;\n\t}\n\n\t// Boolean (bit with length 1)\n\tif (normalized === \"bit\") {\n\t\treturn DataTypes.boolean;\n\t}\n\n\t// Date/time types\n\tif (\n\t\tnormalized === \"date\" ||\n\t\tnormalized === \"datetime\" ||\n\t\tnormalized === \"datetime2\" ||\n\t\tnormalized === \"smalldatetime\" ||\n\t\tnormalized === \"time\" ||\n\t\tnormalized === \"datetimeoffset\"\n\t) {\n\t\treturn DataTypes.date;\n\t}\n\n\t// JSON (SQL Server 2016+)\n\tif (normalized === \"json\") {\n\t\treturn DataTypes.json;\n\t}\n\n\t// All text and binary types default to text\n\treturn DataTypes.text;\n}\n\n/**\n * Maps SQL Server data types to standardized display labels\n * @param mssqlDataType - The data type from sys.columns or information_schema.columns\n */\nexport function standardizeMssqlDataTypeLabel(mssqlDataType: string): StandardizedDataType {\n\tif (!mssqlDataType) {\n\t\treturn StandardizedDataType.text;\n\t}\n\tconst normalized = mssqlDataType.toLowerCase().trim();\n\n\t// Numeric types\n\tif (normalized === \"tinyint\") return StandardizedDataType.tinyint;\n\tif (normalized === \"smallint\") return StandardizedDataType.smallint;\n\tif (normalized === \"int\") return StandardizedDataType.int;\n\tif (normalized === \"bigint\") return StandardizedDataType.bigint;\n\tif (normalized === \"decimal\" || normalized === \"numeric\")\n\t\treturn StandardizedDataType.numeric;\n\tif (normalized === \"float\") return StandardizedDataType.float;\n\tif (normalized === \"real\") return StandardizedDataType.float;\n\tif (normalized === \"money\" || normalized === \"smallmoney\") return StandardizedDataType.money;\n\n\t// Boolean\n\tif (normalized === \"bit\") return StandardizedDataType.boolean;\n\n\t// Text types\n\tif (normalized === \"char\") return StandardizedDataType.char;\n\tif (normalized === \"varchar\") return StandardizedDataType.varchar;\n\tif (normalized === \"text\") return StandardizedDataType.text;\n\tif (normalized === \"nchar\") return StandardizedDataType.char;\n\tif (normalized === \"nvarchar\") return StandardizedDataType.varchar;\n\tif (normalized === \"ntext\") return StandardizedDataType.text;\n\n\t// Binary types\n\tif (normalized === \"binary\") return StandardizedDataType.binary;\n\tif (normalized === \"varbinary\") return StandardizedDataType.varbinary;\n\tif (normalized === \"image\") return StandardizedDataType.blob;\n\n\t// UUID\n\tif (normalized === \"uniqueidentifier\") return StandardizedDataType.uuid;\n\n\t// Date/time types\n\tif (normalized === \"date\") return StandardizedDataType.date;\n\tif (normalized === \"time\") return StandardizedDataType.time;\n\tif (normalized === \"datetime\") return StandardizedDataType.datetime;\n\tif (normalized === \"datetime2\") return StandardizedDataType.datetime;\n\tif (normalized === \"smalldatetime\") return StandardizedDataType.datetime;\n\tif (normalized === \"datetimeoffset\") return StandardizedDataType.timestamptz;\n\n\t// JSON and XML\n\tif (normalized === \"json\") return StandardizedDataType.json;\n\tif (normalized === \"xml\") return StandardizedDataType.xml;\n\n\t// Default\n\treturn StandardizedDataType.text;\n}\n\n/**\n * Maps SQLite type affinity strings to generic DataTypes (used for cell rendering).\n * SQLite has flexible typing — column types are user-declared strings, so we use affinity rules.\n */\nexport function mapSqliteToDataType(sqliteType: string): DataTypes {\n\tconst normalized = sqliteType?.toLowerCase().trim() || \"\";\n\n\tif (normalized === \"boolean\" || normalized === \"bool\") return DataTypes.boolean;\n\tif (normalized === \"json\") return DataTypes.json;\n\n\tif (\n\t\tnormalized === \"date\" ||\n\t\tnormalized === \"datetime\" ||\n\t\tnormalized === \"timestamp\" ||\n\t\tnormalized === \"time\"\n\t) {\n\t\treturn DataTypes.date;\n\t}\n\n\t// SQLite integer affinity: any type name containing \"INT\"\n\tif (\n\t\tnormalized.includes(\"int\") ||\n\t\tnormalized === \"real\" ||\n\t\tnormalized.includes(\"floa\") ||\n\t\tnormalized.includes(\"doub\") ||\n\t\tnormalized === \"numeric\" ||\n\t\tnormalized.startsWith(\"numeric(\") ||\n\t\tnormalized === \"decimal\" ||\n\t\tnormalized.startsWith(\"decimal(\")\n\t) {\n\t\treturn DataTypes.number;\n\t}\n\n\treturn DataTypes.text;\n}\n\n/**\n * Maps SQLite type strings to the standardized display labels used in ColumnInfoSchemaType.\n */\nexport function standardizeSqliteDataTypeLabel(sqliteType: string): StandardizedDataType {\n\tconst normalized = sqliteType?.toLowerCase().trim() || \"\";\n\n\tif (normalized === \"integer\" || normalized === \"int\") return StandardizedDataType.int;\n\tif (normalized === \"bigint\" || normalized.startsWith(\"bigint(\"))\n\t\treturn StandardizedDataType.bigint;\n\tif (normalized === \"smallint\" || normalized.startsWith(\"smallint(\"))\n\t\treturn StandardizedDataType.smallint;\n\tif (normalized === \"tinyint\" || normalized.startsWith(\"tinyint(\"))\n\t\treturn StandardizedDataType.tinyint;\n\tif (normalized === \"mediumint\" || normalized.startsWith(\"mediumint(\"))\n\t\treturn StandardizedDataType.mediumint;\n\tif (normalized.includes(\"int\")) return StandardizedDataType.int;\n\n\tif (normalized === \"real\" || normalized === \"float\" || normalized.startsWith(\"float(\"))\n\t\treturn StandardizedDataType.float;\n\tif (\n\t\tnormalized === \"double\" ||\n\t\tnormalized === \"double precision\" ||\n\t\tnormalized.startsWith(\"double(\")\n\t)\n\t\treturn StandardizedDataType.double;\n\n\tif (\n\t\tnormalized === \"numeric\" ||\n\t\tnormalized.startsWith(\"numeric(\") ||\n\t\tnormalized === \"decimal\" ||\n\t\tnormalized.startsWith(\"decimal(\")\n\t) {\n\t\treturn StandardizedDataType.numeric;\n\t}\n\n\tif (normalized === \"boolean\" || normalized === \"bool\") return StandardizedDataType.boolean;\n\n\tif (normalized === \"text\" || normalized === \"clob\") return StandardizedDataType.text;\n\tif (normalized === \"varchar\" || normalized.startsWith(\"varchar(\"))\n\t\treturn StandardizedDataType.varchar;\n\tif (normalized === \"char\" || normalized.startsWith(\"char(\"))\n\t\treturn StandardizedDataType.char;\n\n\tif (normalized === \"json\") return StandardizedDataType.json;\n\n\tif (normalized === \"date\") return StandardizedDataType.date;\n\tif (normalized === \"time\") return StandardizedDataType.time;\n\tif (normalized === \"datetime\") return StandardizedDataType.datetime;\n\tif (normalized === \"timestamp\") return StandardizedDataType.timestamp;\n\n\tif (normalized === \"blob\") return StandardizedDataType.blob;\n\n\treturn StandardizedDataType.text;\n}\n","import { z } from \"zod\";\n\nexport const FOREIGN_KEY_ACTIONS = [\n\t\"CASCADE\",\n\t\"SET NULL\",\n\t\"SET DEFAULT\",\n\t\"RESTRICT\",\n\t\"NO ACTION\",\n] as const;\nexport const foreignKeyActionSchema = z.enum(FOREIGN_KEY_ACTIONS);\n\nexport const fieldDataSchema = z.object({\n\tcolumnName: z.string(\"Column name is required\"),\n\tcolumnType: z.string(\"Column type is required\"),\n\tdefaultValue: z.string().optional(),\n\tisPrimaryKey: z.boolean().default(false),\n\tisNullable: z.boolean().default(false),\n\tisUnique: z.boolean().default(false),\n\tisIdentity: z.boolean().default(false),\n\tisArray: z.boolean().default(false),\n});\nexport type FieldDataType = z.infer<typeof fieldDataSchema>;\n\nexport const foreignKeyDataSchema = z.object({\n\tcolumnName: z.string(\"Column name is required\"),\n\treferencedTable: z.string(\"Referenced table is required\"),\n\treferencedColumn: z.string(\"Referenced column is required\"),\n\tonUpdate: foreignKeyActionSchema.default(\"NO ACTION\"),\n\tonDelete: foreignKeyActionSchema.default(\"NO ACTION\"),\n});\nexport type ForeignKeyDataType = z.infer<typeof foreignKeyDataSchema>;\n\nexport const createTableSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n\tfields: z.array(fieldDataSchema).min(1, \"At least one field is required\"),\n\tforeignKeys: z.array(foreignKeyDataSchema).optional(),\n});\n\nexport type CreateTableSchemaType = z.infer<typeof createTableSchema>;\n","import type { DatabaseTypeSchema } from \"./database.types.js\";\n\nexport type DatabaseCapability = \"liveMode\";\n\nexport interface DatabaseCapabilities {\n\tliveMode: boolean;\n}\n\nexport const DATABASE_CAPABILITIES: Record<DatabaseTypeSchema, DatabaseCapabilities> = {\n\tpg: { liveMode: true },\n\tmysql: { liveMode: false },\n\tmssql: { liveMode: false },\n\tsqlite: { liveMode: false },\n\tmongodb: { liveMode: false },\n\tredis: { liveMode: false },\n};\n\nexport function hasDatabaseCapability(\n\tdbType: DatabaseTypeSchema | null | undefined,\n\tcapability: DatabaseCapability,\n): boolean {\n\tif (!dbType) return false;\n\treturn DATABASE_CAPABILITIES[dbType]?.[capability] ?? false;\n}\n","import { z } from \"zod\";\nimport { databaseTypeSchema } from \"./database.types.js\";\n\nexport const databaseInfoSchema = z.object({\n\tname: z.string(\"Name is required\"),\n\tsize: z.string(\"Size is required\"),\n\towner: z.string(\"Owner is required\"),\n\tencoding: z.string(\"Encoding is required\"),\n});\n\nexport type DatabaseInfoSchemaType = z.infer<typeof databaseInfoSchema>;\n\nexport const databaseListSchema = z.object({\n\tdatabases: z.array(databaseInfoSchema),\n\tdbType: databaseTypeSchema,\n});\n\nexport type DatabaseListSchemaType = z.infer<typeof databaseListSchema>;\n\nexport const connectionInfoSchema = z.object({\n\tversion: z.string(\"Version is required\"),\n\tdatabase: z.string(\"Database is required\"),\n\tuser: z.string(\"User is required\"),\n\thost: z.string(\"Host is required\").nullable(),\n\tport: z.number(\"Port is required\").nullable(),\n\tactive_connections: z.coerce.number(\"Active connections is required\"),\n\tmax_connections: z.coerce.number(\"Max connections is required\"),\n});\n\nexport type ConnectionInfoSchemaType = z.infer<typeof connectionInfoSchema>;\n","import type { DatabaseTypeSchema } from \"./database.types\";\n\nexport type DatabaseSchema = {\n\tdbType: DatabaseTypeSchema;\n\ttables: Table[];\n\trelationships: Relationship[];\n};\n\nexport type Table = {\n\tname: string;\n\tdescription?: string;\n\tcolumns: Column[];\n\tsampleData?: Record<string, string>[];\n};\n\nexport type Column = {\n\tname: string;\n\ttype: string;\n\tnullable: boolean;\n\tisPrimaryKey?: boolean;\n\tforeignKey?: string;\n\tdescription?: string;\n\tenumValues?: string[];\n};\n\nexport type Relationship = {\n\tfromTable: string;\n\tfromColumn: string;\n\ttoTable: string;\n\ttoColumn: string;\n};\n","import { z } from \"zod\";\nimport type { DatabaseSchemaType } from \"./database.types\";\n\nexport const deleteRecordSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n\tprimaryKeys: z\n\t\t.array(\n\t\t\tz.object({\n\t\t\t\tcolumnName: z.string(\"Column name is required\"),\n\t\t\t\tvalue: z.any(),\n\t\t\t}),\n\t\t)\n\t\t.min(1, \"At least one primary key is required\"),\n});\n\nexport type DeleteRecordSchemaType = z.infer<typeof deleteRecordSchema>;\n\nexport type DeleteRecordParams = DeleteRecordSchemaType & {\n\tdb: DatabaseSchemaType[\"db\"];\n};\n\nexport type DeleteRecordResult = {\n\tdeletedCount: number;\n\tfkViolation: boolean;\n\trelatedRecords: RelatedRecord[];\n};\n\nexport type ForeignKeyConstraint = {\n\tconstraintName: string;\n\treferencingTable: string;\n\treferencingColumn: string;\n\treferencedTable: string;\n\treferencedColumn: string;\n};\n\nexport type ForeignKeyConstraintRow = {\n\tconstraint_name: string;\n\treferencing_table: string;\n\treferencing_column: string;\n\treferenced_table: string;\n\treferenced_column: string;\n};\n\nexport type RelatedRecord = {\n\ttableName: string;\n\tcolumnName: string;\n\tconstraintName: string;\n\trecords: Array<Record<string, unknown>>;\n};\n","import { z } from \"zod\";\nimport { databaseSchema } from \"./database.types\";\nimport type { RelatedRecord } from \"./delete-record.types\";\n\nexport const deleteTableQuerySchema = databaseSchema.extend({\n\tcascade: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform((val) => val === \"true\"),\n});\n\nexport type DeleteTableQuerySchemaType = z.infer<typeof deleteTableQuerySchema>;\n\nexport type DeleteTableParams = {\n\ttableName: string;\n\tdb: string;\n\tcascade?: boolean;\n};\n\nexport type DeleteTableResult = {\n\tdeletedCount: number;\n\tfkViolation: boolean;\n\trelatedRecords: RelatedRecord[];\n};\n","import { z } from \"zod\";\n\nexport const executeQuerySchema = z.object({\n\tquery: z.string(\"Query is required\"),\n});\n\nexport type ExecuteQueryParams = z.infer<typeof executeQuerySchema>;\n\nexport type ExecuteQueryResult = {\n\tcolumns: string[];\n\trows: Record<string, unknown>[];\n\trowCount: number;\n\tduration: number;\n\tmessage?: string;\n\terror?: string;\n};\n","import { z } from \"zod\";\nimport { databaseSchema } from \"./database.types.js\";\n\nexport const FORMAT_TYPES = [\"csv\", \"xlsx\", \"json\"] as const;\nexport type FormatType = (typeof FORMAT_TYPES)[number];\n\nexport const exportTableSchema = databaseSchema.extend({\n\tformat: z.enum(FORMAT_TYPES, {\n\t\tmessage: \"Invalid format. Supported formats: csv, xlsx, json\",\n\t}),\n});\nexport type ExportTableSchemaType = z.infer<typeof exportTableSchema>;\n\nexport type CellValue = string | number | boolean | Date | null | undefined;\n","import { z } from \"zod\";\n\nexport const redisKeyTypeSchema = z.enum([\n\t\"string\",\n\t\"hash\",\n\t\"list\",\n\t\"set\",\n\t\"zset\",\n\t\"stream\",\n\t\"unknown\",\n]);\nexport type RedisKeyTypeSchemaType = z.infer<typeof redisKeyTypeSchema>;\n\nexport const encodedRedisValueSchema = z.object({\n\tbase64: z\n\t\t.string()\n\t\t.max(16 * 1024 * 1024)\n\t\t.refine(\n\t\t\t(value) => /^(?:[A-Za-z0-9_-]{4})*(?:[A-Za-z0-9_-]{2,3})?$/.test(value),\n\t\t\t\"Invalid unpadded base64url value\",\n\t\t),\n\tutf8: z.string().optional(),\n});\nexport type EncodedRedisValueSchemaType = z.infer<typeof encodedRedisValueSchema>;\n\nexport const keyScanQuerySchema = z.object({\n\tdb: z.string(),\n\tcursor: z\n\t\t.string()\n\t\t.max(2048)\n\t\t.regex(/^[A-Za-z0-9_-]+$/)\n\t\t.optional(),\n\tlimit: z.coerce.number().int().min(1).max(200).default(50),\n\tsearch: z.string().max(512).optional(),\n\texactPattern: z.stringbool().default(false),\n\ttype: redisKeyTypeSchema.exclude([\"unknown\"]).optional(),\n});\nexport type KeyScanQuerySchemaType = z.infer<typeof keyScanQuerySchema>;\n\nexport const redisKeySummarySchema = z.object({\n\tkey: encodedRedisValueSchema,\n\ttype: redisKeyTypeSchema,\n\tttlMs: z.number().int(),\n\tmemoryBytes: z.number().int().nonnegative().nullable(),\n});\nexport type RedisKeySummarySchemaType = z.infer<typeof redisKeySummarySchema>;\n\nexport const keyScanResultSchema = z.object({\n\tkeys: z.array(redisKeySummarySchema),\n\tnextCursor: z.string().nullable(),\n\thasMore: z.boolean(),\n});\nexport type KeyScanResultSchemaType = z.infer<typeof keyScanResultSchema>;\n\nexport const keyDetailsQuerySchema = z.object({\n\tdb: z.string(),\n\tcursor: z\n\t\t.string()\n\t\t.max(2048)\n\t\t.regex(/^[A-Za-z0-9_-]+$/)\n\t\t.optional(),\n\tlimit: z.coerce.number().int().min(1).max(500).default(100),\n\tfull: z.stringbool().default(false),\n\tdirection: z.enum([\"forward\", \"backward\"]).default(\"forward\"),\n});\nexport type KeyDetailsQuerySchemaType = z.infer<typeof keyDetailsQuerySchema>;\n\nexport const keyParamSchema = z.object({\n\tkey: z\n\t\t.string()\n\t\t.min(1)\n\t\t.max(16 * 1024)\n\t\t.regex(/^[A-Za-z0-9_-]+$/), // \"-\" is the URL sentinel for Redis' valid empty binary key.\n});\n\nconst redisStringValueSchema = z.object({\n\tkind: z.literal(\"string\"),\n\tvalue: encodedRedisValueSchema,\n\ttruncated: z.boolean(),\n});\n\nconst redisHashValueSchema = z.object({\n\tkind: z.literal(\"hash\"),\n\tentries: z.array(\n\t\tz.object({ field: encodedRedisValueSchema, value: encodedRedisValueSchema }),\n\t),\n});\n\nconst redisListValueSchema = z.object({\n\tkind: z.literal(\"list\"),\n\tentries: z.array(z.object({ index: z.number().int(), value: encodedRedisValueSchema })),\n});\n\nconst redisSetValueSchema = z.object({\n\tkind: z.literal(\"set\"),\n\tmembers: z.array(encodedRedisValueSchema),\n});\n\nconst redisSortedSetValueSchema = z.object({\n\tkind: z.literal(\"zset\"),\n\tentries: z.array(\n\t\tz.object({\n\t\t\tmember: encodedRedisValueSchema,\n\t\t\tscore: z.union([z.number(), z.literal(\"inf\"), z.literal(\"-inf\")]),\n\t\t}),\n\t),\n});\n\nconst redisStreamValueSchema = z.object({\n\tkind: z.literal(\"stream\"),\n\tentries: z.array(\n\t\tz.object({\n\t\t\tid: z.string(),\n\t\t\tfields: z.array(\n\t\t\t\tz.object({ field: encodedRedisValueSchema, value: encodedRedisValueSchema }),\n\t\t\t),\n\t\t}),\n\t),\n});\n\nconst redisUnknownValueSchema = z.object({ kind: z.literal(\"unknown\") });\n\nexport const redisKeyValueSchema = z.discriminatedUnion(\"kind\", [\n\tredisStringValueSchema,\n\tredisHashValueSchema,\n\tredisListValueSchema,\n\tredisSetValueSchema,\n\tredisSortedSetValueSchema,\n\tredisStreamValueSchema,\n\tredisUnknownValueSchema,\n]);\nexport type RedisKeyValueSchemaType = z.infer<typeof redisKeyValueSchema>;\n\nexport const keyDetailsResultSchema = redisKeySummarySchema.extend({\n\tlength: z.number().int().nonnegative().nullable(),\n\trevision: z.string(),\n\tvalue: redisKeyValueSchema,\n\tnextCursor: z.string().nullable(),\n\thasMore: z.boolean(),\n});\nexport type KeyDetailsResultSchemaType = z.infer<typeof keyDetailsResultSchema>;\n\nexport const keyRawQuerySchema = z.object({\n\tdb: z.string(),\n\toffset: z.coerce.number().int().nonnegative().default(0),\n\tlimit: z.coerce\n\t\t.number()\n\t\t.int()\n\t\t.min(1)\n\t\t.max(1024 * 1024)\n\t\t.default(1024 * 1024),\n\texpectedRevision: z.string().optional(),\n});\nexport type KeyRawQuerySchemaType = z.infer<typeof keyRawQuerySchema>;\n\nexport const keyRawResultSchema = z.object({\n\tchunk: encodedRedisValueSchema,\n\tlength: z.number().int().nonnegative(),\n\tnextOffset: z.number().int().nonnegative().nullable(),\n\thasMore: z.boolean(),\n});\nexport type KeyRawResultSchemaType = z.infer<typeof keyRawResultSchema>;\n\nconst createStringValueSchema = z.object({\n\tkind: z.literal(\"string\"),\n\tvalue: encodedRedisValueSchema,\n});\n\nconst createHashValueSchema = z.object({\n\tkind: z.literal(\"hash\"),\n\tentries: z\n\t\t.array(z.object({ field: encodedRedisValueSchema, value: encodedRedisValueSchema }))\n\t\t.min(1),\n});\n\nconst createListValueSchema = z.object({\n\tkind: z.literal(\"list\"),\n\tentries: z.array(encodedRedisValueSchema).min(1),\n});\n\nconst createSetValueSchema = z.object({\n\tkind: z.literal(\"set\"),\n\tmembers: z.array(encodedRedisValueSchema).min(1),\n});\n\nconst createSortedSetValueSchema = z.object({\n\tkind: z.literal(\"zset\"),\n\tentries: z.array(z.object({ member: encodedRedisValueSchema, score: z.number() })).min(1),\n});\n\nconst createStreamValueSchema = z.object({\n\tkind: z.literal(\"stream\"),\n\tid: z.string().default(\"*\"),\n\tfields: z\n\t\t.array(z.object({ field: encodedRedisValueSchema, value: encodedRedisValueSchema }))\n\t\t.min(1),\n});\n\nexport const createKeySchema = z.object({\n\tkey: encodedRedisValueSchema,\n\ttype: redisKeyTypeSchema.exclude([\"unknown\"]),\n\tvalue: z.discriminatedUnion(\"kind\", [\n\t\tcreateStringValueSchema,\n\t\tcreateHashValueSchema,\n\t\tcreateListValueSchema,\n\t\tcreateSetValueSchema,\n\t\tcreateSortedSetValueSchema,\n\t\tcreateStreamValueSchema,\n\t]),\n\tttlMs: z.number().int().positive().nullable().default(null),\n});\nexport type CreateKeySchemaType = z.infer<typeof createKeySchema>;\n\nexport const keyWriteResultSchema = z.object({\n\tkey: encodedRedisValueSchema,\n\trevision: z.string().nullable(),\n\tdeleted: z.boolean(),\n});\nexport type KeyWriteResultSchemaType = z.infer<typeof keyWriteResultSchema>;\n\nconst renameKeyActionSchema = z.object({\n\taction: z.literal(\"rename\"),\n\tnewKey: encodedRedisValueSchema,\n});\n\nconst setTtlKeyActionSchema = z.object({\n\taction: z.literal(\"setTtl\"),\n\tttlMs: z.number().int().positive().nullable(),\n});\n\nconst setStringKeyActionSchema = z.object({\n\taction: z.literal(\"setString\"),\n\tvalue: encodedRedisValueSchema,\n});\n\nconst upsertHashKeyActionSchema = z.object({\n\taction: z.literal(\"upsertHash\"),\n\tfield: encodedRedisValueSchema,\n\tvalue: encodedRedisValueSchema,\n});\n\nconst deleteHashKeyActionSchema = z.object({\n\taction: z.literal(\"deleteHash\"),\n\tfield: encodedRedisValueSchema,\n});\n\nconst pushListKeyActionSchema = z.object({\n\taction: z.literal(\"pushList\"),\n\tside: z.enum([\"left\", \"right\"]),\n\tvalue: encodedRedisValueSchema,\n});\n\nconst setListKeyActionSchema = z.object({\n\taction: z.literal(\"setList\"),\n\tindex: z.number().int(),\n\tvalue: encodedRedisValueSchema,\n});\n\nconst deleteListKeyActionSchema = z.object({\n\taction: z.literal(\"deleteList\"),\n\tindex: z.number().int(),\n});\n\nconst addSetKeyActionSchema = z.object({\n\taction: z.literal(\"addSet\"),\n\tmember: encodedRedisValueSchema,\n});\n\nconst removeSetKeyActionSchema = z.object({\n\taction: z.literal(\"removeSet\"),\n\tmember: encodedRedisValueSchema,\n});\n\nconst upsertSortedSetKeyActionSchema = z.object({\n\taction: z.literal(\"upsertZset\"),\n\tmember: encodedRedisValueSchema,\n\tscore: z.number(),\n});\n\nconst removeSortedSetKeyActionSchema = z.object({\n\taction: z.literal(\"removeZset\"),\n\tmember: encodedRedisValueSchema,\n});\n\nconst appendStreamKeyActionSchema = z.object({\n\taction: z.literal(\"appendStream\"),\n\tid: z.string().default(\"*\"),\n\tfields: z\n\t\t.array(z.object({ field: encodedRedisValueSchema, value: encodedRedisValueSchema }))\n\t\t.min(1),\n});\n\nconst deleteStreamKeyActionSchema = z.object({\n\taction: z.literal(\"deleteStream\"),\n\tid: z.string(),\n});\n\nexport const keyActionSchema = z.object({\n\texpectedRevision: z.string(),\n\tforce: z.boolean().default(false),\n\toperation: z.discriminatedUnion(\"action\", [\n\t\trenameKeyActionSchema,\n\t\tsetTtlKeyActionSchema,\n\t\tsetStringKeyActionSchema,\n\t\tupsertHashKeyActionSchema,\n\t\tdeleteHashKeyActionSchema,\n\t\tpushListKeyActionSchema,\n\t\tsetListKeyActionSchema,\n\t\tdeleteListKeyActionSchema,\n\t\taddSetKeyActionSchema,\n\t\tremoveSetKeyActionSchema,\n\t\tupsertSortedSetKeyActionSchema,\n\t\tremoveSortedSetKeyActionSchema,\n\t\tappendStreamKeyActionSchema,\n\t\tdeleteStreamKeyActionSchema,\n\t]),\n});\nexport type KeyActionSchemaType = z.infer<typeof keyActionSchema>;\n\nexport const deleteKeyQuerySchema = z.object({\n\tdb: z.string(),\n\texpectedRevision: z.string(),\n\tforce: z.stringbool().default(false),\n});\nexport type DeleteKeyQuerySchemaType = z.infer<typeof deleteKeyQuerySchema>;\n\nexport const deleteKeyResultSchema = z.object({ deleted: z.boolean() });\nexport type DeleteKeyResultSchemaType = z.infer<typeof deleteKeyResultSchema>;\n","export type RateLimitResponse = {\n\tlimit: number;\n\tused: number;\n\tremaining: number;\n};\n","import { z } from \"zod\";\nimport { databaseSchema } from \"./database.types\";\nimport { deleteColumnParamSchema } from \"./delete-column.types\";\n\nexport const renameColumnSchema = z.object({\n\tnewColumnName: z.string(\"New column name is required\"),\n});\n\nexport type RenameColumnSchemaType = z.infer<typeof renameColumnSchema>;\n\nexport const renameColumnParamSchema = deleteColumnParamSchema;\n\nexport type RenameColumnParamSchemaType = z.infer<typeof renameColumnParamSchema>;\n\nexport const renameColumnParamsSchema = z.object({\n\tdb: databaseSchema.shape.db,\n\ttableName: deleteColumnParamSchema.shape.tableName,\n\tcolumnName: deleteColumnParamSchema.shape.columnName,\n\tnewColumnName: renameColumnSchema.shape.newColumnName,\n});\n\nexport type RenameColumnParamsSchemaType = z.infer<typeof renameColumnParamsSchema>;\n","import { z } from \"zod\";\nimport { databaseSchema, tableNameSchema } from \"./database.types\";\n\nexport const renameTableSchema = z.object({\n\t// Trimmed server-side so whitespace-only names are rejected even if a\n\t// client skips the frontend trim (matches the sidebar dialog behavior).\n\tnewTableName: z\n\t\t.string(\"New table name is required\")\n\t\t.trim()\n\t\t.min(1, \"New table name is required\"),\n\tschemaName: z.string().trim().min(1).optional(),\n});\n\nexport type RenameTableSchemaType = z.infer<typeof renameTableSchema>;\n\nexport const renameTableParamSchema = tableNameSchema;\n\nexport type RenameTableParamSchemaType = z.infer<typeof renameTableParamSchema>;\n\nexport const renameTableParamsSchema = z.object({\n\tdb: databaseSchema.shape.db,\n\ttableName: tableNameSchema.shape.tableName,\n\tnewTableName: renameTableSchema.shape.newTableName,\n\tschemaName: renameTableSchema.shape.schemaName,\n});\n\nexport type RenameTableParamsSchemaType = z.infer<typeof renameTableParamsSchema>;\n","import { z } from \"zod\";\nimport { databaseSchema } from \"./database.types.js\";\n\nexport const filterSchema = z.object({\n\tcolumnName: z.string(),\n\toperator: z.string(),\n\tvalue: z.string(),\n});\n\nexport type FilterType = z.infer<typeof filterSchema>;\n\nexport const sortDirections = [\"asc\", \"desc\"] as const;\nexport type SortDirection = (typeof sortDirections)[number];\n\nexport const sortSchema = z.object({\n\tcolumnName: z.string(),\n\tdirection: z.enum(sortDirections),\n});\n\nexport type SortType = z.infer<typeof sortSchema>;\n\nexport const tableDataMetaSchema = z.object({\n\tlimit: z.number(),\n\ttotal: z.number(),\n\thasNextPage: z.boolean(),\n\thasPreviousPage: z.boolean(),\n\tnextCursor: z.string().nullable(),\n\tprevCursor: z.string().nullable(),\n});\n\nexport const tableDataResultSchema = z.object({\n\tdata: z.array(z.record(z.string(), z.unknown())),\n\tmeta: tableDataMetaSchema,\n});\n\nexport type TableDataResultSchemaType = z.infer<typeof tableDataResultSchema>;\n\nexport const tableDataQuerySchema = z.object({\n\tdb: databaseSchema.shape.db,\n\tcursor: z.string().optional(), // Base64 encoded cursor for pagination\n\tlimit: z.string().optional().default(\"50\").transform(Number),\n\tdirection: z.enum(sortDirections).optional().default(sortDirections[0]), // Pagination direction\n\tsort: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform((val) => {\n\t\t\tif (!val) return \"\";\n\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(val);\n\t\t\t\tif (Array.isArray(parsed)) {\n\t\t\t\t\treturn parsed;\n\t\t\t\t}\n\t\t\t\treturn val;\n\t\t\t} catch {\n\t\t\t\treturn val;\n\t\t\t}\n\t\t}),\n\torder: z.enum(sortDirections).optional(),\n\tfilters: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform((val) => {\n\t\t\tif (!val) return [];\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(val);\n\t\t\t} catch {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t}),\n});\n\nexport type TableDataQuerySchemaType = z.infer<typeof tableDataQuerySchema>;\n\nexport interface CursorData {\n\tvalues: Record<string, unknown>;\n\tsortColumns: string[];\n}\n","import { z } from \"zod\";\n\nexport const tableInfoSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n\tschemaName: z.string().optional(),\n\trowCount: z.coerce.number(\"Row count is required\"),\n});\n\nexport type TableInfoSchemaType = z.infer<typeof tableInfoSchema>;\n","import { z } from \"zod\";\n\nexport const tableSchemaResultSchema = z.object({\n\tschema: z.string(),\n});\n\nexport type TableSchemaResult = z.infer<typeof tableSchemaResultSchema>;\n","import { z } from \"zod\";\n\nexport const updateRecordsSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n\tprimaryKey: z.string(\"Primary key is required\").default(\"id\"),\n\t/**\n\t * Every component of a composite primary key. When present it takes precedence\n\t * over `primaryKey`, so a row is matched on all of its key columns instead of\n\t * only the first one.\n\t */\n\tprimaryKeys: z.array(z.string().min(1)).min(1).optional(),\n\tupdates: z\n\t\t.array(\n\t\t\tz.object(\n\t\t\t\t{\n\t\t\t\t\trowData: z.record(z.string(\"Column name is required\"), z.any()),\n\t\t\t\t\tcolumnName: z.string(\"Column name is required\"),\n\t\t\t\t\tvalue: z.any(),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tmessage: \"Each update must have a row data, column name, and value.\",\n\t\t\t\t},\n\t\t\t),\n\t\t)\n\t\t.min(1, \"At least one update is required\"),\n});\n\nexport type UpdateRecordsSchemaType = z.infer<typeof updateRecordsSchema>;\n","export * from \"./add-column.types.js\";\nexport * from \"./add-record.types.js\"; // done\nexport * from \"./ai-provider.types.js\";\nexport * from \"./alter-column.types.js\";\nexport * from \"./api-response.types.js\";\nexport * from \"./bulk-insert-records.type.js\";\nexport * from \"./chat.types.js\"; // done\nexport * from \"./cmd-args.types.js\"; // done\nexport * from \"./column.type.js\";\nexport * from \"./column-info.types.js\";\nexport * from \"./create-table.types.js\"; // done\nexport * from \"./database.types.js\"; // done\nexport * from \"./database-capabilities.types.js\";\nexport * from \"./database-list.types.js\"; // done\nexport * from \"./database-schema.type.js\"; // done\nexport * from \"./delete-column.types.js\"; // done\nexport * from \"./delete-record.types.js\"; // done\nexport * from \"./delete-table.types.js\"; // done\nexport * from \"./execute-query.types.js\"; // done\nexport * from \"./export-table.types.js\";\nexport * from \"./key-browser.types.js\";\nexport * from \"./rate-limit-response.type.js\";\nexport * from \"./rename-column.types.js\";\nexport * from \"./rename-table.types.js\";\nexport * from \"./table-data.types.js\"; // done\nexport * from \"./table-info.type.js\"; // done\nexport * from \"./table-schema.types.js\"; // done\nexport * from \"./update-recors.types.js\"; // done\n","import type { FilterType, SortDirection, SortType } from \"@db-studio/shared/types\";\n\nexport function buildWhereClause(\n\tfilters: FilterType[],\n\tstartIdx = 0,\n): { clause: string; values: unknown[]; nextIdx: number } {\n\tif (filters.length === 0) return { clause: \"\", values: [], nextIdx: startIdx };\n\n\tconst conditions: string[] = [];\n\tconst values: unknown[] = [];\n\tlet idx = startIdx;\n\n\tfor (const filter of filters) {\n\t\tconst col = `[${filter.columnName}]`;\n\t\tswitch (filter.operator) {\n\t\t\tcase \"=\":\n\t\t\tcase \"!=\":\n\t\t\tcase \">\":\n\t\t\tcase \">=\":\n\t\t\tcase \"<\":\n\t\t\tcase \"<=\":\n\t\t\t\tconditions.push(`${col} ${filter.operator} @p${idx}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tidx++;\n\t\t\t\tbreak;\n\t\t\tcase \"is\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${col} IS NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} = @p${idx}`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t\tidx++;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"is not\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${col} IS NOT NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} != @p${idx}`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t\tidx++;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"like\":\n\t\t\tcase \"ilike\":\n\t\t\t\tconditions.push(`${col} LIKE @p${idx}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tidx++;\n\t\t\t\tbreak;\n\t\t\tcase \"not like\":\n\t\t\tcase \"not ilike\":\n\t\t\t\tconditions.push(`${col} NOT LIKE @p${idx}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tidx++;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (conditions.length === 0) return { clause: \"\", values: [], nextIdx: startIdx };\n\treturn { clause: `WHERE ${conditions.join(\" AND \")}`, values, nextIdx: idx };\n}\n\nexport function buildSortClause(sorts: SortType[] | string, order: SortDirection): string {\n\tif (Array.isArray(sorts)) {\n\t\tif (sorts.length === 0) return \"\";\n\t\treturn `ORDER BY ${sorts.map((s) => `[${s.columnName}] ${s.direction.toUpperCase()}`).join(\", \")}`;\n\t}\n\tif (sorts && typeof sorts === \"string\") {\n\t\treturn `ORDER BY [${sorts}] ${order?.toUpperCase() || \"ASC\"}`;\n\t}\n\treturn \"\";\n}\n\nexport function mapColumnTypeToMssql(columnType: string, isArray: boolean): string {\n\tif (isArray) return \"NVARCHAR(MAX)\";\n\n\tconst normalized = columnType.toLowerCase().trim();\n\tconst typeMap: Record<string, string> = {\n\t\tserial: \"INT IDENTITY(1,1)\",\n\t\tserial4: \"INT IDENTITY(1,1)\",\n\t\tbigserial: \"BIGINT IDENTITY(1,1)\",\n\t\tserial8: \"BIGINT IDENTITY(1,1)\",\n\t\tint: \"INT\",\n\t\tint4: \"INT\",\n\t\tinteger: \"INT\",\n\t\tbigint: \"BIGINT\",\n\t\tint8: \"BIGINT\",\n\t\tsmallint: \"SMALLINT\",\n\t\tint2: \"SMALLINT\",\n\t\ttinyint: \"TINYINT\",\n\t\tnumeric: \"NUMERIC\",\n\t\tdecimal: \"DECIMAL\",\n\t\treal: \"REAL\",\n\t\tfloat4: \"REAL\",\n\t\tfloat: \"FLOAT\",\n\t\t\"double precision\": \"FLOAT\",\n\t\tfloat8: \"FLOAT\",\n\t\tmoney: \"MONEY\",\n\t\tboolean: \"BIT\",\n\t\tbool: \"BIT\",\n\t\ttext: \"NVARCHAR(MAX)\",\n\t\tvarchar: \"VARCHAR(255)\",\n\t\t\"character varying\": \"VARCHAR(255)\",\n\t\tchar: \"CHAR(1)\",\n\t\tcharacter: \"CHAR(1)\",\n\t\tbpchar: \"CHAR\",\n\t\tuuid: \"UNIQUEIDENTIFIER\",\n\t\tjson: \"NVARCHAR(MAX)\",\n\t\tjsonb: \"NVARCHAR(MAX)\",\n\t\txml: \"XML\",\n\t\tdate: \"DATE\",\n\t\ttime: \"TIME\",\n\t\t\"time without time zone\": \"TIME\",\n\t\ttimestamp: \"DATETIME2\",\n\t\t\"timestamp without time zone\": \"DATETIME2\",\n\t\t\"timestamp with time zone\": \"DATETIMEOFFSET\",\n\t\ttimestamptz: \"DATETIMEOFFSET\",\n\t\tinterval: \"VARCHAR(255)\",\n\t\tbytea: \"VARBINARY(MAX)\",\n\t\tinet: \"VARCHAR(45)\",\n\t\tcidr: \"VARCHAR(45)\",\n\t\tmacaddr: \"VARCHAR(17)\",\n\t\tmacaddr8: \"VARCHAR(23)\",\n\t};\n\n\treturn typeMap[normalized] || columnType.toUpperCase();\n}\n\nexport function formatMssqlDefaultValue(\n\tdefaultValue: string,\n\tcolumnType: string,\n): string | null {\n\tconst trimmed = defaultValue.trim().toLowerCase();\n\n\tif (trimmed.includes(\"(\") && trimmed.includes(\")\")) {\n\t\tif (trimmed.includes(\"newid()\")) {\n\t\t\tif (!columnType.toUpperCase().includes(\"UNIQUEIDENTIFIER\")) return null;\n\t\t\treturn \"NEWID()\";\n\t\t}\n\t\tif (trimmed.includes(\"getdate\") || trimmed.includes(\"current_timestamp\"))\n\t\t\treturn \"GETDATE()\";\n\t\treturn defaultValue.trim();\n\t}\n\n\tif (trimmed === \"null\") return \"NULL\";\n\tif (trimmed === \"true\" || trimmed === \"false\") return trimmed === \"true\" ? \"1\" : \"0\";\n\treturn defaultValue.trim();\n}\n\ntype MssqlColumnDefinitionInput = {\n\tcolumnName: string;\n\tcolumnType: string;\n\tdefaultValue?: string | null;\n\tisPrimaryKey?: boolean;\n\tisNullable?: boolean;\n\tisUnique?: boolean;\n\tisIdentity?: boolean;\n\tisArray?: boolean;\n};\n\nexport function buildMssqlColumnDefinition(\n\tfield: MssqlColumnDefinitionInput,\n\toptions: { includePrimaryKey?: boolean; includeUnique?: boolean } = {},\n): string {\n\tconst mappedType = mapColumnTypeToMssql(field.columnType, field.isArray ?? false);\n\tlet def = `[${field.columnName}] ${mappedType}`;\n\n\tif (field.isIdentity && !mappedType.includes(\"IDENTITY\")) {\n\t\tdef += \" IDENTITY(1,1)\";\n\t}\n\n\tif (!field.isNullable && !field.isPrimaryKey) def += \" NOT NULL\";\n\n\tif (field.defaultValue?.trim() && !mappedType.includes(\"IDENTITY\")) {\n\t\tconst dv = formatMssqlDefaultValue(field.defaultValue, mappedType);\n\t\tif (dv !== null) def += ` DEFAULT ${dv}`;\n\t}\n\n\tif (options.includeUnique && field.isUnique && !field.isPrimaryKey) def += \" UNIQUE\";\n\tif (options.includePrimaryKey && field.isPrimaryKey) def += \" PRIMARY KEY\";\n\n\treturn def;\n}\n","import type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteRecordSchemaType,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tFieldDataType,\n\tForeignKeyConstraint,\n\tForeignKeyDataType,\n\tRelatedRecord,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tTableDataResultSchemaType,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { mapMssqlToDataType, standardizeMssqlDataTypeLabel } from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { ConnectionPool as MssqlPool } from \"mssql\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getMssqlPool } from \"@/adapters/connections.js\";\nimport { parseDatabaseUrl } from \"@/utils/parse-database-url.js\";\nimport {\n\tbuildMssqlColumnDefinition,\n\tbuildSortClause,\n\tbuildWhereClause,\n\tformatMssqlDefaultValue,\n\tmapColumnTypeToMssql,\n} from \"./mssql.query-builder.js\";\n\nconst MSSQL_FK_VIOLATION = 547;\nconst MSSQL_FK_DEPENDENCY = 3726;\n\ninterface FkConstraintRow {\n\tconstraint_name: string;\n\treferencing_table: string;\n\treferencing_column: string;\n\treferenced_table: string;\n\treferenced_column: string;\n}\n\nexport class MsSqlAdapter extends BaseAdapter {\n\t// =========================================================\n\t// Abstract method implementations\n\t// =========================================================\n\n\tprotected async runQuery<T>(db: string, sql: string, values: unknown[]): Promise<T> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst request = pool.request();\n\t\tvalues.forEach((val, idx) => {\n\t\t\trequest.input(`p${idx}`, val);\n\t\t});\n\t\tconst result = await request.query(sql);\n\t\treturn result.recordset as T;\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn `[${name}]`;\n\t}\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\treturn mapMssqlToDataType(nativeType);\n\t}\n\n\tmapFromUniversalType(universalType: string): string {\n\t\tconst map: Record<string, string> = {\n\t\t\ttext: \"NVARCHAR(MAX)\",\n\t\t\tnumber: \"INT\",\n\t\t\tboolean: \"BIT\",\n\t\t\tjson: \"NVARCHAR(MAX)\",\n\t\t\tdate: \"DATETIME2\",\n\t\t\tarray: \"NVARCHAR(MAX)\",\n\t\t\tenum: \"NVARCHAR(255)\",\n\t\t};\n\t\treturn map[universalType] ?? \"NVARCHAR(MAX)\";\n\t}\n\n\tprotected buildTableDataQuery(params: GetTableDataParams): QueryBundle {\n\t\tconst { tableName, filters = [], sort = [], order = \"asc\", limit = 50, cursor } = params;\n\t\tconst {\n\t\t\tclause: filterWhere,\n\t\t\tvalues: filterValues,\n\t\t\tnextIdx,\n\t\t} = buildWhereClause(filters, 0);\n\t\tconst sortClause = buildSortClause(sort, order) || \"ORDER BY (SELECT NULL)\";\n\t\tconst currentOffset = cursor ? this.decodeOffsetCursor(cursor) : 0;\n\n\t\tconst sql = `SELECT * FROM [${tableName}] ${filterWhere} ${sortClause} OFFSET @p${nextIdx} ROWS FETCH NEXT @p${nextIdx + 1} ROWS ONLY`;\n\t\tconst values = [...filterValues, currentOffset, limit + 1];\n\n\t\tconst countSql = `SELECT COUNT(*) as total FROM [${tableName}] ${filterWhere}`;\n\t\treturn { sql, values, countSql, countValues: filterValues };\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn (rawRows as Record<string, unknown>[]).map((row) => this.normalizeRow(row));\n\t}\n\n\tprotected buildCursors(\n\t\tparams: GetTableDataParams,\n\t\t_rows: NormalizedRow[],\n\t\thasMore: boolean,\n\t): { nextCursor: string | null; prevCursor: string | null } {\n\t\tconst { cursor, limit = 50 } = params;\n\t\tconst currentOffset = cursor ? this.decodeOffsetCursor(cursor) : 0;\n\t\treturn {\n\t\t\tnextCursor: hasMore ? this.makeCursor(currentOffset + limit) : null,\n\t\t\tprevCursor:\n\t\t\t\tcurrentOffset > 0 ? this.makeCursor(Math.max(0, currentOffset - limit)) : null,\n\t\t};\n\t}\n\n\t// =========================================================\n\t// Override getTableData for MSSQL OFFSET/FETCH pagination\n\t// =========================================================\n\n\toverride async getTableData(params: GetTableDataParams): Promise<TableDataResultSchemaType> {\n\t\ttry {\n\t\t\tconst {\n\t\t\t\ttableName,\n\t\t\t\tdb,\n\t\t\t\tlimit = 50,\n\t\t\t\tsort = [],\n\t\t\t\torder = \"asc\",\n\t\t\t\tcursor,\n\t\t\t\tfilters = [],\n\t\t\t} = params;\n\t\t\tconst pool = await getMssqlPool(db);\n\n\t\t\tconst currentOffset = cursor ? this.decodeOffsetCursor(cursor) : 0;\n\t\t\tconst {\n\t\t\t\tclause: filterWhere,\n\t\t\t\tvalues: filterValues,\n\t\t\t\tnextIdx,\n\t\t\t} = buildWhereClause(filters, 0);\n\t\t\tconst sortClause = buildSortClause(sort, order) || \"ORDER BY (SELECT NULL)\";\n\n\t\t\tconst countRequest = pool.request();\n\t\t\tfilterValues.forEach((val, idx) => {\n\t\t\t\tcountRequest.input(`p${idx}`, val);\n\t\t\t});\n\t\t\tconst countResult = await countRequest.query(\n\t\t\t\t`SELECT COUNT(*) as total FROM [${tableName}] ${filterWhere}`,\n\t\t\t);\n\t\t\tconst total = Number(countResult.recordset[0]?.total ?? 0);\n\n\t\t\tconst dataRequest = pool.request();\n\t\t\tfilterValues.forEach((val, idx) => {\n\t\t\t\tdataRequest.input(`p${idx}`, val);\n\t\t\t});\n\t\t\tdataRequest.input(`p${nextIdx}`, currentOffset);\n\t\t\tdataRequest.input(`p${nextIdx + 1}`, limit + 1);\n\n\t\t\tconst dataResult = await dataRequest.query(\n\t\t\t\t`SELECT * FROM [${tableName}] ${filterWhere} ${sortClause} OFFSET @p${nextIdx} ROWS FETCH NEXT @p${nextIdx + 1} ROWS ONLY`,\n\t\t\t);\n\n\t\t\tlet rows = dataResult.recordset as Record<string, unknown>[];\n\t\t\tconst hasMore = rows.length > limit;\n\t\t\tif (hasMore) rows = rows.slice(0, limit);\n\n\t\t\treturn {\n\t\t\t\tdata: rows,\n\t\t\t\tmeta: {\n\t\t\t\t\tlimit,\n\t\t\t\t\ttotal,\n\t\t\t\t\thasNextPage: hasMore,\n\t\t\t\t\thasPreviousPage: currentOffset > 0,\n\t\t\t\t\tnextCursor: hasMore ? this.makeCursor(currentOffset + limit) : null,\n\t\t\t\t\tprevCursor:\n\t\t\t\t\t\tcurrentOffset > 0 ? this.makeCursor(Math.max(0, currentOffset - limit)) : null,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// IDbAdapter implementations\n\t// =========================================================\n\n\t// --- Databases ---\n\n\tasync getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst pool = await getMssqlPool();\n\t\t\tconst result = await pool.request().query(`\n\t\t\t\tSELECT\n\t\t\t\t d.name AS name,\n\t\t\t\t CAST(ROUND(CAST(SUM(mf.size) * 8.0 / 1024 AS DECIMAL(10,2)), 2) AS VARCHAR(20)) + ' MB' AS size,\n\t\t\t\t SUSER_SNAME(d.owner_sid) AS owner,\n\t\t\t\t d.collation_name AS encoding\n\t\t\t\tFROM sys.databases d\n\t\t\t\tJOIN sys.master_files mf ON d.database_id = mf.database_id\n\t\t\t\tWHERE (d.database_id > 4 OR d.name = DB_NAME())\n\t\t\t\tGROUP BY d.name, d.owner_sid, d.collation_name\n\t\t\t\tORDER BY d.name\n\t\t\t`);\n\t\t\tif (!result.recordset[0]) {\n\t\t\t\tthrow new HTTPException(500, { message: \"No databases returned from server\" });\n\t\t\t}\n\t\t\treturn result.recordset as DatabaseInfoSchemaType[];\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\tconst pool = await getMssqlPool();\n\t\tconst result = await pool.request().query(\"SELECT DB_NAME() AS db\");\n\t\tif (!result.recordset[0]) {\n\t\t\tthrow new HTTPException(500, { message: \"No current database returned from server\" });\n\t\t}\n\t\treturn result.recordset[0] as DatabaseSchemaType;\n\t}\n\n\tasync getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\tconst pool = await getMssqlPool();\n\t\tconst result = await pool.request().query(`\n\t\t\tSELECT\n\t\t\t @@VERSION AS version,\n\t\t\t DB_NAME() AS database_name,\n\t\t\t SUSER_NAME() AS [user],\n\t\t\t @@SERVERNAME AS host,\n\t\t\t (SELECT local_tcp_port FROM sys.dm_exec_connections WHERE session_id = @@SPID) AS port,\n\t\t\t @@MAX_CONNECTIONS AS max_connections,\n\t\t\t (SELECT COUNT(*) FROM sys.dm_exec_sessions WHERE is_user_process = 1) AS active_connections\n\t\t`);\n\t\tif (!result.recordset[0]) {\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: \"No connection information returned from server\",\n\t\t\t});\n\t\t}\n\t\tconst info = result.recordset[0] as Record<string, string | number>;\n\t\tconst urlDefaults = parseDatabaseUrl();\n\t\treturn {\n\t\t\thost: String(info.host || urlDefaults.host),\n\t\t\tport: Number(info.port || urlDefaults.port),\n\t\t\tuser: String(info.user),\n\t\t\tdatabase: String(info.database_name ?? \"\"),\n\t\t\tversion: String(info.version),\n\t\t\tactive_connections: Number(info.active_connections ?? 0),\n\t\t\tmax_connections: Number(info.max_connections),\n\t\t};\n\t}\n\n\t// --- Tables ---\n\n\tasync getTablesList(db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst result = await pool.request().query(`\n\t\t\tSELECT table_name AS tableName\n\t\t\tFROM information_schema.tables\n\t\t\tWHERE table_catalog = DB_NAME()\n\t\t\t AND table_type = 'BASE TABLE'\n\t\t\t AND table_schema = 'dbo'\n\t\t\tORDER BY table_name\n\t\t`);\n\t\tif (!result.recordset || result.recordset.length === 0) return [];\n\n\t\treturn Promise.all(\n\t\t\t(result.recordset as Array<{ tableName: string }>).map(async (table) => {\n\t\t\t\tconst countResult = await pool\n\t\t\t\t\t.request()\n\t\t\t\t\t.query(`SELECT COUNT(*) as count FROM [${table.tableName}]`);\n\t\t\t\treturn {\n\t\t\t\t\ttableName: table.tableName,\n\t\t\t\t\trowCount: (countResult.recordset[0] as { count: number })?.count ?? 0,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\t}\n\n\tasync createTable({\n\t\ttableData,\n\t\tdb,\n\t}: {\n\t\ttableData: CreateTableSchemaType;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<void> {\n\t\tconst { tableName, fields, foreignKeys } = tableData;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst columnDefs = fields.map((field: FieldDataType) => {\n\t\t\tconst mappedType = mapColumnTypeToMssql(field.columnType, field.isArray ?? false);\n\t\t\tlet colDef = `[${field.columnName}] ${mappedType}`;\n\t\t\tif (!field.isNullable && !field.isPrimaryKey) colDef += \" NOT NULL\";\n\t\t\tif (field.defaultValue && !mappedType.includes(\"IDENTITY\")) {\n\t\t\t\tconst dv = formatMssqlDefaultValue(field.defaultValue, mappedType);\n\t\t\t\tif (dv !== null) colDef += ` DEFAULT ${dv}`;\n\t\t\t}\n\t\t\treturn colDef;\n\t\t});\n\n\t\tconst constraintDefs: string[] = [];\n\t\tconst primaryKeyFields = fields.filter((f: FieldDataType) => f.isPrimaryKey);\n\t\tif (primaryKeyFields.length > 0) {\n\t\t\tconstraintDefs.push(\n\t\t\t\t`PRIMARY KEY (${primaryKeyFields.map((f: FieldDataType) => `[${f.columnName}]`).join(\", \")})`,\n\t\t\t);\n\t\t}\n\t\tfor (const field of fields as FieldDataType[]) {\n\t\t\tif (field.isUnique && !field.isPrimaryKey) {\n\t\t\t\tconstraintDefs.push(`UNIQUE ([${field.columnName}])`);\n\t\t\t}\n\t\t}\n\n\t\tconst fkDefs =\n\t\t\tforeignKeys?.map((fk: ForeignKeyDataType) => {\n\t\t\t\tconst name = `FK_${tableName}_${fk.columnName}`;\n\t\t\t\treturn `CONSTRAINT [${name}] FOREIGN KEY ([${fk.columnName}]) REFERENCES [${fk.referencedTable}] ([${fk.referencedColumn}]) ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}`;\n\t\t\t}) ?? [];\n\n\t\tawait pool\n\t\t\t.request()\n\t\t\t.query(\n\t\t\t\t`CREATE TABLE [${tableName}] (\\n\\t\\t\\t${[...columnDefs, ...constraintDefs, ...fkDefs].join(\",\\n\\t\\t\\t\")}\\n\\t\\t)`,\n\t\t\t);\n\t}\n\n\tasync deleteTable(params: DeleteTableParams): Promise<DeleteTableResult> {\n\t\tconst { tableName, db, cascade } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst tableCheck = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.TABLES\n\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND TABLE_SCHEMA = 'dbo'\n\t\t\t`);\n\t\tif (Number(tableCheck.recordset[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\n\t\tconst rowCount = await this.getTableRowCount(tableName, db);\n\n\t\tif (!cascade) {\n\t\t\tconst relatedRecords = await this.getRelatedRecordsForTable(tableName, db);\n\t\t\tif (relatedRecords.length > 0) {\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tif (cascade) {\n\t\t\t\tconst fkConstraints = await this.getForeignKeyReferences(tableName, db);\n\t\t\t\tfor (const fk of fkConstraints) {\n\t\t\t\t\tawait pool\n\t\t\t\t\t\t.request()\n\t\t\t\t\t\t.query(\n\t\t\t\t\t\t\t`ALTER TABLE [${fk.referencingTable}] DROP CONSTRAINT [${fk.constraintName}]`,\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait pool.request().query(`DROP TABLE [${tableName}]`);\n\t\t\treturn { deletedCount: rowCount, fkViolation: false, relatedRecords: [] };\n\t\t} catch (error: unknown) {\n\t\t\tconst mssqlError = error as { number?: number };\n\t\t\tif (mssqlError.number === MSSQL_FK_DEPENDENCY) {\n\t\t\t\tconst relatedRecords = await this.getRelatedRecordsForTable(tableName, db);\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to delete table \"${tableName}\"` });\n\t\t}\n\t}\n\n\tasync renameTable(params: RenameTableParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, newTableName, db } = params;\n\t\t\tthis.assertDifferentTableName(tableName, newTableName);\n\t\t\tconst pool = await getMssqlPool(db);\n\n\t\t\tawait this.assertTableExists(pool, tableName);\n\n\t\t\tconst targetCheck = await pool\n\t\t\t\t.request()\n\t\t\t\t.input(\"tableName\", newTableName)\n\t\t\t\t.query(`\n\t\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.TABLES\n\t\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND TABLE_SCHEMA = 'dbo'\n\t\t\t\t`);\n\t\t\tif (Number(targetCheck.recordset[0]?.cnt ?? 0) > 0) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Table \"${newTableName}\" already exists`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait pool\n\t\t\t\t.request()\n\t\t\t\t.input(\"oldName\", tableName)\n\t\t\t\t.input(\"newName\", newTableName)\n\t\t\t\t.query(\"EXEC sp_rename @oldName, @newName\");\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getTableSchema({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst tableCheck = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.TABLES\n\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND TABLE_SCHEMA = 'dbo'\n\t\t\t`);\n\t\tif (Number(tableCheck.recordset[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\n\t\tconst schemaResult = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT\n\t\t\t\t c.COLUMN_NAME,\n\t\t\t\t c.DATA_TYPE,\n\t\t\t\t c.CHARACTER_MAXIMUM_LENGTH,\n\t\t\t\t c.NUMERIC_PRECISION,\n\t\t\t\t c.NUMERIC_SCALE,\n\t\t\t\t c.IS_NULLABLE,\n\t\t\t\t c.COLUMN_DEFAULT,\n\t\t\t\t CASE\n\t\t\t\t WHEN pk.COLUMN_NAME IS NOT NULL THEN 'PRIMARY KEY'\n\t\t\t\t WHEN fk.COLUMN_NAME IS NOT NULL THEN 'FOREIGN KEY'\n\t\t\t\t ELSE ''\n\t\t\t\t END AS KEY_TYPE\n\t\t\t\tFROM INFORMATION_SCHEMA.COLUMNS c\n\t\t\t\tLEFT JOIN (\n\t\t\t\t SELECT ku.TABLE_SCHEMA, ku.TABLE_NAME, ku.COLUMN_NAME\n\t\t\t\t FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc\n\t\t\t\t JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku\n\t\t\t\t ON tc.CONSTRAINT_NAME = ku.CONSTRAINT_NAME\n\t\t\t\t WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY'\n\t\t\t\t) pk ON c.TABLE_SCHEMA = pk.TABLE_SCHEMA\n\t\t\t\t AND c.TABLE_NAME = pk.TABLE_NAME\n\t\t\t\t AND c.COLUMN_NAME = pk.COLUMN_NAME\n\t\t\t\tLEFT JOIN (\n\t\t\t\t SELECT ku.TABLE_SCHEMA, ku.TABLE_NAME, ku.COLUMN_NAME\n\t\t\t\t FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc\n\t\t\t\t JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku\n\t\t\t\t ON rc.CONSTRAINT_NAME = ku.CONSTRAINT_NAME\n\t\t\t\t) fk ON c.TABLE_SCHEMA = fk.TABLE_SCHEMA\n\t\t\t\t AND c.TABLE_NAME = fk.TABLE_NAME\n\t\t\t\t AND c.COLUMN_NAME = fk.COLUMN_NAME\n\t\t\t\tWHERE c.TABLE_CATALOG = DB_NAME()\n\t\t\t\t AND c.TABLE_NAME = @tableName\n\t\t\t\t AND c.TABLE_SCHEMA = 'dbo'\n\t\t\t\tORDER BY c.ORDINAL_POSITION\n\t\t\t`);\n\n\t\tif (!schemaResult.recordset || schemaResult.recordset.length === 0) {\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to retrieve schema for table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\tconst columns = (\n\t\t\tschemaResult.recordset as Array<{\n\t\t\t\tCOLUMN_NAME: string;\n\t\t\t\tDATA_TYPE: string;\n\t\t\t\tCHARACTER_MAXIMUM_LENGTH: number | null;\n\t\t\t\tNUMERIC_PRECISION: number | null;\n\t\t\t\tNUMERIC_SCALE: number | null;\n\t\t\t\tIS_NULLABLE: string;\n\t\t\t\tCOLUMN_DEFAULT: string | null;\n\t\t\t}>\n\t\t).map((col) => {\n\t\t\tlet colDef = ` [${col.COLUMN_NAME}] ${col.DATA_TYPE}`;\n\t\t\tif (col.CHARACTER_MAXIMUM_LENGTH) {\n\t\t\t\tcolDef +=\n\t\t\t\t\tcol.CHARACTER_MAXIMUM_LENGTH === -1 ? \"(MAX)\" : `(${col.CHARACTER_MAXIMUM_LENGTH})`;\n\t\t\t} else if (col.NUMERIC_PRECISION !== null && col.NUMERIC_SCALE !== null) {\n\t\t\t\tcolDef += `(${col.NUMERIC_PRECISION},${col.NUMERIC_SCALE})`;\n\t\t\t} else if (col.NUMERIC_PRECISION !== null) {\n\t\t\t\tcolDef += `(${col.NUMERIC_PRECISION})`;\n\t\t\t}\n\t\t\tcolDef += col.IS_NULLABLE === \"YES\" ? \" NULL\" : \" NOT NULL\";\n\t\t\tif (col.COLUMN_DEFAULT) colDef += ` DEFAULT ${col.COLUMN_DEFAULT}`;\n\t\t\treturn colDef;\n\t\t});\n\n\t\treturn `CREATE TABLE [${tableName}] (\\n${columns.join(\",\\n\")}\\n)`;\n\t}\n\n\t// --- Columns ---\n\n\tasync getTableColumns({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst result = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT\n\t\t\t\t c.COLUMN_NAME AS columnName,\n\t\t\t\t c.DATA_TYPE AS dataType,\n\t\t\t\t CASE WHEN c.IS_NULLABLE = 'YES' THEN 1 ELSE 0 END AS isNullable,\n\t\t\t\t c.COLUMN_DEFAULT AS columnDefault,\n\t\t\t\t CASE WHEN pk.COLUMN_NAME IS NOT NULL THEN 1 ELSE 0 END AS isPrimaryKey,\n\t\t\t\t CASE WHEN fk.COLUMN_NAME IS NOT NULL THEN 1 ELSE 0 END AS isForeignKey,\n\t\t\t\t fk.REFERENCED_TABLE_NAME AS referencedTable,\n\t\t\t\t fk.REFERENCED_COLUMN_NAME AS referencedColumn\n\t\t\t\tFROM INFORMATION_SCHEMA.COLUMNS c\n\t\t\t\tLEFT JOIN (\n\t\t\t\t SELECT ku.TABLE_SCHEMA, ku.TABLE_NAME, ku.COLUMN_NAME\n\t\t\t\t FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc\n\t\t\t\t JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku\n\t\t\t\t ON tc.CONSTRAINT_NAME = ku.CONSTRAINT_NAME\n\t\t\t\t AND tc.TABLE_SCHEMA = ku.TABLE_SCHEMA\n\t\t\t\t AND tc.TABLE_NAME = ku.TABLE_NAME\n\t\t\t\t WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY'\n\t\t\t\t) pk ON c.TABLE_SCHEMA = pk.TABLE_SCHEMA\n\t\t\t\t AND c.TABLE_NAME = pk.TABLE_NAME\n\t\t\t\t AND c.COLUMN_NAME = pk.COLUMN_NAME\n\t\t\t\tLEFT JOIN (\n\t\t\t\t SELECT ku.TABLE_SCHEMA, ku.TABLE_NAME, ku.COLUMN_NAME,\n\t\t\t\t ku2.TABLE_NAME AS REFERENCED_TABLE_NAME,\n\t\t\t\t ku2.COLUMN_NAME AS REFERENCED_COLUMN_NAME\n\t\t\t\t FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc\n\t\t\t\t JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku\n\t\t\t\t ON rc.CONSTRAINT_NAME = ku.CONSTRAINT_NAME AND rc.CONSTRAINT_SCHEMA = ku.TABLE_SCHEMA\n\t\t\t\t JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku2\n\t\t\t\t ON rc.UNIQUE_CONSTRAINT_NAME = ku2.CONSTRAINT_NAME AND rc.UNIQUE_CONSTRAINT_SCHEMA = ku2.TABLE_SCHEMA\n\t\t\t\t) fk ON c.TABLE_SCHEMA = fk.TABLE_SCHEMA\n\t\t\t\t AND c.TABLE_NAME = fk.TABLE_NAME\n\t\t\t\t AND c.COLUMN_NAME = fk.COLUMN_NAME\n\t\t\t\tWHERE c.TABLE_CATALOG = DB_NAME()\n\t\t\t\t AND c.TABLE_NAME = @tableName\n\t\t\t\t AND c.TABLE_SCHEMA = 'dbo'\n\t\t\t\tORDER BY c.ORDINAL_POSITION\n\t\t\t`);\n\n\t\tif (!result.recordset || result.recordset.length === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\n\t\tconst checkResult = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT cc.COLUMN_NAME AS columnName, chk.CHECK_CLAUSE AS checkClause\n\t\t\t\tFROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS chk\n\t\t\t\tJOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cc\n\t\t\t\t ON chk.CONSTRAINT_NAME = cc.CONSTRAINT_NAME AND cc.TABLE_SCHEMA = 'dbo'\n\t\t\t\tWHERE cc.TABLE_NAME = @tableName AND cc.TABLE_CATALOG = DB_NAME()\n\t\t\t`);\n\n\t\tconst checkEnumMap = new Map<string, string[]>();\n\t\tfor (const row of checkResult.recordset as { columnName: string; checkClause: string }[]) {\n\t\t\tconst values = this.parseCheckConstraintValues(row.checkClause);\n\t\t\tif (values) checkEnumMap.set(row.columnName, values);\n\t\t}\n\n\t\treturn (\n\t\t\tresult.recordset as Array<{\n\t\t\t\tcolumnName: string;\n\t\t\t\tdataType: string;\n\t\t\t\tisNullable: number;\n\t\t\t\tcolumnDefault: string | null;\n\t\t\t\tisPrimaryKey: number;\n\t\t\t\tisForeignKey: number;\n\t\t\t\treferencedTable: string | null;\n\t\t\t\treferencedColumn: string | null;\n\t\t\t}>\n\t\t).map((r) => {\n\t\t\tconst enumValues = checkEnumMap.get(r.columnName) ?? null;\n\t\t\treturn {\n\t\t\t\tcolumnName: r.columnName,\n\t\t\t\tdataType: enumValues ? \"enum\" : mapMssqlToDataType(r.dataType),\n\t\t\t\tdataTypeLabel: enumValues ? \"enum\" : standardizeMssqlDataTypeLabel(r.dataType),\n\t\t\t\tisNullable: Boolean(r.isNullable),\n\t\t\t\tcolumnDefault: r.columnDefault ?? null,\n\t\t\t\tisPrimaryKey: Boolean(r.isPrimaryKey),\n\t\t\t\tisForeignKey: Boolean(r.isForeignKey),\n\t\t\t\treferencedTable: r.referencedTable ?? null,\n\t\t\t\treferencedColumn: r.referencedColumn ?? null,\n\t\t\t\tenumValues,\n\t\t\t};\n\t\t});\n\t}\n\n\tasync addColumn(params: AddColumnParamsSchemaType): Promise<void> {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tcolumnName,\n\t\t\tcolumnType,\n\t\t\tdefaultValue,\n\t\t\tisPrimaryKey,\n\t\t\tisNullable,\n\t\t\tisUnique,\n\t\t\tisIdentity,\n\t\t\tdb,\n\t\t} = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\n\t\tconst colCheck = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.input(\"columnName\", columnName)\n\t\t\t.query(`\n\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.COLUMNS\n\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND COLUMN_NAME = @columnName AND TABLE_SCHEMA = 'dbo'\n\t\t\t`);\n\t\tif (Number(colCheck.recordset[0]?.cnt ?? 0) > 0) {\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${columnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\tconst colDef = buildMssqlColumnDefinition(\n\t\t\t{ columnName, columnType, defaultValue, isPrimaryKey, isNullable, isUnique, isIdentity },\n\t\t\t{ includePrimaryKey: true, includeUnique: true },\n\t\t);\n\t\tawait pool.request().query(`ALTER TABLE [${tableName}] ADD ${colDef}`);\n\t}\n\n\tasync deleteColumn(params: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\tconst { tableName, columnName, db } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\t\tawait this.assertColumnExists(pool, tableName, columnName);\n\n\t\tconst result = await pool\n\t\t\t.request()\n\t\t\t.query(`ALTER TABLE [${tableName}] DROP COLUMN [${columnName}]`);\n\t\treturn { deletedCount: result.rowsAffected[0] ?? 1 };\n\t}\n\n\tasync alterColumn(params: AlterColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, columnType, isNullable, defaultValue, db } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\t\tawait this.assertColumnExists(pool, tableName, columnName);\n\n\t\tconst defaultConstraintResult = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.input(\"columnName\", columnName)\n\t\t\t.query(`\n\t\t\t\tSELECT dc.name AS constraint_name\n\t\t\t\tFROM sys.default_constraints dc\n\t\t\t\tJOIN sys.columns c\n\t\t\t\t ON dc.parent_object_id = c.object_id AND dc.parent_column_id = c.column_id\n\t\t\t\tWHERE OBJECT_NAME(dc.parent_object_id) = @tableName AND c.name = @columnName\n\t\t\t`);\n\t\tconst constraintName = defaultConstraintResult.recordset[0]?.constraint_name as\n\t\t\t| string\n\t\t\t| undefined;\n\t\tif (constraintName) {\n\t\t\tawait pool\n\t\t\t\t.request()\n\t\t\t\t.query(`ALTER TABLE [${tableName}] DROP CONSTRAINT [${constraintName}]`);\n\t\t}\n\n\t\tconst nullability = isNullable ? \"NULL\" : \"NOT NULL\";\n\t\tawait pool\n\t\t\t.request()\n\t\t\t.query(\n\t\t\t\t`ALTER TABLE [${tableName}] ALTER COLUMN [${columnName}] ${columnType} ${nullability}`,\n\t\t\t);\n\n\t\tif (defaultValue?.trim()) {\n\t\t\tawait pool\n\t\t\t\t.request()\n\t\t\t\t.query(\n\t\t\t\t\t`ALTER TABLE [${tableName}] ADD DEFAULT ${defaultValue.trim()} FOR [${columnName}]`,\n\t\t\t\t);\n\t\t}\n\t}\n\n\tasync renameColumn(params: RenameColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, newColumnName, db } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\t\tawait this.assertColumnExists(pool, tableName, columnName);\n\n\t\tconst newColCheck = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.input(\"columnName\", newColumnName)\n\t\t\t.query(`\n\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.COLUMNS\n\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND COLUMN_NAME = @columnName AND TABLE_SCHEMA = 'dbo'\n\t\t\t`);\n\t\tif (Number(newColCheck.recordset[0]?.cnt ?? 0) > 0) {\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${newColumnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\tawait pool\n\t\t\t.request()\n\t\t\t.query(`EXEC sp_rename '${tableName}.${columnName}', '${newColumnName}', 'COLUMN'`);\n\t}\n\n\t// --- Records ---\n\n\tasync addRecord({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\tconst { tableName, data } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\tconst identityResult = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(\n\t\t\t\t`SELECT name FROM sys.columns WHERE object_id = OBJECT_ID(@tableName) AND is_identity = 1`,\n\t\t\t);\n\t\tconst identityColumns = new Set(\n\t\t\t(identityResult.recordset as { name: string }[]).map((r) => r.name),\n\t\t);\n\n\t\tconst columns = Object.keys(data).filter((col) => !identityColumns.has(col));\n\t\tconst values = columns.map((col) => {\n\t\t\tconst value = data[col];\n\t\t\tif (booleanColumns.has(col) && typeof value === \"string\") {\n\t\t\t\treturn value === \"true\" ? 1 : 0;\n\t\t\t}\n\t\t\treturn value;\n\t\t});\n\n\t\tconst columnNames = columns.map((col) => `[${col}]`).join(\", \");\n\t\tconst paramNames = columns.map((_col, idx) => `@param${idx}`).join(\", \");\n\n\t\tconst request = pool.request();\n\t\tcolumns.forEach((_col, idx) => {\n\t\t\trequest.input(`param${idx}`, values[idx]);\n\t\t});\n\n\t\tconst result = await request.query(\n\t\t\t`INSERT INTO [${tableName}] (${columnNames}) VALUES (${paramNames})`,\n\t\t);\n\t\tif (result.rowsAffected[0] === 0) {\n\t\t\tthrow new HTTPException(500, { message: `Failed to insert record into \"${tableName}\"` });\n\t\t}\n\t\treturn { insertedCount: result.rowsAffected[0] ?? 0 };\n\t}\n\n\tasync updateRecords({\n\t\tparams,\n\t\tdb,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\tconst { tableName } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\tconst keyColumns = this.resolveKeyColumns(params);\n\t\tconst groups = this.groupUpdatesByKey(params, keyColumns);\n\n\t\tconst transaction = pool.transaction();\n\t\tawait transaction.begin();\n\n\t\ttry {\n\t\t\tlet total = 0;\n\t\t\tfor (const { keyValues, rowUpdates } of groups) {\n\t\t\t\tconst request = transaction.request();\n\t\t\t\tconst setClauses = rowUpdates.map((u, idx) => `[${u.columnName}] = @value${idx}`);\n\n\t\t\t\trowUpdates.forEach((u, idx) => {\n\t\t\t\t\tlet value = u.value;\n\t\t\t\t\tif (value !== null && typeof value === \"object\") value = JSON.stringify(value);\n\t\t\t\t\tif (booleanColumns.has(u.columnName) && typeof value === \"string\") {\n\t\t\t\t\t\tvalue = value === \"true\" ? 1 : 0;\n\t\t\t\t\t}\n\t\t\t\t\trequest.input(`value${idx}`, value);\n\t\t\t\t});\n\t\t\t\tkeyValues.forEach((value, idx) => {\n\t\t\t\t\trequest.input(`pkValue${idx}`, value);\n\t\t\t\t});\n\t\t\t\tconst whereClauses = keyColumns.map((column, idx) => `[${column}] = @pkValue${idx}`);\n\n\t\t\t\tconst result = await request.query(\n\t\t\t\t\t`UPDATE [${tableName}] SET ${setClauses.join(\", \")} WHERE ${whereClauses.join(\" AND \")}`,\n\t\t\t\t);\n\t\t\t\tif (result.rowsAffected[0] === 0) {\n\t\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\t\tmessage: `Record with ${this.describeKey(keyColumns, keyValues)} not found in table \"${tableName}\"`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\ttotal += result.rowsAffected[0] ?? 0;\n\t\t\t}\n\t\t\tawait transaction.commit();\n\t\t\treturn { updatedCount: total };\n\t\t} catch (error) {\n\t\t\tawait transaction.rollback();\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to update records in \"${tableName}\"` });\n\t\t}\n\t}\n\n\tasync deleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst transaction = pool.transaction();\n\t\tawait transaction.begin();\n\n\t\ttry {\n\t\t\tconst request = transaction.request();\n\t\t\tpkValues.forEach((value, idx) => {\n\t\t\t\trequest.input(`pk${idx}`, value);\n\t\t\t});\n\t\t\tconst paramList = pkValues.map((_, idx) => `@pk${idx}`).join(\", \");\n\n\t\t\tconst result = await request.query(\n\t\t\t\t`DELETE FROM [${tableName}] WHERE [${pkColumn}] IN (${paramList})`,\n\t\t\t);\n\t\t\tawait transaction.commit();\n\t\t\treturn {\n\t\t\t\tdeletedCount: result.rowsAffected[0] ?? 0,\n\t\t\t\tfkViolation: false,\n\t\t\t\trelatedRecords: [],\n\t\t\t};\n\t\t} catch (error: unknown) {\n\t\t\tawait transaction.rollback();\n\t\t\tconst mssqlError = error as { number?: number };\n\t\t\tif (mssqlError.number === MSSQL_FK_VIOLATION) {\n\t\t\t\tconst relatedRecords = await this.getRelatedRecords(tableName, primaryKeys, db);\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to delete records from \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\tasync forceDeleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<{ deletedCount: number }> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst transaction = pool.transaction();\n\t\tawait transaction.begin();\n\n\t\ttry {\n\t\t\tconst fkConstraints = await this.getForeignKeyReferences(tableName, db);\n\t\t\tlet totalRelated = 0;\n\t\t\tconst deletedTables = new Set<string>();\n\t\t\tconst visited = new Set<string>();\n\n\t\t\tconst deleteRelatedRecursively = async (\n\t\t\t\ttargetTable: string,\n\t\t\t\ttargetColumn: string,\n\t\t\t\tvalues: unknown[],\n\t\t\t\tvisitedSet: Set<string>,\n\t\t\t) => {\n\t\t\t\tconst key = `${targetTable}.${targetColumn}`;\n\t\t\t\tif (visitedSet.has(key)) return;\n\t\t\t\tvisitedSet.add(key);\n\n\t\t\t\tconst nestedFks = await this.getForeignKeyReferences(targetTable, db);\n\t\t\t\tfor (const nestedFk of nestedFks) {\n\t\t\t\t\tconst selectRequest = transaction.request();\n\t\t\t\t\tvalues.forEach((val, idx) => {\n\t\t\t\t\t\tselectRequest.input(`val${idx}`, val);\n\t\t\t\t\t});\n\t\t\t\t\tconst selectParamList = values.map((_, idx) => `@val${idx}`).join(\", \");\n\n\t\t\t\t\tconst selectResult = await selectRequest.query(\n\t\t\t\t\t\t`SELECT [${nestedFk.referencedColumn}] FROM [${targetTable}] WHERE [${targetColumn}] IN (${selectParamList})`,\n\t\t\t\t\t);\n\t\t\t\t\tconst nestedValues = (selectResult.recordset as Record<string, unknown>[]).map(\n\t\t\t\t\t\t(row) => row[nestedFk.referencedColumn],\n\t\t\t\t\t);\n\t\t\t\t\tif (nestedValues.length > 0) {\n\t\t\t\t\t\tawait deleteRelatedRecursively(\n\t\t\t\t\t\t\tnestedFk.referencingTable,\n\t\t\t\t\t\t\tnestedFk.referencingColumn,\n\t\t\t\t\t\t\tnestedValues,\n\t\t\t\t\t\t\tvisitedSet,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst deleteRequest = transaction.request();\n\t\t\t\tvalues.forEach((val, idx) => {\n\t\t\t\t\tdeleteRequest.input(`delVal${idx}`, val);\n\t\t\t\t});\n\t\t\t\tconst deleteParamList = values.map((_, idx) => `@delVal${idx}`).join(\", \");\n\n\t\t\t\tconst deleteResult = await deleteRequest.query(\n\t\t\t\t\t`DELETE FROM [${targetTable}] WHERE [${targetColumn}] IN (${deleteParamList})`,\n\t\t\t\t);\n\t\t\t\ttotalRelated += deleteResult.rowsAffected[0] ?? 0;\n\t\t\t\tdeletedTables.add(targetTable);\n\t\t\t};\n\n\t\t\tfor (const constraint of fkConstraints) {\n\t\t\t\tif (!deletedTables.has(constraint.referencingTable)) {\n\t\t\t\t\tawait deleteRelatedRecursively(\n\t\t\t\t\t\tconstraint.referencingTable,\n\t\t\t\t\t\tconstraint.referencingColumn,\n\t\t\t\t\t\tpkValues,\n\t\t\t\t\t\tvisited,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst mainRequest = transaction.request();\n\t\t\tpkValues.forEach((val, idx) => {\n\t\t\t\tmainRequest.input(`mainPk${idx}`, val);\n\t\t\t});\n\t\t\tconst mainParamList = pkValues.map((_, idx) => `@mainPk${idx}`).join(\", \");\n\n\t\t\tconst result = await mainRequest.query(\n\t\t\t\t`DELETE FROM [${tableName}] WHERE [${pkColumn}] IN (${mainParamList})`,\n\t\t\t);\n\t\t\tawait transaction.commit();\n\t\t\treturn { deletedCount: (result.rowsAffected[0] ?? 0) + totalRelated };\n\t\t} catch (error) {\n\t\t\tawait transaction.rollback();\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to force delete records from \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\tasync bulkInsertRecords({\n\t\ttableName,\n\t\trecords,\n\t\tdb,\n\t}: BulkInsertRecordsParams): Promise<BulkInsertResult> {\n\t\tif (!records || records.length === 0) {\n\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\t\t}\n\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst transaction = pool.transaction();\n\n\t\ttry {\n\t\t\tconst columns = Object.keys(records[0]);\n\t\t\tconst columnNames = columns.map((col) => `[${col}]`).join(\", \");\n\t\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\t\tawait transaction.begin();\n\n\t\t\tfor (let i = 0; i < records.length; i++) {\n\t\t\t\tconst record = records[i];\n\t\t\t\tconst request = transaction.request();\n\t\t\t\tconst values = columns.map((col) => {\n\t\t\t\t\tconst value = record[col];\n\t\t\t\t\tif (booleanColumns.has(col) && typeof value === \"string\") {\n\t\t\t\t\t\treturn value === \"true\" ? 1 : 0;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t});\n\n\t\t\t\tconst paramNames = columns.map((_, idx) => `@p${i}_${idx}`).join(\", \");\n\t\t\t\tcolumns.forEach((_col, idx) => {\n\t\t\t\t\trequest.input(`p${i}_${idx}`, values[idx]);\n\t\t\t\t});\n\n\t\t\t\ttry {\n\t\t\t\t\tawait request.query(\n\t\t\t\t\t\t`INSERT INTO [${tableName}] (${columnNames}) VALUES (${paramNames})`,\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new HTTPException(500, {\n\t\t\t\t\t\tmessage: `Failed to insert record ${i + 1}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait transaction.commit();\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `Successfully inserted ${records.length} record${records.length !== 1 ? \"s\" : \"\"}`,\n\t\t\t\tsuccessCount: records.length,\n\t\t\t\tfailureCount: 0,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tawait transaction.rollback();\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to bulk insert records into \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\t// --- Query ---\n\n\tasync executeQuery({\n\t\tquery,\n\t\tdb,\n\t}: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tif (!query?.trim()) throw new HTTPException(400, { message: \"Query is required\" });\n\n\t\tconst cleanedQuery = query.trim().replace(/;+$/, \"\");\n\t\tconst start = performance.now();\n\t\tconst result = await pool.request().query(cleanedQuery);\n\t\tconst duration = performance.now() - start;\n\n\t\tif (result.recordset) {\n\t\t\tconst rows = result.recordset as Record<string, unknown>[];\n\t\t\tconst columns = result.recordset.columns\n\t\t\t\t? Object.keys(result.recordset.columns)\n\t\t\t\t: Object.keys(rows[0] ?? {});\n\t\t\treturn {\n\t\t\t\tcolumns,\n\t\t\t\trows,\n\t\t\t\trowCount: rows.length,\n\t\t\t\tduration,\n\t\t\t\tmessage: rows.length === 0 ? \"OK\" : undefined,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tcolumns: [],\n\t\t\trows: [],\n\t\t\trowCount: result.rowsAffected[0] ?? 0,\n\t\t\tduration,\n\t\t\tmessage: `OK — ${result.rowsAffected[0] ?? 0} row(s) affected`,\n\t\t};\n\t}\n\n\t// =========================================================\n\t// Private helpers\n\t// =========================================================\n\n\tprivate async getForeignKeyReferences(\n\t\ttableName: string,\n\t\tdb: string,\n\t): Promise<ForeignKeyConstraint[]> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst result = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT\n\t\t\t\t fk.name AS constraint_name,\n\t\t\t\t OBJECT_NAME(fk.parent_object_id) AS referencing_table,\n\t\t\t\t COL_NAME(fkc.parent_object_id, fkc.parent_column_id) AS referencing_column,\n\t\t\t\t OBJECT_NAME(fk.referenced_object_id) AS referenced_table,\n\t\t\t\t COL_NAME(fkc.referenced_object_id, fkc.referenced_column_id) AS referenced_column\n\t\t\t\tFROM sys.foreign_keys fk\n\t\t\t\tINNER JOIN sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id\n\t\t\t\tWHERE OBJECT_NAME(fk.referenced_object_id) = @tableName\n\t\t\t`);\n\t\treturn (result.recordset as FkConstraintRow[]).map((row) => ({\n\t\t\tconstraintName: row.constraint_name,\n\t\t\treferencingTable: row.referencing_table,\n\t\t\treferencingColumn: row.referencing_column,\n\t\t\treferencedTable: row.referenced_table,\n\t\t\treferencedColumn: row.referenced_column,\n\t\t}));\n\t}\n\n\tprivate async getRelatedRecordsForTable(\n\t\ttableName: string,\n\t\tdb: string,\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getForeignKeyReferences(tableName, db);\n\t\tif (fks.length === 0) return [];\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst results: RelatedRecord[] = [];\n\t\tfor (const fk of fks) {\n\t\t\tconst relatedResult = await pool\n\t\t\t\t.request()\n\t\t\t\t.query(`SELECT TOP 100 * FROM [${fk.referencingTable}]`);\n\t\t\tif (relatedResult.recordset.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: relatedResult.recordset as Record<string, unknown>[],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate async getRelatedRecords(\n\t\ttableName: string,\n\t\tprimaryKeys: DeleteRecordSchemaType[\"primaryKeys\"],\n\t\tdb: string,\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getForeignKeyReferences(tableName, db);\n\t\tif (fks.length === 0) return [];\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst results: RelatedRecord[] = [];\n\n\t\tconst constraintsByTable = new Map<string, ForeignKeyConstraint[]>();\n\t\tfor (const fk of fks) {\n\t\t\tconst key = `${fk.referencingTable}.${fk.referencingColumn}`;\n\t\t\tif (!constraintsByTable.has(key)) constraintsByTable.set(key, []);\n\t\t\tconstraintsByTable.get(key)?.push(fk);\n\t\t}\n\n\t\tfor (const [, constraints] of constraintsByTable) {\n\t\t\tconst fk = constraints[0];\n\t\t\tif (!fk) continue;\n\t\t\tconst matchingPk = primaryKeys.find((pk) => pk.columnName === fk.referencedColumn);\n\t\t\tif (!matchingPk) continue;\n\n\t\t\tconst request = pool.request();\n\t\t\tpkValues.forEach((value, idx) => {\n\t\t\t\trequest.input(`pk${idx}`, value);\n\t\t\t});\n\t\t\tconst paramList = pkValues.map((_, idx) => `@pk${idx}`).join(\", \");\n\n\t\t\tconst relatedResult = await request.query(\n\t\t\t\t`SELECT TOP 100 * FROM [${fk.referencingTable}] WHERE [${fk.referencingColumn}] IN (${paramList})`,\n\t\t\t);\n\t\t\tif (relatedResult.recordset.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: relatedResult.recordset as Record<string, unknown>[],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate async getTableRowCount(tableName: string, db: string): Promise<number> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst result = await pool.request().query(`SELECT COUNT(*) as count FROM [${tableName}]`);\n\t\treturn Number(result.recordset[0]?.count ?? 0);\n\t}\n\n\tprivate async getBooleanColumnSet(tableName: string, db: string): Promise<Set<string>> {\n\t\tconst cols = await this.getTableColumns({ tableName, db });\n\t\treturn new Set(cols.filter((c) => c.dataTypeLabel === \"boolean\").map((c) => c.columnName));\n\t}\n\n\tprivate async assertTableExists(pool: MssqlPool, tableName: string): Promise<void> {\n\t\tconst result = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.TABLES\n\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND TABLE_SCHEMA = 'dbo'\n\t\t\t`);\n\t\tif (Number(result.recordset[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\t}\n\n\tprivate async assertColumnExists(\n\t\tpool: MssqlPool,\n\t\ttableName: string,\n\t\tcolumnName: string,\n\t): Promise<void> {\n\t\tconst result = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.input(\"columnName\", columnName)\n\t\t\t.query(`\n\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.COLUMNS\n\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND COLUMN_NAME = @columnName AND TABLE_SCHEMA = 'dbo'\n\t\t\t`);\n\t\tif (Number(result.recordset[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate parseCheckConstraintValues(checkClause: string): string[] | null {\n\t\tconst matches = checkClause.match(/'([^']+)'/g);\n\t\tif (!matches || matches.length === 0) return null;\n\t\treturn matches.map((m) => m.slice(1, -1));\n\t}\n\n\tprivate makeCursor(offset: number): string {\n\t\treturn this.encodeCursor({ values: { _offset: offset }, sortColumns: [\"_offset\"] });\n\t}\n\n\tprivate decodeOffsetCursor(cursor: string): number {\n\t\tconst data = this.decodeCursor(cursor);\n\t\treturn Number(data?.values._offset ?? 0);\n\t}\n}\n","import type { CursorData, FilterType, SortDirection, SortType } from \"@db-studio/shared/types\";\n\nexport function buildWhereClause(filters: FilterType[]): {\n\tclause: string;\n\tvalues: unknown[];\n} {\n\tif (filters.length === 0) return { clause: \"\", values: [] };\n\n\tconst conditions: string[] = [];\n\tconst values: unknown[] = [];\n\n\tfor (const filter of filters) {\n\t\tconst col = `\\`${filter.columnName}\\``;\n\t\tswitch (filter.operator) {\n\t\t\tcase \"=\":\n\t\t\tcase \"!=\":\n\t\t\tcase \">\":\n\t\t\tcase \">=\":\n\t\t\tcase \"<\":\n\t\t\tcase \"<=\":\n\t\t\t\tconditions.push(`${col} ${filter.operator} ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"is\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${col} IS NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} = ?`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"is not\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${col} IS NOT NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} != ?`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"like\":\n\t\t\tcase \"ilike\":\n\t\t\t\tconditions.push(`${col} LIKE ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"not like\":\n\t\t\tcase \"not ilike\":\n\t\t\t\tconditions.push(`${col} NOT LIKE ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (conditions.length === 0) return { clause: \"\", values: [] };\n\treturn { clause: `WHERE ${conditions.join(\" AND \")}`, values };\n}\n\nexport function buildSortClause(sorts: SortType[] | string, order: SortDirection): string {\n\tif (Array.isArray(sorts)) {\n\t\tif (sorts.length === 0) return \"\";\n\t\treturn `ORDER BY ${sorts.map((s) => `\\`${s.columnName}\\` ${s.direction.toUpperCase()}`).join(\", \")}`;\n\t}\n\tif (sorts && typeof sorts === \"string\") {\n\t\treturn `ORDER BY \\`${sorts}\\` ${order?.toUpperCase() || \"ASC\"}`;\n\t}\n\treturn \"\";\n}\n\nexport function buildCursorWhereClause(\n\tcursorData: CursorData,\n\tdirection: SortDirection,\n\tsortDirection: SortDirection,\n): { clause: string; values: unknown[] } {\n\tconst { values, sortColumns } = cursorData;\n\tif (sortColumns.length === 0) return { clause: \"\", values: [] };\n\n\tconst isAscending = sortDirection === \"asc\";\n\tconst isForward = direction === \"asc\";\n\tconst useGreaterThan = isAscending === isForward;\n\tconst operator = useGreaterThan ? \">\" : \"<\";\n\n\tconst columnList = sortColumns.map((col) => `\\`${col}\\``).join(\", \");\n\tconst placeholders = sortColumns.map(() => \"?\").join(\", \");\n\tconst queryValues = sortColumns.map((col) => values[col]);\n\n\treturn {\n\t\tclause: `(${columnList}) ${operator} (${placeholders})`,\n\t\tvalues: queryValues,\n\t};\n}\n\ntype MysqlColumnDefinitionInput = {\n\tcolumnName: string;\n\tcolumnType: string;\n\tdefaultValue?: string | null;\n\tisPrimaryKey?: boolean;\n\tisNullable?: boolean;\n\tisUnique?: boolean;\n\tisIdentity?: boolean;\n\tisArray?: boolean;\n};\n\ntype BuildMysqlColumnDefinitionOptions = {\n\tincludePrimaryKey?: boolean;\n\tincludeUnique?: boolean;\n\tpreserveAutoIncrement?: boolean;\n};\n\nexport function mapColumnTypeToMysql(columnType: string, isArray: boolean): string {\n\tif (isArray) return \"JSON\";\n\tconst normalized = columnType.toLowerCase().trim();\n\tconst typeMap: Record<string, string> = {\n\t\tserial: \"INT AUTO_INCREMENT\",\n\t\tserial4: \"INT AUTO_INCREMENT\",\n\t\tbigserial: \"BIGINT AUTO_INCREMENT\",\n\t\tserial8: \"BIGINT AUTO_INCREMENT\",\n\t\tint: \"INT\",\n\t\tint4: \"INT\",\n\t\tinteger: \"INT\",\n\t\tbigint: \"BIGINT\",\n\t\tint8: \"BIGINT\",\n\t\tsmallint: \"SMALLINT\",\n\t\tint2: \"SMALLINT\",\n\t\tnumeric: \"DECIMAL\",\n\t\tdecimal: \"DECIMAL\",\n\t\treal: \"FLOAT\",\n\t\tfloat4: \"FLOAT\",\n\t\tfloat: \"FLOAT\",\n\t\t\"double precision\": \"DOUBLE\",\n\t\tfloat8: \"DOUBLE\",\n\t\tmoney: \"DECIMAL(19, 4)\",\n\t\tboolean: \"TINYINT(1)\",\n\t\tbool: \"TINYINT(1)\",\n\t\ttext: \"LONGTEXT\",\n\t\tvarchar: \"VARCHAR(255)\",\n\t\t\"character varying\": \"VARCHAR(255)\",\n\t\tchar: \"CHAR(1)\",\n\t\tcharacter: \"CHAR(1)\",\n\t\tbpchar: \"CHAR\",\n\t\tuuid: \"CHAR(36)\",\n\t\tjson: \"JSON\",\n\t\tjsonb: \"JSON\",\n\t\txml: \"LONGTEXT\",\n\t\tdate: \"DATE\",\n\t\ttime: \"TIME\",\n\t\t\"time without time zone\": \"TIME\",\n\t\ttimestamp: \"DATETIME\",\n\t\t\"timestamp without time zone\": \"DATETIME\",\n\t\t\"timestamp with time zone\": \"DATETIME\",\n\t\ttimestamptz: \"DATETIME\",\n\t\tinterval: \"VARCHAR(255)\",\n\t\tbytea: \"LONGBLOB\",\n\t\tinet: \"VARCHAR(45)\",\n\t\tcidr: \"VARCHAR(45)\",\n\t\tmacaddr: \"VARCHAR(17)\",\n\t\tmacaddr8: \"VARCHAR(23)\",\n\t\tpoint: \"POINT\",\n\t\tline: \"LINESTRING\",\n\t\tpolygon: \"POLYGON\",\n\t};\n\treturn typeMap[normalized] || columnType.toUpperCase();\n}\n\nexport function formatMysqlDefaultValue(\n\tdefaultValue: string | null | undefined,\n\tcolumnType: string,\n): string | null {\n\tif (!defaultValue?.trim()) return null;\n\tconst trimmed = defaultValue.trim().toLowerCase();\n\n\tif (trimmed.includes(\"(\") && trimmed.includes(\")\")) {\n\t\tif (trimmed.includes(\"uuid()\")) {\n\t\t\tif (\n\t\t\t\t!columnType.toUpperCase().includes(\"CHAR\") &&\n\t\t\t\t!columnType.toUpperCase().includes(\"TEXT\")\n\t\t\t) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn \"(UUID())\";\n\t\t}\n\t\tif (trimmed.includes(\"current_timestamp\") || trimmed.includes(\"now()\"))\n\t\t\treturn \"(CURRENT_TIMESTAMP)\";\n\t\tif (trimmed.includes(\"current_date\")) return \"(CURRENT_DATE)\";\n\t\treturn `(${defaultValue.trim()})`;\n\t}\n\n\tif (trimmed === \"null\") return \"NULL\";\n\tif (trimmed === \"true\") return \"1\";\n\tif (trimmed === \"false\") return \"0\";\n\treturn defaultValue.trim();\n}\n\nexport function buildMysqlColumnDefinition(\n\tfield: MysqlColumnDefinitionInput,\n\toptions: BuildMysqlColumnDefinitionOptions = {},\n): string {\n\tconst mappedType = mapColumnTypeToMysql(field.columnType, field.isArray ?? false);\n\tlet def = `\\`${field.columnName}\\` ${mappedType}`;\n\n\tif (!field.isNullable && !field.isPrimaryKey) def += \" NOT NULL\";\n\n\tif (field.defaultValue && !mappedType.includes(\"AUTO_INCREMENT\")) {\n\t\tconst dv = formatMysqlDefaultValue(field.defaultValue, mappedType);\n\t\tif (dv !== null) def += ` DEFAULT ${dv}`;\n\t}\n\n\tif (\n\t\t(field.isIdentity || options.preserveAutoIncrement) &&\n\t\t!mappedType.includes(\"AUTO_INCREMENT\")\n\t) {\n\t\tdef += \" AUTO_INCREMENT\";\n\t}\n\n\tif (options.includeUnique && field.isUnique && !field.isPrimaryKey) def += \" UNIQUE\";\n\tif (options.includePrimaryKey && field.isPrimaryKey) def += \" PRIMARY KEY\";\n\n\treturn def;\n}\n","import type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tCursorData,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteRecordSchemaType,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tFieldDataType,\n\tForeignKeyConstraint,\n\tForeignKeyConstraintRow,\n\tForeignKeyDataType,\n\tRelatedRecord,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tSortDirection,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { mapMysqlToDataType, standardizeMysqlDataTypeLabel } from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { FieldPacket, ResultSetHeader, RowDataPacket } from \"mysql2\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getMysqlPool } from \"@/adapters/connections.js\";\nimport { parseDatabaseUrl } from \"@/utils/parse-database-url.js\";\nimport {\n\tbuildCursorWhereClause,\n\tbuildMysqlColumnDefinition,\n\tbuildSortClause,\n\tbuildWhereClause,\n} from \"./mysql.query-builder.js\";\n\ntype MysqlPool = ReturnType<typeof getMysqlPool>;\n\nconst MYSQL_FK_VIOLATION = 1451;\nconst MYSQL_FK_DEPENDENCY = 1217;\n\nexport class MySqlAdapter extends BaseAdapter {\n\t// =========================================================\n\t// Abstract method implementations\n\t// =========================================================\n\n\tprotected async runQuery<T>(db: string, sql: string, values: unknown[]): Promise<T> {\n\t\tconst pool = getMysqlPool(db);\n\t\t// biome-ignore lint/suspicious/noExplicitAny: mysql2 execute doesn't accept unknown[]\n\t\tconst [rows] = await pool.execute(sql, values as any);\n\t\treturn rows as T;\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn `\\`${name}\\``;\n\t}\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\treturn mapMysqlToDataType(nativeType);\n\t}\n\n\tmapFromUniversalType(universalType: string): string {\n\t\tconst map: Record<string, string> = {\n\t\t\ttext: \"LONGTEXT\",\n\t\t\tnumber: \"INT\",\n\t\t\tboolean: \"TINYINT(1)\",\n\t\t\tjson: \"JSON\",\n\t\t\tdate: \"DATETIME\",\n\t\t\tarray: \"JSON\",\n\t\t\tenum: \"TEXT\",\n\t\t};\n\t\treturn map[universalType] ?? \"LONGTEXT\";\n\t}\n\n\tprotected buildTableDataQuery(params: GetTableDataParams): QueryBundle {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tcursor = \"\",\n\t\t\tlimit = 50,\n\t\t\tdirection = \"asc\",\n\t\t\tsort = [],\n\t\t\torder = \"asc\",\n\t\t\tfilters = [],\n\t\t} = params;\n\n\t\tlet sortColumns: string[] = [];\n\t\tlet effectiveSortDirection: SortDirection = order;\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t\teffectiveSortDirection = sort[0].direction;\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\n\t\tconst { clause: filterWhere, values: filterValues } = buildWhereClause(filters);\n\n\t\tlet cursorWhere = \"\";\n\t\tlet cursorValues: unknown[] = [];\n\t\tif (cursor) {\n\t\t\tconst cursorData = this.decodeCursor(cursor);\n\t\t\tif (cursorData) {\n\t\t\t\tconst res = buildCursorWhereClause(cursorData, direction, effectiveSortDirection);\n\t\t\t\tcursorWhere = res.clause;\n\t\t\t\tcursorValues = res.values;\n\t\t\t}\n\t\t}\n\n\t\tlet combinedWhere = \"\";\n\t\tif (filterWhere && cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${filterWhere.replace(/^WHERE\\s+/i, \"\")} AND ${cursorWhere}`;\n\t\t} else if (filterWhere) {\n\t\t\tcombinedWhere = filterWhere;\n\t\t} else if (cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${cursorWhere}`;\n\t\t}\n\n\t\tconst sortClause = buildSortClause(Array.isArray(sort) ? sort : sort, order);\n\t\tlet effectiveSortClause = sortClause;\n\t\tif (direction === \"desc\") {\n\t\t\tif (sortClause) {\n\t\t\t\teffectiveSortClause = sortClause\n\t\t\t\t\t.replace(/\\bASC\\b/gi, \"TEMP_DESC\")\n\t\t\t\t\t.replace(/\\bDESC\\b/gi, \"ASC\")\n\t\t\t\t\t.replace(/TEMP_DESC/g, \"DESC\");\n\t\t\t} else if (sortColumns.length > 0) {\n\t\t\t\teffectiveSortClause = `ORDER BY ${sortColumns.map((col) => `\\`${col}\\` ${effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\"}`).join(\", \")}`;\n\t\t\t}\n\t\t} else if (!sortClause && sortColumns.length > 0) {\n\t\t\teffectiveSortClause = `ORDER BY ${sortColumns.map((col) => `\\`${col}\\` ${effectiveSortDirection.toUpperCase()}`).join(\", \")}`;\n\t\t}\n\n\t\tconst sql = `SELECT * FROM \\`${tableName}\\` ${combinedWhere} ${effectiveSortClause} LIMIT ${limit + 1}`;\n\t\tconst values = [...filterValues, ...cursorValues];\n\t\tconst countSql = `SELECT COUNT(*) as total FROM \\`${tableName}\\` ${filterWhere}`;\n\n\t\treturn { sql, values, countSql, countValues: filterValues };\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn (rawRows as Record<string, unknown>[]).map((row) => this.normalizeRow(row));\n\t}\n\n\tprotected buildCursors(\n\t\tparams: GetTableDataParams,\n\t\trows: NormalizedRow[],\n\t\thasMore: boolean,\n\t): { nextCursor: string | null; prevCursor: string | null } {\n\t\tif (rows.length === 0) return { nextCursor: null, prevCursor: null };\n\n\t\tconst { direction = \"asc\", sort = [], cursor } = params;\n\t\tlet sortColumns: string[] = [];\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\n\t\tconst createCursor = (row: NormalizedRow): string =>\n\t\t\tthis.encodeCursor({\n\t\t\t\tvalues: Object.fromEntries(sortColumns.map((col) => [col, row[col]])),\n\t\t\t\tsortColumns,\n\t\t\t} satisfies CursorData);\n\n\t\tconst firstRow = rows[0];\n\t\tconst lastRow = rows[rows.length - 1];\n\t\tlet nextCursor: string | null = null;\n\t\tlet prevCursor: string | null = null;\n\n\t\tif (direction === \"asc\") {\n\t\t\tif (hasMore) nextCursor = createCursor(lastRow);\n\t\t\tif (cursor) prevCursor = createCursor(firstRow);\n\t\t} else {\n\t\t\tif (cursor) nextCursor = createCursor(lastRow);\n\t\t\tif (hasMore) prevCursor = createCursor(firstRow);\n\t\t}\n\n\t\treturn { nextCursor, prevCursor };\n\t}\n\n\t// =========================================================\n\t// Override getTableData to incorporate primary-key cursor columns\n\t// =========================================================\n\n\toverride async getTableData(params: GetTableDataParams) {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tdb,\n\t\t\tlimit = 50,\n\t\t\tdirection = \"asc\",\n\t\t\tsort = [],\n\t\t\torder = \"asc\",\n\t\t\tcursor,\n\t\t\tfilters = [],\n\t\t} = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tconst pkColumns = await this.getPrimaryKeyColumns(pool, tableName);\n\n\t\tlet sortColumns: string[] = [];\n\t\tlet effectiveSortDirection: SortDirection = order;\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t\teffectiveSortDirection = sort[0].direction;\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\n\t\tconst cursorColumns = [\n\t\t\t...sortColumns,\n\t\t\t...pkColumns.filter((pk) => !sortColumns.includes(pk)),\n\t\t];\n\n\t\tconst { clause: filterWhere, values: filterValues } = buildWhereClause(filters);\n\n\t\tlet cursorWhere = \"\";\n\t\tlet cursorValues: unknown[] = [];\n\t\tif (cursor) {\n\t\t\tconst cursorData = this.decodeCursor(cursor);\n\t\t\tif (cursorData) {\n\t\t\t\tconst res = buildCursorWhereClause(cursorData, direction, effectiveSortDirection);\n\t\t\t\tcursorWhere = res.clause;\n\t\t\t\tcursorValues = res.values;\n\t\t\t}\n\t\t}\n\n\t\tlet combinedWhere = \"\";\n\t\tif (filterWhere && cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${filterWhere.replace(/^WHERE\\s+/i, \"\")} AND ${cursorWhere}`;\n\t\t} else if (filterWhere) {\n\t\t\tcombinedWhere = filterWhere;\n\t\t} else if (cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${cursorWhere}`;\n\t\t}\n\n\t\tconst sortClause = buildSortClause(Array.isArray(sort) ? sort : sort, order);\n\t\tlet effectiveSortClause = sortClause;\n\t\tif (direction === \"desc\") {\n\t\t\tif (sortClause) {\n\t\t\t\teffectiveSortClause = sortClause\n\t\t\t\t\t.replace(/\\bASC\\b/gi, \"TEMP_DESC\")\n\t\t\t\t\t.replace(/\\bDESC\\b/gi, \"ASC\")\n\t\t\t\t\t.replace(/TEMP_DESC/g, \"DESC\");\n\t\t\t} else if (cursorColumns.length > 0) {\n\t\t\t\teffectiveSortClause = `ORDER BY ${cursorColumns.map((col) => `\\`${col}\\` ${effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\"}`).join(\", \")}`;\n\t\t\t}\n\t\t} else if (!sortClause && cursorColumns.length > 0) {\n\t\t\teffectiveSortClause = `ORDER BY ${cursorColumns.map((col) => `\\`${col}\\` ${effectiveSortDirection.toUpperCase()}`).join(\", \")}`;\n\t\t}\n\n\t\tconst [countRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as total FROM \\`${tableName}\\` ${filterWhere}`,\n\t\t\tfilterValues as any,\n\t\t);\n\t\tconst total = Number((countRows as Array<{ total: number }>)[0]?.total ?? 0);\n\n\t\tconst [dataRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT * FROM \\`${tableName}\\` ${combinedWhere} ${effectiveSortClause} LIMIT ${Math.floor(limit) + 1}`,\n\t\t\t[...filterValues, ...cursorValues] as any,\n\t\t);\n\n\t\tlet rows = dataRows as Record<string, unknown>[];\n\t\tconst hasMore = rows.length > limit;\n\t\tif (hasMore) rows = rows.slice(0, limit);\n\t\tif (direction === \"desc\") rows = rows.reverse();\n\n\t\tlet nextCursor: string | null = null;\n\t\tlet prevCursor: string | null = null;\n\n\t\tif (rows.length > 0 && cursorColumns.length > 0) {\n\t\t\tconst firstRow = rows[0];\n\t\t\tconst lastRow = rows[rows.length - 1];\n\t\t\tconst makeCursor = (row: Record<string, unknown>): CursorData => ({\n\t\t\t\tvalues: Object.fromEntries(cursorColumns.map((col) => [col, row[col]])),\n\t\t\t\tsortColumns: cursorColumns,\n\t\t\t});\n\n\t\t\tif (direction === \"asc\") {\n\t\t\t\tif (hasMore) nextCursor = this.encodeCursor(makeCursor(lastRow));\n\t\t\t\tif (cursor) prevCursor = this.encodeCursor(makeCursor(firstRow));\n\t\t\t} else {\n\t\t\t\tif (cursor) nextCursor = this.encodeCursor(makeCursor(lastRow));\n\t\t\t\tif (hasMore) prevCursor = this.encodeCursor(makeCursor(firstRow));\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tdata: rows,\n\t\t\tmeta: {\n\t\t\t\tlimit,\n\t\t\t\ttotal,\n\t\t\t\thasNextPage: direction === \"asc\" ? hasMore : !!cursor,\n\t\t\t\thasPreviousPage: direction === \"asc\" ? !!cursor : hasMore,\n\t\t\t\tnextCursor,\n\t\t\t\tprevCursor,\n\t\t\t},\n\t\t};\n\t}\n\n\t// =========================================================\n\t// IDbAdapter implementations\n\t// =========================================================\n\n\t// --- Databases ---\n\n\tasync getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst pool = getMysqlPool();\n\t\t\tconst [rows] = await pool.execute<RowDataPacket[]>(`\n\t\t\t\tSELECT\n\t\t\t\t s.SCHEMA_NAME AS name,\n\t\t\t\t CONCAT(ROUND(COALESCE(SUM(t.data_length + t.index_length), 0) / 1024 / 1024, 2), ' MB') AS size,\n\t\t\t\t CURRENT_USER() AS owner,\n\t\t\t\t s.DEFAULT_CHARACTER_SET_NAME AS encoding\n\t\t\t\tFROM information_schema.SCHEMATA s\n\t\t\t\tLEFT JOIN information_schema.TABLES t ON t.TABLE_SCHEMA = s.SCHEMA_NAME\n\t\t\t\tWHERE (s.SCHEMA_NAME NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys') OR s.SCHEMA_NAME = DATABASE())\n\t\t\t\tGROUP BY s.SCHEMA_NAME, s.DEFAULT_CHARACTER_SET_NAME\n\t\t\t\tORDER BY s.SCHEMA_NAME\n\t\t\t`);\n\t\t\tif (!rows[0])\n\t\t\t\tthrow new HTTPException(500, { message: \"No databases returned from server\" });\n\t\t\treturn rows as DatabaseInfoSchemaType[];\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\tconst pool = getMysqlPool();\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\"SELECT DATABASE() AS db\");\n\t\tif (!rows[0])\n\t\t\tthrow new HTTPException(500, { message: \"No current database returned from server\" });\n\t\treturn (rows as Array<{ db: string }>)[0] as DatabaseSchemaType;\n\t}\n\n\tasync getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\tconst pool = getMysqlPool();\n\t\tconst [infoRows] = await pool.execute<RowDataPacket[]>(`\n\t\t\tSELECT\n\t\t\t VERSION() AS version,\n\t\t\t DATABASE() AS database_name,\n\t\t\t CURRENT_USER() AS user,\n\t\t\t @@hostname AS host,\n\t\t\t @@port AS port,\n\t\t\t @@max_connections AS max_connections\n\t\t`);\n\t\tconst [connRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t\"SELECT COUNT(*) AS cnt FROM information_schema.PROCESSLIST\",\n\t\t);\n\t\tif (!infoRows[0])\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: \"No connection information returned from server\",\n\t\t\t});\n\n\t\tconst info = (infoRows as Array<Record<string, string | number>>)[0];\n\t\tconst urlDefaults = parseDatabaseUrl();\n\n\t\treturn {\n\t\t\thost: String(info.host || urlDefaults.host),\n\t\t\tport: Number(info.port || urlDefaults.port),\n\t\t\tuser: String(info.user),\n\t\t\tdatabase: String(info.database_name ?? \"\"),\n\t\t\tversion: String(info.version),\n\t\t\tactive_connections: Number((connRows as Array<{ cnt: number }>)[0]?.cnt ?? 0),\n\t\t\tmax_connections: Number(info.max_connections),\n\t\t};\n\t}\n\n\t// --- Tables ---\n\n\tasync getTablesList(db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\tconst pool = getMysqlPool(db);\n\t\tconst [tables] = await pool.execute<RowDataPacket[]>(`\n\t\t\tSELECT table_name as tableName\n\t\t\tFROM information_schema.tables\n\t\t\tWHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'\n\t\t\tORDER BY table_name\n\t\t`);\n\t\tif (!tables || tables.length === 0) return [];\n\n\t\treturn Promise.all(\n\t\t\t(tables as Array<{ tableName: string }>).map(async (table) => {\n\t\t\t\tconst [countRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t\t\t`SELECT COUNT(*) as count FROM \\`${table.tableName}\\``,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\ttableName: table.tableName,\n\t\t\t\t\trowCount: (countRows as Array<{ count: number }>)[0]?.count ?? 0,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\t}\n\n\tasync createTable({\n\t\ttableData,\n\t\tdb,\n\t}: {\n\t\ttableData: CreateTableSchemaType;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<void> {\n\t\tconst { tableName, fields, foreignKeys } = tableData;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tconst columnDefs = fields.map((field: FieldDataType) => buildMysqlColumnDefinition(field));\n\n\t\tconst constraintDefs: string[] = [];\n\t\tconst primaryKeyFields = fields.filter((f: FieldDataType) => f.isPrimaryKey);\n\t\tif (primaryKeyFields.length > 0) {\n\t\t\tconstraintDefs.push(\n\t\t\t\t`PRIMARY KEY (${primaryKeyFields.map((f: FieldDataType) => `\\`${f.columnName}\\``).join(\", \")})`,\n\t\t\t);\n\t\t}\n\t\tfor (const field of fields as FieldDataType[]) {\n\t\t\tif (field.isUnique && !field.isPrimaryKey) {\n\t\t\t\tconstraintDefs.push(\n\t\t\t\t\t`UNIQUE KEY \\`uq_${tableName}_${field.columnName}\\` (\\`${field.columnName}\\`)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst fkDefs =\n\t\t\tforeignKeys?.map((fk: ForeignKeyDataType) => {\n\t\t\t\tconst name = `fk_${tableName}_${fk.columnName}_${fk.referencedTable}_${fk.referencedColumn}`;\n\t\t\t\treturn `CONSTRAINT \\`${name}\\` FOREIGN KEY (\\`${fk.columnName}\\`) REFERENCES \\`${fk.referencedTable}\\` (\\`${fk.referencedColumn}\\`) ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}`;\n\t\t\t}) ?? [];\n\n\t\tawait pool.execute<ResultSetHeader>(\n\t\t\t`CREATE TABLE \\`${tableName}\\` (\\n\\t\\t\\t\\t${[...columnDefs, ...constraintDefs, ...fkDefs].join(\",\\n\\t\\t\\t\\t\")}\\n\\t\\t\\t) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`,\n\t\t);\n\t}\n\n\tasync deleteTable(params: DeleteTableParams): Promise<DeleteTableResult> {\n\t\tconst { tableName, db, cascade } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tconst [tableRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (Number((tableRows as Array<{ cnt: number }>)[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\n\t\tconst rowCount = await this.getTableRowCount(pool, tableName);\n\n\t\tif (!cascade) {\n\t\t\tconst relatedRecords = await this.getRelatedRecordsForTable(tableName, db);\n\t\t\tif (relatedRecords.length > 0) {\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tif (cascade) {\n\t\t\t\tconst connection = await pool.getConnection();\n\t\t\t\ttry {\n\t\t\t\t\tawait connection.execute(\"SET FOREIGN_KEY_CHECKS = 0\");\n\t\t\t\t\tawait connection.execute(`DROP TABLE \\`${tableName}\\``);\n\t\t\t\t\tawait connection.execute(\"SET FOREIGN_KEY_CHECKS = 1\");\n\t\t\t\t} finally {\n\t\t\t\t\tconnection.release();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait pool.execute(`DROP TABLE \\`${tableName}\\``);\n\t\t\t}\n\t\t\treturn { deletedCount: rowCount, fkViolation: false, relatedRecords: [] };\n\t\t} catch (error) {\n\t\t\tawait pool.execute(\"SET FOREIGN_KEY_CHECKS = 1\").catch(() => {});\n\t\t\tconst mysqlError = error as { errno?: number };\n\t\t\tif (\n\t\t\t\tmysqlError.errno === MYSQL_FK_DEPENDENCY ||\n\t\t\t\tmysqlError.errno === MYSQL_FK_VIOLATION\n\t\t\t) {\n\t\t\t\tconst relatedRecords = await this.getRelatedRecordsForTable(tableName, db);\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to delete table \"${tableName}\"` });\n\t\t}\n\t}\n\n\tasync renameTable(params: RenameTableParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, newTableName, db } = params;\n\t\t\tthis.assertDifferentTableName(tableName, newTableName);\n\t\t\tconst pool = getMysqlPool(db);\n\n\t\t\tawait this.assertTableExists(pool, tableName);\n\n\t\t\tconst [targetRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?`,\n\t\t\t\t[newTableName],\n\t\t\t);\n\t\t\tif (Number((targetRows as Array<{ cnt: number }>)[0]?.cnt ?? 0) > 0) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Table \"${newTableName}\" already exists`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait pool.execute<ResultSetHeader>(\n\t\t\t\t`RENAME TABLE \\`${tableName.replaceAll(\"`\", \"``\")}\\` TO \\`${newTableName.replaceAll(\"`\", \"``\")}\\``,\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getTableSchema({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\tconst pool = getMysqlPool(db);\n\t\tconst [tableRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (Number((tableRows as Array<{ cnt: number }>)[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(`SHOW CREATE TABLE \\`${tableName}\\``);\n\t\tconst row = (rows as Array<Record<string, string>>)[0];\n\t\tconst createTableSql = row?.[\"Create Table\"] ?? row?.create_table ?? \"\";\n\t\tif (!createTableSql) {\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to retrieve schema for table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t\treturn createTableSql;\n\t}\n\n\t// --- Columns ---\n\n\tasync getTableColumns({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\tconst pool = getMysqlPool(db);\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT\n\t\t\t c.COLUMN_NAME AS columnName,\n\t\t\t c.DATA_TYPE AS dataType,\n\t\t\t c.COLUMN_TYPE AS columnType,\n\t\t\t (c.IS_NULLABLE = 'YES') AS isNullable,\n\t\t\t c.COLUMN_DEFAULT AS columnDefault,\n\t\t\t (c.COLUMN_KEY = 'PRI') AS isPrimaryKey,\n\t\t\t (kcu.REFERENCED_TABLE_NAME IS NOT NULL) AS isForeignKey,\n\t\t\t kcu.REFERENCED_TABLE_NAME AS referencedTable,\n\t\t\t kcu.REFERENCED_COLUMN_NAME AS referencedColumn\n\t\t\tFROM information_schema.COLUMNS c\n\t\t\tLEFT JOIN information_schema.KEY_COLUMN_USAGE kcu\n\t\t\t ON c.TABLE_SCHEMA = kcu.TABLE_SCHEMA\n\t\t\t AND c.TABLE_NAME = kcu.TABLE_NAME\n\t\t\t AND c.COLUMN_NAME = kcu.COLUMN_NAME\n\t\t\t AND kcu.REFERENCED_TABLE_NAME IS NOT NULL\n\t\t\tWHERE c.TABLE_SCHEMA = DATABASE()\n\t\t\t AND c.TABLE_NAME = ?\n\t\t\tORDER BY c.ORDINAL_POSITION`,\n\t\t\t[tableName],\n\t\t);\n\n\t\tif (!rows || rows.length === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\n\t\treturn (\n\t\t\trows as Array<{\n\t\t\t\tcolumnName: string;\n\t\t\t\tdataType: string;\n\t\t\t\tcolumnType: string;\n\t\t\t\tisNullable: number | boolean;\n\t\t\t\tcolumnDefault: string | null;\n\t\t\t\tisPrimaryKey: number | boolean;\n\t\t\t\tisForeignKey: number | boolean;\n\t\t\t\treferencedTable: string | null;\n\t\t\t\treferencedColumn: string | null;\n\t\t\t}>\n\t\t).map((r) => {\n\t\t\tconst isEnum = r.dataType === \"enum\" || r.dataType === \"set\";\n\t\t\treturn {\n\t\t\t\tcolumnName: r.columnName,\n\t\t\t\tdataType: mapMysqlToDataType(r.dataType, r.columnType),\n\t\t\t\tdataTypeLabel: standardizeMysqlDataTypeLabel(r.dataType, r.columnType),\n\t\t\t\tisNullable: Boolean(r.isNullable),\n\t\t\t\tcolumnDefault: r.columnDefault ?? null,\n\t\t\t\tisPrimaryKey: Boolean(r.isPrimaryKey),\n\t\t\t\tisForeignKey: Boolean(r.isForeignKey),\n\t\t\t\treferencedTable: r.referencedTable ?? null,\n\t\t\t\treferencedColumn: r.referencedColumn ?? null,\n\t\t\t\tenumValues: isEnum ? this.parseMysqlEnumValues(r.columnType) : null,\n\t\t\t};\n\t\t});\n\t}\n\n\tasync addColumn(params: AddColumnParamsSchemaType): Promise<void> {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tcolumnName,\n\t\t\tcolumnType,\n\t\t\tdefaultValue,\n\t\t\tisPrimaryKey,\n\t\t\tisNullable,\n\t\t\tisUnique,\n\t\t\tisIdentity,\n\t\t\tisArray,\n\t\t\tdb,\n\t\t} = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\n\t\tconst [colRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?`,\n\t\t\t[tableName, columnName],\n\t\t);\n\t\tif (Number((colRows as Array<{ cnt: number }>)[0]?.cnt ?? 0) > 0) {\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${columnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\tconst colDef = buildMysqlColumnDefinition(\n\t\t\t{\n\t\t\t\tcolumnName,\n\t\t\t\tcolumnType,\n\t\t\t\tdefaultValue,\n\t\t\t\tisPrimaryKey,\n\t\t\t\tisNullable,\n\t\t\t\tisUnique,\n\t\t\t\tisIdentity,\n\t\t\t\tisArray,\n\t\t\t},\n\t\t\t{ includePrimaryKey: true, includeUnique: true },\n\t\t);\n\t\tawait pool.execute<ResultSetHeader>(`ALTER TABLE \\`${tableName}\\` ADD COLUMN ${colDef}`);\n\t}\n\n\tasync deleteColumn(params: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\tconst { tableName, columnName, db } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\t\tawait this.assertColumnExists(pool, tableName, columnName);\n\n\t\tconst [result] = await pool.execute<ResultSetHeader>(\n\t\t\t`ALTER TABLE \\`${tableName}\\` DROP COLUMN \\`${columnName}\\``,\n\t\t);\n\t\treturn { deletedCount: result.affectedRows };\n\t}\n\n\tasync alterColumn(params: AlterColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, columnType, isNullable, defaultValue, db } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\n\t\tconst [colRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ? LIMIT 1`,\n\t\t\t[tableName, columnName],\n\t\t);\n\t\tconst colRow = (colRows as Array<{ EXTRA?: string | null }>)[0];\n\t\tif (!colRow) {\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\tconst colDef = buildMysqlColumnDefinition(\n\t\t\t{ columnName, columnType, defaultValue, isNullable },\n\t\t\t{ preserveAutoIncrement: colRow.EXTRA?.toLowerCase().includes(\"auto_increment\") },\n\t\t);\n\t\tawait pool.execute<ResultSetHeader>(\n\t\t\t`ALTER TABLE \\`${tableName}\\` MODIFY COLUMN ${colDef}`,\n\t\t);\n\t}\n\n\tasync renameColumn(params: RenameColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, newColumnName, db } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\t\tawait this.assertColumnExists(pool, tableName, columnName);\n\n\t\tconst [newColRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?`,\n\t\t\t[tableName, newColumnName],\n\t\t);\n\t\tif (Number((newColRows as Array<{ cnt: number }>)[0]?.cnt ?? 0) > 0) {\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${newColumnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\tawait pool.execute<ResultSetHeader>(\n\t\t\t`ALTER TABLE \\`${tableName}\\` RENAME COLUMN \\`${columnName}\\` TO \\`${newColumnName}\\``,\n\t\t);\n\t}\n\n\t// --- Records ---\n\n\tasync addRecord({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\tconst { tableName, data } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\t\tconst columns = Object.keys(data);\n\t\tconst values = Object.values(data).map((value, i) => {\n\t\t\tif (booleanColumns.has(columns[i]) && typeof value === \"string\") {\n\t\t\t\treturn value === \"true\" ? 1 : 0;\n\t\t\t}\n\t\t\treturn value;\n\t\t});\n\n\t\tconst [result] = await pool.execute<ResultSetHeader>(\n\t\t\t`INSERT INTO \\`${tableName}\\` (${columns.map((c) => `\\`${c}\\``).join(\", \")}) VALUES (${columns.map(() => \"?\").join(\", \")})`,\n\t\t\tvalues as any,\n\t\t);\n\t\tif (result.affectedRows === 0) {\n\t\t\tthrow new HTTPException(500, { message: `Failed to insert record into \"${tableName}\"` });\n\t\t}\n\t\treturn { insertedCount: result.affectedRows };\n\t}\n\n\tasync updateRecords({\n\t\tparams,\n\t\tdb,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\tconst { tableName } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\tconst keyColumns = this.resolveKeyColumns(params);\n\t\tconst groups = this.groupUpdatesByKey(params, keyColumns);\n\n\t\tconst connection = await pool.getConnection();\n\t\tawait connection.beginTransaction();\n\n\t\ttry {\n\t\t\tlet total = 0;\n\t\t\tfor (const { keyValues, rowUpdates } of groups) {\n\t\t\t\tconst setClauses = rowUpdates.map((u) => `\\`${u.columnName}\\` = ?`);\n\t\t\t\tconst values: unknown[] = rowUpdates.map((u) => {\n\t\t\t\t\tif (u.value !== null && typeof u.value === \"object\") return JSON.stringify(u.value);\n\t\t\t\t\tif (booleanColumns.has(u.columnName) && typeof u.value === \"string\") {\n\t\t\t\t\t\treturn u.value === \"true\" ? 1 : 0;\n\t\t\t\t\t}\n\t\t\t\t\treturn u.value;\n\t\t\t\t});\n\t\t\t\tvalues.push(...keyValues);\n\t\t\t\tconst whereClauses = keyColumns.map((column) => `\\`${column}\\` = ?`);\n\n\t\t\t\tconst [result] = await connection.execute<ResultSetHeader>(\n\t\t\t\t\t`UPDATE \\`${tableName}\\` SET ${setClauses.join(\", \")} WHERE ${whereClauses.join(\" AND \")}`,\n\t\t\t\t\tvalues as any,\n\t\t\t\t);\n\t\t\t\tif (result.affectedRows === 0) {\n\t\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\t\tmessage: `Record with ${this.describeKey(keyColumns, keyValues)} not found in table \"${tableName}\"`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\ttotal += result.affectedRows;\n\t\t\t}\n\t\t\tawait connection.commit();\n\t\t\treturn { updatedCount: total };\n\t\t} catch (error) {\n\t\t\tawait connection.rollback();\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to update records in \"${tableName}\"` });\n\t\t} finally {\n\t\t\tconnection.release();\n\t\t}\n\t}\n\n\tasync deleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\tconst pool = getMysqlPool(db);\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst placeholders = pkValues.map(() => \"?\").join(\", \");\n\t\tconst connection = await pool.getConnection();\n\t\tawait connection.beginTransaction();\n\n\t\ttry {\n\t\t\tconst [result] = await connection.execute<ResultSetHeader>(\n\t\t\t\t`DELETE FROM \\`${tableName}\\` WHERE \\`${pkColumn}\\` IN (${placeholders})`,\n\t\t\t\tpkValues as any,\n\t\t\t);\n\t\t\tawait connection.commit();\n\t\t\treturn { deletedCount: result.affectedRows, fkViolation: false, relatedRecords: [] };\n\t\t} catch (error) {\n\t\t\tawait connection.rollback();\n\t\t\tconst mysqlError = error as { errno?: number };\n\t\t\tif (mysqlError.errno === MYSQL_FK_VIOLATION) {\n\t\t\t\tconst relatedRecords = await this.getRelatedRecords(tableName, primaryKeys, db);\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to delete records from \"${tableName}\"`,\n\t\t\t});\n\t\t} finally {\n\t\t\tconnection.release();\n\t\t}\n\t}\n\n\tasync forceDeleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<{ deletedCount: number }> {\n\t\tconst pool = getMysqlPool(db);\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst connection = await pool.getConnection();\n\t\tawait connection.beginTransaction();\n\n\t\ttry {\n\t\t\tawait connection.execute(\"SET FOREIGN_KEY_CHECKS = 0\");\n\n\t\t\tconst fkConstraints = await this.getForeignKeyReferences(tableName, db);\n\t\t\tlet totalRelated = 0;\n\t\t\tconst deletedTables = new Set<string>();\n\t\t\tconst visited = new Set<string>();\n\n\t\t\tconst deleteRelatedRecursively = async (\n\t\t\t\ttargetTable: string,\n\t\t\t\ttargetColumn: string,\n\t\t\t\tvalues: unknown[],\n\t\t\t\tvisitedSet: Set<string>,\n\t\t\t) => {\n\t\t\t\tconst key = `${targetTable}.${targetColumn}`;\n\t\t\t\tif (visitedSet.has(key)) return;\n\t\t\t\tvisitedSet.add(key);\n\n\t\t\t\tconst nestedFks = await this.getForeignKeyReferences(targetTable, db);\n\t\t\t\tfor (const nestedFk of nestedFks) {\n\t\t\t\t\tconst nestedPh = values.map(() => \"?\").join(\", \");\n\t\t\t\t\tconst [selectRows] = await connection.execute<RowDataPacket[]>(\n\t\t\t\t\t\t`SELECT \\`${nestedFk.referencedColumn}\\` FROM \\`${targetTable}\\` WHERE \\`${targetColumn}\\` IN (${nestedPh})`,\n\t\t\t\t\t\tvalues as any[],\n\t\t\t\t\t);\n\t\t\t\t\tconst nestedValues = (selectRows as Record<string, unknown>[]).map(\n\t\t\t\t\t\t(row) => row[nestedFk.referencedColumn],\n\t\t\t\t\t);\n\t\t\t\t\tif (nestedValues.length > 0) {\n\t\t\t\t\t\tawait deleteRelatedRecursively(\n\t\t\t\t\t\t\tnestedFk.referencingTable,\n\t\t\t\t\t\t\tnestedFk.referencingColumn,\n\t\t\t\t\t\t\tnestedValues,\n\t\t\t\t\t\t\tvisitedSet,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst ph = values.map(() => \"?\").join(\", \");\n\t\t\t\tconst [deleteResult] = await connection.execute<ResultSetHeader>(\n\t\t\t\t\t`DELETE FROM \\`${targetTable}\\` WHERE \\`${targetColumn}\\` IN (${ph})`,\n\t\t\t\t\tvalues as any[],\n\t\t\t\t);\n\t\t\t\ttotalRelated += deleteResult.affectedRows;\n\t\t\t\tdeletedTables.add(targetTable);\n\t\t\t};\n\n\t\t\tfor (const constraint of fkConstraints) {\n\t\t\t\tif (!deletedTables.has(constraint.referencingTable)) {\n\t\t\t\t\tawait deleteRelatedRecursively(\n\t\t\t\t\t\tconstraint.referencingTable,\n\t\t\t\t\t\tconstraint.referencingColumn,\n\t\t\t\t\t\tpkValues,\n\t\t\t\t\t\tvisited,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst mainPh = pkValues.map(() => \"?\").join(\", \");\n\t\t\tconst [result] = await connection.execute<ResultSetHeader>(\n\t\t\t\t`DELETE FROM \\`${tableName}\\` WHERE \\`${pkColumn}\\` IN (${mainPh})`,\n\t\t\t\tpkValues as any,\n\t\t\t);\n\n\t\t\tawait connection.execute(\"SET FOREIGN_KEY_CHECKS = 1\");\n\t\t\tawait connection.commit();\n\t\t\treturn { deletedCount: result.affectedRows + totalRelated };\n\t\t} catch (error) {\n\t\t\tawait connection.execute(\"SET FOREIGN_KEY_CHECKS = 1\").catch(() => {});\n\t\t\tawait connection.rollback();\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to force delete records from \"${tableName}\"`,\n\t\t\t});\n\t\t} finally {\n\t\t\tconnection.release();\n\t\t}\n\t}\n\n\tasync bulkInsertRecords({\n\t\ttableName,\n\t\trecords,\n\t\tdb,\n\t}: BulkInsertRecordsParams): Promise<BulkInsertResult> {\n\t\tif (!records || records.length === 0) {\n\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\t\t}\n\n\t\tconst pool = getMysqlPool(db);\n\t\tconst connection = await pool.getConnection();\n\n\t\ttry {\n\t\t\tconst columns = Object.keys(records[0]);\n\t\t\tconst colNames = columns.map((c) => `\\`${c}\\``).join(\", \");\n\t\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\t\tawait connection.beginTransaction();\n\n\t\t\tfor (let i = 0; i < records.length; i++) {\n\t\t\t\tconst record = records[i];\n\t\t\t\tconst values = columns.map((col) => {\n\t\t\t\t\tconst value = record[col];\n\t\t\t\t\tif (booleanColumns.has(col) && typeof value === \"string\")\n\t\t\t\t\t\treturn value === \"true\" ? 1 : 0;\n\t\t\t\t\treturn value;\n\t\t\t\t});\n\n\t\t\t\ttry {\n\t\t\t\t\tawait connection.execute<ResultSetHeader>(\n\t\t\t\t\t\t`INSERT INTO \\`${tableName}\\` (${colNames}) VALUES (${columns.map(() => \"?\").join(\", \")})`,\n\t\t\t\t\t\tvalues as any,\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new HTTPException(500, {\n\t\t\t\t\t\tmessage: `Failed to insert record ${i + 1}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait connection.commit();\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `Successfully inserted ${records.length} record${records.length !== 1 ? \"s\" : \"\"}`,\n\t\t\t\tsuccessCount: records.length,\n\t\t\t\tfailureCount: 0,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tawait connection.rollback();\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to bulk insert records into \"${tableName}\"`,\n\t\t\t});\n\t\t} finally {\n\t\t\tconnection.release();\n\t\t}\n\t}\n\n\t// --- Query ---\n\n\tasync executeQuery({\n\t\tquery,\n\t\tdb,\n\t}: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\tconst pool = getMysqlPool(db);\n\t\tif (!query?.trim()) throw new HTTPException(400, { message: \"Query is required\" });\n\n\t\tconst cleaned = query.trim().replace(/;+$/, \"\");\n\t\tconst start = performance.now();\n\t\tconst [result, fields] = (await pool.execute(cleaned)) as [\n\t\t\tRowDataPacket[] | ResultSetHeader,\n\t\t\tFieldPacket[],\n\t\t];\n\t\tconst duration = performance.now() - start;\n\n\t\tif (Array.isArray(result)) {\n\t\t\tconst rows = result as RowDataPacket[];\n\t\t\tconst columns = fields ? fields.map((f) => f.name) : Object.keys(rows[0] ?? {});\n\t\t\treturn {\n\t\t\t\tcolumns,\n\t\t\t\trows: rows as Record<string, unknown>[],\n\t\t\t\trowCount: rows.length,\n\t\t\t\tduration,\n\t\t\t\tmessage: rows.length === 0 ? \"OK\" : undefined,\n\t\t\t};\n\t\t}\n\n\t\tconst dmlResult = result as ResultSetHeader;\n\t\treturn {\n\t\t\tcolumns: [],\n\t\t\trows: [],\n\t\t\trowCount: dmlResult.affectedRows,\n\t\t\tduration,\n\t\t\tmessage: `OK — ${dmlResult.affectedRows} row(s) affected`,\n\t\t};\n\t}\n\n\t// =========================================================\n\t// Private helpers\n\t// =========================================================\n\n\tprivate async getPrimaryKeyColumns(pool: MysqlPool, tableName: string): Promise<string[]> {\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COLUMN_NAME as column_name\n\t\t\t FROM information_schema.COLUMNS\n\t\t\t WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_KEY = 'PRI'\n\t\t\t ORDER BY ORDINAL_POSITION`,\n\t\t\t[tableName],\n\t\t);\n\t\treturn (rows as Array<{ column_name: string }>).map((r) => r.column_name);\n\t}\n\n\tprivate async getForeignKeyReferences(\n\t\ttableName: string,\n\t\tdb: string,\n\t): Promise<ForeignKeyConstraint[]> {\n\t\tconst pool = getMysqlPool(db);\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT\n\t\t\t\tkcu.CONSTRAINT_NAME AS constraint_name,\n\t\t\t\tkcu.TABLE_NAME AS referencing_table,\n\t\t\t\tkcu.COLUMN_NAME AS referencing_column,\n\t\t\t\tkcu.REFERENCED_TABLE_NAME AS referenced_table,\n\t\t\t\tkcu.REFERENCED_COLUMN_NAME AS referenced_column\n\t\t\tFROM information_schema.KEY_COLUMN_USAGE kcu\n\t\t\tJOIN information_schema.TABLE_CONSTRAINTS tc\n\t\t\t ON kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME\n\t\t\t AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA\n\t\t\t AND kcu.TABLE_NAME = tc.TABLE_NAME\n\t\t\tWHERE tc.CONSTRAINT_TYPE = 'FOREIGN KEY'\n\t\t\t AND kcu.TABLE_SCHEMA = DATABASE()\n\t\t\t AND kcu.REFERENCED_TABLE_NAME = ?`,\n\t\t\t[tableName],\n\t\t);\n\t\treturn (rows as ForeignKeyConstraintRow[]).map((row) => ({\n\t\t\tconstraintName: row.constraint_name,\n\t\t\treferencingTable: row.referencing_table,\n\t\t\treferencingColumn: row.referencing_column,\n\t\t\treferencedTable: row.referenced_table,\n\t\t\treferencedColumn: row.referenced_column,\n\t\t}));\n\t}\n\n\tprivate async getRelatedRecordsForTable(\n\t\ttableName: string,\n\t\tdb: string,\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getForeignKeyReferences(tableName, db);\n\t\tif (fks.length === 0) return [];\n\n\t\tconst pool = getMysqlPool(db);\n\t\tconst results: RelatedRecord[] = [];\n\t\tfor (const fk of fks) {\n\t\t\tconst [relatedRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t\t`SELECT * FROM \\`${fk.referencingTable}\\` LIMIT 100`,\n\t\t\t);\n\t\t\tif (relatedRows.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: relatedRows as Record<string, unknown>[],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate async getRelatedRecords(\n\t\ttableName: string,\n\t\tprimaryKeys: DeleteRecordSchemaType[\"primaryKeys\"],\n\t\tdb: string,\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getForeignKeyReferences(tableName, db);\n\t\tif (fks.length === 0) return [];\n\n\t\tconst pool = getMysqlPool(db);\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst results: RelatedRecord[] = [];\n\n\t\tconst constraintsByTable = new Map<string, ForeignKeyConstraint[]>();\n\t\tfor (const fk of fks) {\n\t\t\tconst key = `${fk.referencingTable}.${fk.referencingColumn}`;\n\t\t\tif (!constraintsByTable.has(key)) constraintsByTable.set(key, []);\n\t\t\tconstraintsByTable.get(key)?.push(fk);\n\t\t}\n\n\t\tfor (const [, constraints] of constraintsByTable) {\n\t\t\tconst fk = constraints[0];\n\t\t\tif (!fk) continue;\n\t\t\tconst matchingPk = primaryKeys.find((pk) => pk.columnName === fk.referencedColumn);\n\t\t\tif (!matchingPk) continue;\n\n\t\t\tconst placeholders = pkValues.map(() => \"?\").join(\", \");\n\t\t\tconst [relatedRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t\t`SELECT * FROM \\`${fk.referencingTable}\\` WHERE \\`${fk.referencingColumn}\\` IN (${placeholders}) LIMIT 100`,\n\t\t\t\tpkValues as any,\n\t\t\t);\n\t\t\tif (relatedRows.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: relatedRows as Record<string, unknown>[],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate async getTableRowCount(pool: MysqlPool, tableName: string): Promise<number> {\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as count FROM \\`${tableName}\\``,\n\t\t);\n\t\treturn Number((rows as Array<{ count: number }>)[0]?.count ?? 0);\n\t}\n\n\tprivate async getBooleanColumnSet(tableName: string, db: string): Promise<Set<string>> {\n\t\tconst cols = await this.getTableColumns({ tableName, db });\n\t\treturn new Set(cols.filter((c) => c.dataTypeLabel === \"boolean\").map((c) => c.columnName));\n\t}\n\n\tprivate async assertTableExists(pool: MysqlPool, tableName: string): Promise<void> {\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (Number((rows as Array<{ cnt: number }>)[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\t}\n\n\tprivate async assertColumnExists(\n\t\tpool: MysqlPool,\n\t\ttableName: string,\n\t\tcolumnName: string,\n\t): Promise<void> {\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?`,\n\t\t\t[tableName, columnName],\n\t\t);\n\t\tif (Number((rows as Array<{ cnt: number }>)[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate parseMysqlEnumValues(columnType: string): string[] | null {\n\t\tconst match = columnType.match(/^(?:enum|set)\\((.+)\\)$/i);\n\t\tif (!match?.[1]) return null;\n\t\treturn match[1].split(\",\").map((v) => v.trim().replace(/^'|'$/g, \"\"));\n\t}\n}\n","import type { CursorData, FilterType, SortDirection, SortType } from \"@db-studio/shared/types\";\n\nexport function buildWhereClause(filters: FilterType[]): {\n\tclause: string;\n\tvalues: unknown[];\n} {\n\tif (filters.length === 0) {\n\t\treturn { clause: \"\", values: [] };\n\t}\n\n\tconst conditions: string[] = [];\n\tconst values: unknown[] = [];\n\n\tfor (const filter of filters) {\n\t\tconst paramIndex = values.length + 1;\n\t\tconst columnName = `\"${filter.columnName}\"`;\n\n\t\tswitch (filter.operator) {\n\t\t\tcase \"=\":\n\t\t\tcase \"!=\":\n\t\t\tcase \">\":\n\t\t\tcase \">=\":\n\t\t\tcase \"<\":\n\t\t\tcase \"<=\":\n\t\t\t\tconditions.push(`${columnName} ${filter.operator} $${paramIndex}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"is\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${columnName} IS NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${columnName} = $${paramIndex}`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"is not\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${columnName} IS NOT NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${columnName} != $${paramIndex}`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"like\":\n\t\t\t\tconditions.push(`${columnName}::text LIKE $${paramIndex}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"not like\":\n\t\t\t\tconditions.push(`${columnName}::text NOT LIKE $${paramIndex}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"ilike\":\n\t\t\t\tconditions.push(`${columnName}::text ILIKE $${paramIndex}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"not ilike\":\n\t\t\t\tconditions.push(`${columnName}::text NOT ILIKE $${paramIndex}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (conditions.length === 0) {\n\t\treturn { clause: \"\", values: [] };\n\t}\n\n\treturn { clause: `WHERE ${conditions.join(\" AND \")}`, values };\n}\n\nexport function buildSortClause(sorts: SortType[] | string, order: SortDirection): string {\n\tif (Array.isArray(sorts)) {\n\t\tif (sorts.length === 0) return \"\";\n\t\tconst parts = sorts.map((s) => `\"${s.columnName}\" ${s.direction.toUpperCase()}`);\n\t\treturn `ORDER BY ${parts.join(\", \")}`;\n\t}\n\tif (sorts && typeof sorts === \"string\") {\n\t\treturn `ORDER BY \"${sorts}\" ${order?.toUpperCase() || \"ASC\"}`;\n\t}\n\treturn \"\";\n}\n\nexport function buildCursorWhereClause(\n\tcursorData: CursorData,\n\tdirection: SortDirection,\n\tsortDirection: SortDirection,\n\tstartParamIndex: number,\n): { clause: string; values: unknown[] } {\n\tconst { values, sortColumns } = cursorData;\n\tconst conditions: string[] = [];\n\tconst queryValues: unknown[] = [];\n\n\tconst isAscending = sortDirection === \"asc\";\n\tconst isForward = direction === \"asc\";\n\tconst useGreaterThan = isAscending === isForward;\n\n\tif (sortColumns.length > 0) {\n\t\tconst columnList = sortColumns.map((col) => `\"${col}\"`).join(\", \");\n\t\tconst placeholders = sortColumns.map((_, i) => `$${startParamIndex + i}`).join(\", \");\n\t\tconst operator = useGreaterThan ? \">\" : \"<\";\n\t\tconditions.push(`(${columnList}) ${operator} (${placeholders})`);\n\t\tfor (const col of sortColumns) {\n\t\t\tqueryValues.push(values[col]);\n\t\t}\n\t}\n\n\treturn {\n\t\tclause: conditions.length > 0 ? `(${conditions.join(\" AND \")})` : \"\",\n\t\tvalues: queryValues,\n\t};\n}\n\n/**\n * Postgres resolves a bare table name through search_path, but catalog queries\n * filter on a literal schema and would otherwise disagree with the data queries\n * — the reason a table outside \"public\" used to list yet 404 on its columns.\n * Both helpers below mirror Postgres' own resolution.\n */\n\n/** Every schema on the current search_path. Use for EXISTS-style checks. */\nexport const SEARCH_PATH_SCHEMAS = \"ANY(current_schemas(false))\";\n\n/**\n * The single schema a bare table name resolves to, honouring search_path order\n * so a name present in several schemas picks the same one Postgres would.\n */\nexport const resolvedSchemaFor = (tableParam: string): string =>\n\t`(SELECT sp.schema_name FROM unnest(current_schemas(false)) WITH ORDINALITY AS sp(schema_name, position)\n\t JOIN information_schema.tables it\n\t ON it.table_schema = sp.schema_name AND it.table_name = ${tableParam}\n\t ORDER BY sp.position LIMIT 1)`;\n","import type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tCursorData,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteRecordSchemaType,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tFieldDataType,\n\tForeignKeyConstraint,\n\tForeignKeyConstraintRow,\n\tForeignKeyDataType,\n\tRelatedRecord,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tSortDirection,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { mapPostgresToDataType, standardizeDataTypeLabel } from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getDbPool } from \"@/adapters/connections.js\";\nimport { parseDatabaseUrl } from \"@/utils/parse-database-url.js\";\nimport {\n\tbuildCursorWhereClause,\n\tbuildSortClause,\n\tbuildWhereClause,\n\tresolvedSchemaFor,\n} from \"./pg.query-builder.js\";\n\ntype PgPool = ReturnType<typeof getDbPool>;\n\nexport class PgAdapter extends BaseAdapter {\n\t// =========================================================\n\t// Abstract method implementations\n\t// =========================================================\n\n\tprotected async runQuery<T>(db: string, sql: string, values: unknown[]): Promise<T> {\n\t\tconst pool = getDbPool(db);\n\t\tconst result = await pool.query(sql, values);\n\t\treturn result.rows as T;\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn `\"${name}\"`;\n\t}\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\treturn mapPostgresToDataType(nativeType);\n\t}\n\n\tmapFromUniversalType(universalType: string): string {\n\t\tconst map: Record<string, string> = {\n\t\t\ttext: \"TEXT\",\n\t\t\tnumber: \"INTEGER\",\n\t\t\tboolean: \"BOOLEAN\",\n\t\t\tjson: \"JSONB\",\n\t\t\tdate: \"TIMESTAMP WITH TIME ZONE\",\n\t\t\tarray: \"TEXT[]\",\n\t\t\tenum: \"TEXT\",\n\t\t};\n\t\treturn map[universalType] ?? \"TEXT\";\n\t}\n\n\tprotected buildTableDataQuery(params: GetTableDataParams): QueryBundle {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tcursor = \"\",\n\t\t\tlimit = 50,\n\t\t\tdirection = \"asc\",\n\t\t\tsort = [],\n\t\t\torder = \"asc\",\n\t\t\tfilters = [],\n\t\t\tdb,\n\t\t} = params;\n\n\t\tconst pool = getDbPool(db);\n\t\tvoid pool; // just to keep reference — actual pool used in runQuery\n\n\t\tlet sortColumns: string[] = [];\n\t\tlet effectiveSortDirection: SortDirection = order;\n\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t\teffectiveSortDirection = sort[0].direction;\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\n\t\t// We can't synchronously get primary key columns here (it's async).\n\t\t// The adapter overrides getTableData() to handle that step instead.\n\t\t// For cursor columns we use whatever sort columns are provided, or ctid as fallback.\n\t\tconst cursorColumns = sortColumns.length > 0 ? [...sortColumns] : [\"ctid\"];\n\n\t\tconst { clause: filterWhere, values: filterValues } = buildWhereClause(filters);\n\n\t\tlet cursorWhere = \"\";\n\t\tlet cursorValues: unknown[] = [];\n\n\t\tif (cursor) {\n\t\t\tconst cursorData = this.decodeCursor(cursor);\n\t\t\tif (cursorData) {\n\t\t\t\tconst res = buildCursorWhereClause(\n\t\t\t\t\tcursorData,\n\t\t\t\t\tdirection,\n\t\t\t\t\teffectiveSortDirection,\n\t\t\t\t\tfilterValues.length + 1,\n\t\t\t\t);\n\t\t\t\tcursorWhere = res.clause;\n\t\t\t\tcursorValues = res.values;\n\t\t\t}\n\t\t}\n\n\t\tlet combinedWhere = \"\";\n\t\tif (filterWhere && cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${filterWhere.replace(/^WHERE\\s+/i, \"\")} AND ${cursorWhere}`;\n\t\t} else if (filterWhere) {\n\t\t\tcombinedWhere = filterWhere;\n\t\t} else if (cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${cursorWhere}`;\n\t\t}\n\n\t\tconst sortClause = buildSortClause(Array.isArray(sort) ? sort : sort, order);\n\t\tlet effectiveSortClause = sortClause;\n\n\t\tif (direction === \"desc\") {\n\t\t\tif (sortClause) {\n\t\t\t\teffectiveSortClause = sortClause\n\t\t\t\t\t.replace(/\\bASC\\b/gi, \"TEMP_DESC\")\n\t\t\t\t\t.replace(/\\bDESC\\b/gi, \"ASC\")\n\t\t\t\t\t.replace(/TEMP_DESC/g, \"DESC\");\n\t\t\t} else {\n\t\t\t\tconst parts = cursorColumns.map(\n\t\t\t\t\t(col) => `\"${col}\" ${effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\"}`,\n\t\t\t\t);\n\t\t\t\teffectiveSortClause = `ORDER BY ${parts.join(\", \")}`;\n\t\t\t}\n\t\t} else if (!sortClause && cursorColumns.length > 0) {\n\t\t\tconst parts = cursorColumns.map(\n\t\t\t\t(col) => `\"${col}\" ${effectiveSortDirection.toUpperCase()}`,\n\t\t\t);\n\t\t\teffectiveSortClause = `ORDER BY ${parts.join(\", \")}`;\n\t\t}\n\n\t\tconst limitParamIndex = filterValues.length + cursorValues.length + 1;\n\t\tconst sql = `SELECT * FROM \"${tableName}\" ${combinedWhere} ${effectiveSortClause} LIMIT $${limitParamIndex}`;\n\t\tconst values = [...filterValues, ...cursorValues, limit + 1];\n\n\t\tconst countSql = `SELECT COUNT(*) as total FROM \"${tableName}\" ${filterWhere}`;\n\t\tconst countValues = filterValues;\n\n\t\treturn { sql, values, countSql, countValues };\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn (rawRows as Record<string, unknown>[]).map((row) => this.normalizeRow(row));\n\t}\n\n\tprotected buildCursors(\n\t\tparams: GetTableDataParams,\n\t\trows: NormalizedRow[],\n\t\thasMore: boolean,\n\t): { nextCursor: string | null; prevCursor: string | null } {\n\t\tif (rows.length === 0) return { nextCursor: null, prevCursor: null };\n\n\t\tconst { direction = \"asc\", sort = [], cursor } = params;\n\t\tlet sortColumns: string[] = [];\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\t\tif (sortColumns.length === 0) sortColumns = [\"ctid\"];\n\n\t\tconst createCursor = (row: NormalizedRow): string => {\n\t\t\tconst data: CursorData = {\n\t\t\t\tvalues: Object.fromEntries(sortColumns.map((col) => [col, row[col]])),\n\t\t\t\tsortColumns,\n\t\t\t};\n\t\t\treturn this.encodeCursor(data);\n\t\t};\n\n\t\tconst firstRow = rows[0];\n\t\tconst lastRow = rows[rows.length - 1];\n\n\t\tlet nextCursor: string | null = null;\n\t\tlet prevCursor: string | null = null;\n\n\t\tif (direction === \"asc\") {\n\t\t\tif (hasMore) nextCursor = createCursor(lastRow);\n\t\t\tif (cursor) prevCursor = createCursor(firstRow);\n\t\t} else {\n\t\t\tif (cursor) nextCursor = createCursor(lastRow);\n\t\t\tif (hasMore) prevCursor = createCursor(firstRow);\n\t\t}\n\n\t\treturn { nextCursor, prevCursor };\n\t}\n\n\t// =========================================================\n\t// Override getTableData to incorporate primary-key cursor columns\n\t// =========================================================\n\n\toverride async getTableData(params: GetTableDataParams) {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tdb,\n\t\t\tlimit = 50,\n\t\t\tdirection = \"asc\",\n\t\t\tsort = [],\n\t\t\torder = \"asc\",\n\t\t\tcursor,\n\t\t\tfilters = [],\n\t\t} = params;\n\t\tconst pool = getDbPool(db);\n\n\t\t// Primary key columns for stable cursor pagination\n\t\tconst pkColumns = await this.getPrimaryKeyColumns(pool, tableName);\n\n\t\tlet sortColumns: string[] = [];\n\t\tlet effectiveSortDirection: SortDirection = order;\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t\teffectiveSortDirection = sort[0].direction;\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\n\t\tconst cursorColumns = [\n\t\t\t...sortColumns,\n\t\t\t...pkColumns.filter((pk) => !sortColumns.includes(pk)),\n\t\t];\n\t\tif (cursorColumns.length === 0) cursorColumns.push(\"ctid\");\n\n\t\tconst { clause: filterWhere, values: filterValues } = buildWhereClause(filters);\n\n\t\tlet cursorWhere = \"\";\n\t\tlet cursorValues: unknown[] = [];\n\t\tif (cursor) {\n\t\t\tconst cursorData = this.decodeCursor(cursor);\n\t\t\tif (cursorData) {\n\t\t\t\tconst res = buildCursorWhereClause(\n\t\t\t\t\tcursorData,\n\t\t\t\t\tdirection,\n\t\t\t\t\teffectiveSortDirection,\n\t\t\t\t\tfilterValues.length + 1,\n\t\t\t\t);\n\t\t\t\tcursorWhere = res.clause;\n\t\t\t\tcursorValues = res.values;\n\t\t\t}\n\t\t}\n\n\t\tlet combinedWhere = \"\";\n\t\tif (filterWhere && cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${filterWhere.replace(/^WHERE\\s+/i, \"\")} AND ${cursorWhere}`;\n\t\t} else if (filterWhere) {\n\t\t\tcombinedWhere = filterWhere;\n\t\t} else if (cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${cursorWhere}`;\n\t\t}\n\n\t\tconst sortClause = buildSortClause(Array.isArray(sort) ? sort : sort, order);\n\t\tlet effectiveSortClause = sortClause;\n\n\t\tif (direction === \"desc\") {\n\t\t\tif (sortClause) {\n\t\t\t\teffectiveSortClause = sortClause\n\t\t\t\t\t.replace(/\\bASC\\b/gi, \"TEMP_DESC\")\n\t\t\t\t\t.replace(/\\bDESC\\b/gi, \"ASC\")\n\t\t\t\t\t.replace(/TEMP_DESC/g, \"DESC\");\n\t\t\t} else {\n\t\t\t\tconst parts = cursorColumns.map(\n\t\t\t\t\t(col) => `\"${col}\" ${effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\"}`,\n\t\t\t\t);\n\t\t\t\teffectiveSortClause = `ORDER BY ${parts.join(\", \")}`;\n\t\t\t}\n\t\t} else if (!sortClause && cursorColumns.length > 0) {\n\t\t\tconst parts = cursorColumns.map(\n\t\t\t\t(col) => `\"${col}\" ${effectiveSortDirection.toUpperCase()}`,\n\t\t\t);\n\t\t\teffectiveSortClause = `ORDER BY ${parts.join(\", \")}`;\n\t\t}\n\n\t\tconst countRes = await pool.query(\n\t\t\t`SELECT COUNT(*) as total FROM \"${tableName}\" ${filterWhere}`,\n\t\t\tfilterValues,\n\t\t);\n\t\tconst total = Number(countRes.rows[0].total);\n\n\t\tconst limitParamIndex = filterValues.length + cursorValues.length + 1;\n\t\tconst dataRes = await pool.query(\n\t\t\t`SELECT * FROM \"${tableName}\" ${combinedWhere} ${effectiveSortClause} LIMIT $${limitParamIndex}`,\n\t\t\t[...filterValues, ...cursorValues, limit + 1],\n\t\t);\n\n\t\tconst hasColumns = dataRes.fields && dataRes.fields.length > 0;\n\t\tlet rows = hasColumns\n\t\t\t? dataRes.rows.filter((row) => Object.keys(row).length > 0)\n\t\t\t: dataRes.rows;\n\n\t\tconst hasMore = rows.length > limit;\n\t\tif (hasMore) rows = rows.slice(0, limit);\n\t\tif (direction === \"desc\") rows = rows.reverse();\n\n\t\tconst createCursor = (row: Record<string, unknown>): CursorData => ({\n\t\t\tvalues: Object.fromEntries(cursorColumns.map((col) => [col, row[col]])),\n\t\t\tsortColumns: cursorColumns,\n\t\t});\n\n\t\tlet nextCursor: string | null = null;\n\t\tlet prevCursor: string | null = null;\n\n\t\tif (rows.length > 0) {\n\t\t\tconst firstRow = rows[0];\n\t\t\tconst lastRow = rows[rows.length - 1];\n\t\t\tif (direction === \"asc\") {\n\t\t\t\tif (hasMore) nextCursor = this.encodeCursor(createCursor(lastRow));\n\t\t\t\tif (cursor) prevCursor = this.encodeCursor(createCursor(firstRow));\n\t\t\t} else {\n\t\t\t\tif (cursor) nextCursor = this.encodeCursor(createCursor(lastRow));\n\t\t\t\tif (hasMore) prevCursor = this.encodeCursor(createCursor(firstRow));\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tdata: rows,\n\t\t\tmeta: {\n\t\t\t\tlimit,\n\t\t\t\ttotal,\n\t\t\t\thasNextPage: direction === \"asc\" ? hasMore : !!cursor,\n\t\t\t\thasPreviousPage: direction === \"asc\" ? !!cursor : hasMore,\n\t\t\t\tnextCursor,\n\t\t\t\tprevCursor,\n\t\t\t},\n\t\t};\n\t}\n\n\t// =========================================================\n\t// IDbAdapter implementations\n\t// =========================================================\n\n\t// --- Databases ---\n\n\tasync getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst pool = getDbPool();\n\t\t\tconst { rows } = await pool.query(`\n\t\t\t\tSELECT\n\t\t\t\t\td.datname as name,\n\t\t\t\t\tpg_size_pretty(pg_database_size(d.datname)) as size,\n\t\t\t\t\tpg_catalog.pg_get_userbyid(d.datdba) as owner,\n\t\t\t\t\tpg_encoding_to_char(d.encoding) as encoding\n\t\t\t\tFROM pg_catalog.pg_database d\n\t\t\t\tWHERE d.datistemplate = false\n\t\t\t\t\tAND (d.datname NOT IN ('postgres', 'rdsadmin') OR d.datname = current_database())\n\t\t\t\tORDER BY d.datname;\n\t\t\t`);\n\t\t\tif (!rows[0])\n\t\t\t\tthrow new HTTPException(500, { message: \"No databases returned from database\" });\n\t\t\treturn rows;\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\tconst pool = getDbPool();\n\t\tconst { rows } = await pool.query(\"SELECT current_database() as database;\");\n\t\tif (!rows[0])\n\t\t\tthrow new HTTPException(500, { message: \"No current database returned from database\" });\n\t\treturn rows[0];\n\t}\n\n\tasync getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\tconst pool = getDbPool();\n\t\tconst { rows } = await pool.query(`\n\t\t\tSELECT\n\t\t\t\tversion() as version,\n\t\t\t\tcurrent_database() as database,\n\t\t\t\tcurrent_user as user,\n\t\t\t\tinet_server_addr() as host,\n\t\t\t\tinet_server_port() as port,\n\t\t\t\t(SELECT count(*) FROM pg_stat_activity WHERE datname = current_database()) as active_connections,\n\t\t\t\t(SELECT setting::int FROM pg_settings WHERE name = 'max_connections') as max_connections;\n\t\t`);\n\t\tif (!rows[0])\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: \"No connection information returned from database\",\n\t\t\t});\n\n\t\tconst { connectionInfoSchema } = await import(\"@db-studio/shared/types\");\n\t\tconst result = connectionInfoSchema.parse(rows[0]);\n\t\tconst urlDefaults = parseDatabaseUrl();\n\n\t\treturn {\n\t\t\thost: result.host || urlDefaults.host,\n\t\t\tport: result.port || urlDefaults.port,\n\t\t\tuser: result.user,\n\t\t\tdatabase: result.database,\n\t\t\tversion: result.version.toString(),\n\t\t\tactive_connections: result.active_connections,\n\t\t\tmax_connections: result.max_connections,\n\t\t};\n\t}\n\n\t// --- Tables ---\n\n\tasync getTablesList(db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\tconst pool = getDbPool(db);\n\t\tconst escapeChar = (s: string) => s.replaceAll('\"', '\"\"');\n\n\t\tconst { rows: tables } = await pool.query(`\n\t\t\tSELECT table_schema as \"schemaName\", table_name as \"tableName\"\n\t\t\tFROM information_schema.tables\n\t\t\tWHERE table_type = 'BASE TABLE'\n\t\t\t\tAND table_schema NOT IN ('pg_catalog', 'information_schema')\n\t\t\t\tAND table_schema NOT LIKE 'pg_toast%'\n\t\t\tORDER BY table_schema, table_name;\n\t\t`);\n\t\tif (!tables[0]) return [];\n\n\t\treturn Promise.all(\n\t\t\ttables.map(async (t: { schemaName: string; tableName: string }) => {\n\t\t\t\tconst { rows } = await pool.query(\n\t\t\t\t\t`SELECT COUNT(*)::integer as count FROM \"${escapeChar(t.schemaName)}\".\"${escapeChar(t.tableName)}\"`,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tschemaName: t.schemaName,\n\t\t\t\t\ttableName: t.tableName,\n\t\t\t\t\trowCount: rows[0]?.count ?? 0,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\t}\n\n\tasync createTable({\n\t\ttableData,\n\t\tdb,\n\t}: {\n\t\ttableData: CreateTableSchemaType;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<void> {\n\t\tconst { tableName, fields, foreignKeys } = tableData;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst columnDefs = fields.map((field: FieldDataType) => {\n\t\t\tlet def = `\"${field.columnName}\" ${field.columnType}`;\n\t\t\tif (field.isArray) def += \"[]\";\n\t\t\tif (field.isPrimaryKey) def += \" PRIMARY KEY\";\n\t\t\tif (field.isUnique && !field.isPrimaryKey) def += \" UNIQUE\";\n\t\t\tif (!field.isNullable) def += \" NOT NULL\";\n\t\t\tif (field.isIdentity) def += \" GENERATED ALWAYS AS IDENTITY\";\n\t\t\tif (field.defaultValue && !field.isIdentity) def += ` DEFAULT ${field.defaultValue}`;\n\t\t\treturn def;\n\t\t});\n\n\t\tconst fkDefs =\n\t\t\tforeignKeys?.map((fk: ForeignKeyDataType) => {\n\t\t\t\tconst name = `fk_${tableName}_${fk.columnName}_${fk.referencedTable}_${fk.referencedColumn}`;\n\t\t\t\treturn `CONSTRAINT \"${name}\" FOREIGN KEY (\"${fk.columnName}\") REFERENCES \"${fk.referencedTable}\" (\"${fk.referencedColumn}\") ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}`;\n\t\t\t}) ?? [];\n\n\t\tawait pool.query(\n\t\t\t`CREATE TABLE \"${tableName}\" (\\n\\t\\t\\t\\t${[...columnDefs, ...fkDefs].join(\",\\n\\t\\t\\t\\t\")}\\n\\t\\t\\t);`,\n\t\t);\n\t}\n\n\tasync deleteTable(params: DeleteTableParams): Promise<DeleteTableResult> {\n\t\tconst { tableName, db, cascade } = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst { rows: tableRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = ANY(current_schemas(false))) as exists;`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (!tableRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst rowCount = await this.getTableRowCount(pool, tableName);\n\n\t\tif (!cascade) {\n\t\t\tconst related = await this.getFkReferencesForTable(pool, tableName);\n\t\t\tif (related.length > 0)\n\t\t\t\treturn {\n\t\t\t\t\tdeletedCount: 0,\n\t\t\t\t\tfkViolation: true,\n\t\t\t\t\trelatedRecords: await this.getRelatedRecordsForTable(pool, tableName),\n\t\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tawait pool.query(`DROP TABLE \"${tableName}\" ${cascade ? \"CASCADE\" : \"RESTRICT\"}`);\n\t\t\treturn { deletedCount: rowCount, fkViolation: false, relatedRecords: [] };\n\t\t} catch (error) {\n\t\t\tconst pgErr = error as { code?: string };\n\t\t\tif (pgErr.code === \"2BP01\") {\n\t\t\t\treturn {\n\t\t\t\t\tdeletedCount: 0,\n\t\t\t\t\tfkViolation: true,\n\t\t\t\t\trelatedRecords: await this.getRelatedRecordsForTable(pool, tableName),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to delete table \"${tableName}\"` });\n\t\t}\n\t}\n\n\tasync renameTable(params: RenameTableParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, newTableName, schemaName: requestedSchema, db } = params;\n\t\t\tthis.assertDifferentTableName(tableName, newTableName);\n\t\t\tconst pool = getDbPool(db);\n\n\t\t\t// Tables are listed from every user schema, so resolve the actual schema\n\t\t\t// instead of assuming \"public\".\n\t\t\tconst { rows: schemaRows } = await pool.query(\n\t\t\t\t`SELECT table_schema as \"schemaName\" FROM information_schema.tables WHERE table_name = $1 AND table_schema NOT IN ('pg_catalog', 'information_schema') AND table_schema NOT LIKE 'pg_toast%';`,\n\t\t\t\t[tableName],\n\t\t\t);\n\t\t\tconst schemas = (schemaRows as Array<{ schemaName: string }>).map((r) => r.schemaName);\n\t\t\tif (schemas.length === 0)\n\t\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t\tif (requestedSchema && !schemas.includes(requestedSchema)) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Table \"${requestedSchema}\".\"${tableName}\" does not exist`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!requestedSchema && schemas.length > 1)\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Table \"${tableName}\" exists in multiple schemas (${schemas.join(\", \")}); rename is ambiguous`,\n\t\t\t\t});\n\t\t\tconst schemaName = requestedSchema ?? (schemas[0] as string);\n\n\t\t\tconst { rows: targetRows } = await pool.query(\n\t\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = $2) as exists;`,\n\t\t\t\t[newTableName, schemaName],\n\t\t\t);\n\t\t\tif (targetRows[0]?.exists)\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Table \"${newTableName}\" already exists`,\n\t\t\t\t});\n\n\t\t\tawait pool.query(\n\t\t\t\t`ALTER TABLE \"${schemaName.replaceAll('\"', '\"\"')}\".\"${tableName.replaceAll('\"', '\"\"')}\" RENAME TO \"${newTableName.replaceAll('\"', '\"\"')}\"`,\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getTableSchema({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\tconst pool = getDbPool(db);\n\n\t\tconst { rows: existsRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = ANY(current_schemas(false)) AND table_name = $1) as exists`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (!existsRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tinterface ColumnInfo {\n\t\t\tcolumn_name: string;\n\t\t\tdata_type: string;\n\t\t\tudt_name: string;\n\t\t\tis_nullable: string;\n\t\t\tcolumn_default: string | null;\n\t\t\tcharacter_maximum_length: number | null;\n\t\t\tnumeric_precision: number | null;\n\t\t\tnumeric_scale: number | null;\n\t\t}\n\t\tinterface ConstraintInfo {\n\t\t\tconstraint_name: string;\n\t\t\tconstraint_type: string;\n\t\t\tcolumn_name: string;\n\t\t\tforeign_table_name: string | null;\n\t\t\tforeign_column_name: string | null;\n\t\t}\n\t\tinterface IndexInfo {\n\t\t\tindexname: string;\n\t\t\tindexdef: string;\n\t\t}\n\n\t\tconst { rows: columns } = await pool.query<ColumnInfo>(\n\t\t\t`SELECT column_name, data_type, udt_name, is_nullable, column_default, character_maximum_length, numeric_precision, numeric_scale\n\t\t\t FROM information_schema.columns WHERE table_schema = ${resolvedSchemaFor(\"$1\")} AND table_name = $1 ORDER BY ordinal_position`,\n\t\t\t[tableName],\n\t\t);\n\n\t\tconst { rows: constraints } = await pool.query<ConstraintInfo>(\n\t\t\t`SELECT tc.constraint_name, tc.constraint_type, kcu.column_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name\n\t\t\t FROM information_schema.table_constraints tc\n\t\t\t JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema\n\t\t\t LEFT JOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name AND tc.table_schema = ccu.table_schema AND tc.constraint_type = 'FOREIGN KEY'\n\t\t\t WHERE tc.table_schema = ${resolvedSchemaFor(\"$1\")} AND tc.table_name = $1 ORDER BY tc.constraint_type, tc.constraint_name`,\n\t\t\t[tableName],\n\t\t);\n\n\t\tconst { rows: indexes } = await pool.query<IndexInfo>(\n\t\t\t`SELECT indexname, indexdef FROM pg_indexes WHERE schemaname = ${resolvedSchemaFor(\"$1\")} AND tablename = $1\n\t\t\t AND indexname NOT IN (SELECT constraint_name FROM information_schema.table_constraints WHERE table_schema = ${resolvedSchemaFor(\"$1\")} AND table_name = $1 AND constraint_type = 'PRIMARY KEY')`,\n\t\t\t[tableName],\n\t\t);\n\n\t\tconst formatType = (col: ColumnInfo): string => {\n\t\t\tconst {\n\t\t\t\tdata_type,\n\t\t\t\tudt_name,\n\t\t\t\tcharacter_maximum_length,\n\t\t\t\tnumeric_precision,\n\t\t\t\tnumeric_scale,\n\t\t\t} = col;\n\t\t\tif (data_type === \"USER-DEFINED\") return udt_name;\n\t\t\tif (data_type === \"ARRAY\") return `${udt_name.replace(/^_/, \"\")}[]`;\n\t\t\tif (\n\t\t\t\t(data_type === \"character varying\" || data_type === \"varchar\") &&\n\t\t\t\tcharacter_maximum_length\n\t\t\t)\n\t\t\t\treturn `varchar(${character_maximum_length})`;\n\t\t\tif (data_type === \"character\" && character_maximum_length)\n\t\t\t\treturn `char(${character_maximum_length})`;\n\t\t\tif (data_type === \"numeric\" && numeric_precision !== null) {\n\t\t\t\treturn numeric_scale !== null && numeric_scale > 0\n\t\t\t\t\t? `numeric(${numeric_precision}, ${numeric_scale})`\n\t\t\t\t\t: `numeric(${numeric_precision})`;\n\t\t\t}\n\t\t\tif (data_type === \"timestamp with time zone\") return \"timestamp with time zone\";\n\t\t\tif (data_type === \"timestamp without time zone\") return \"timestamp\";\n\t\t\tconst typeMap: Record<string, string> = {\n\t\t\t\t\"character varying\": \"varchar\",\n\t\t\t\tcharacter: \"char\",\n\t\t\t\t\"double precision\": \"float8\",\n\t\t\t\tinteger: \"integer\",\n\t\t\t\tbigint: \"bigint\",\n\t\t\t\tsmallint: \"smallint\",\n\t\t\t\tboolean: \"boolean\",\n\t\t\t\ttext: \"text\",\n\t\t\t\tuuid: \"uuid\",\n\t\t\t\tjson: \"json\",\n\t\t\t\tjsonb: \"jsonb\",\n\t\t\t\tdate: \"date\",\n\t\t\t\ttime: \"time\",\n\t\t\t\tbytea: \"bytea\",\n\t\t\t};\n\t\t\treturn typeMap[data_type] || data_type;\n\t\t};\n\n\t\tconst lines: string[] = [`create table public.${tableName} (`];\n\t\tconst colDefs = columns.map((col) => {\n\t\t\tlet def = ` ${col.column_name} ${formatType(col)}`;\n\t\t\tif (col.is_nullable === \"NO\") def += \" not null\";\n\t\t\tif (col.column_default !== null) def += ` default ${col.column_default}`;\n\t\t\treturn def;\n\t\t});\n\n\t\tconst constraintMap = new Map<string, ConstraintInfo[]>();\n\t\tfor (const c of constraints) {\n\t\t\tconst arr = constraintMap.get(c.constraint_name) ?? [];\n\t\t\tarr.push(c);\n\t\t\tconstraintMap.set(c.constraint_name, arr);\n\t\t}\n\n\t\tconst constraintDefs: string[] = [];\n\t\tfor (const [name, cols] of constraintMap) {\n\t\t\tconst first = cols[0];\n\t\t\tconst colNames = cols.map((c) => c.column_name).join(\", \");\n\t\t\tif (first.constraint_type === \"PRIMARY KEY\") {\n\t\t\t\tconstraintDefs.push(` constraint ${name} primary key (${colNames})`);\n\t\t\t} else if (first.constraint_type === \"FOREIGN KEY\") {\n\t\t\t\tconstraintDefs.push(\n\t\t\t\t\t` constraint ${name} foreign key (${colNames}) references ${first.foreign_table_name} (${first.foreign_column_name})`,\n\t\t\t\t);\n\t\t\t} else if (first.constraint_type === \"UNIQUE\") {\n\t\t\t\tconstraintDefs.push(` constraint ${name} unique (${colNames})`);\n\t\t\t}\n\t\t}\n\n\t\tlines.push([...colDefs, ...constraintDefs].join(\",\\n\"));\n\t\tlines.push(\") tablespace pg_default;\");\n\n\t\tfor (const idx of indexes) {\n\t\t\tconst isUnique = [...constraintMap.values()].some(\n\t\t\t\t(c) => c[0].constraint_type === \"UNIQUE\" && c[0].constraint_name === idx.indexname,\n\t\t\t);\n\t\t\tif (!isUnique) {\n\t\t\t\tlines.push(\"\");\n\t\t\t\tlines.push(`${idx.indexdef};`);\n\t\t\t}\n\t\t}\n\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\t// --- Columns ---\n\n\tasync getTableColumns({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\tconst pool = getDbPool(db);\n\t\tconst { rows } = await pool.query(\n\t\t\t`SELECT\n\t\t\t\tc.column_name as \"columnName\", c.data_type as \"dataType\", c.udt_name as \"udtName\",\n\t\t\t\tc.is_nullable = 'YES' as \"isNullable\", c.column_default as \"columnDefault\",\n\t\t\t\tCASE WHEN pk.column_name IS NOT NULL THEN true ELSE false END as \"isPrimaryKey\",\n\t\t\t\tCASE WHEN fk.column_name IS NOT NULL THEN true ELSE false END as \"isForeignKey\",\n\t\t\t\tfk.referenced_table as \"referencedTable\", fk.referenced_column as \"referencedColumn\",\n\t\t\t\tCASE WHEN c.data_type = 'USER-DEFINED' THEN\n\t\t\t\t\t(SELECT array_agg(e.enumlabel ORDER BY e.enumsortorder) FROM pg_type t JOIN pg_enum e ON t.oid = e.enumtypid WHERE t.typname = c.udt_name)\n\t\t\t\tELSE NULL END as \"enumValues\"\n\t\t\tFROM information_schema.columns c\n\t\t\tLEFT JOIN (\n\t\t\t\tSELECT ku.column_name FROM information_schema.table_constraints tc\n\t\t\t\tJOIN information_schema.key_column_usage ku ON tc.constraint_name = ku.constraint_name AND tc.table_schema = ku.table_schema\n\t\t\t\tWHERE tc.constraint_type = 'PRIMARY KEY' AND tc.table_schema = ${resolvedSchemaFor(\"$1\")} AND tc.table_name = $1\n\t\t\t) pk ON c.column_name = pk.column_name\n\t\t\tLEFT JOIN (\n\t\t\t\tSELECT kcu.column_name, ccu.table_name AS referenced_table, ccu.column_name AS referenced_column\n\t\t\t\tFROM information_schema.table_constraints tc\n\t\t\t\tJOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema\n\t\t\t\tJOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name AND tc.table_schema = ccu.table_schema\n\t\t\t\tWHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_schema = ${resolvedSchemaFor(\"$1\")} AND tc.table_name = $1\n\t\t\t) fk ON c.column_name = fk.column_name\n\t\t\tWHERE c.table_schema = ${resolvedSchemaFor(\"$1\")} AND c.table_name = $1 ORDER BY c.ordinal_position;`,\n\t\t\t[tableName],\n\t\t);\n\n\t\tif (!rows || rows.length === 0)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\treturn rows.map((r) => {\n\t\t\tlet parsedEnumValues: string[] | null = null;\n\t\t\tif (r.enumValues) {\n\t\t\t\tif (Array.isArray(r.enumValues)) {\n\t\t\t\t\tparsedEnumValues = r.enumValues;\n\t\t\t\t} else if (typeof r.enumValues === \"string\") {\n\t\t\t\t\tparsedEnumValues = r.enumValues.replace(/[{}]/g, \"\").split(\",\").filter(Boolean);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcolumnName: r.columnName,\n\t\t\t\tdataType: mapPostgresToDataType(r.dataType),\n\t\t\t\tdataTypeLabel: standardizeDataTypeLabel(r.dataType),\n\t\t\t\tisNullable: r.isNullable,\n\t\t\t\tcolumnDefault: r.columnDefault,\n\t\t\t\tisPrimaryKey: r.isPrimaryKey,\n\t\t\t\tisForeignKey: r.isForeignKey,\n\t\t\t\treferencedTable: r.referencedTable,\n\t\t\t\treferencedColumn: r.referencedColumn,\n\t\t\t\tenumValues: parsedEnumValues,\n\t\t\t};\n\t\t});\n\t}\n\n\tasync addColumn(params: AddColumnParamsSchemaType): Promise<void> {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tcolumnName,\n\t\t\tcolumnType,\n\t\t\tdefaultValue,\n\t\t\tisPrimaryKey,\n\t\t\tisNullable,\n\t\t\tisUnique,\n\t\t\tisIdentity,\n\t\t\tisArray,\n\t\t\tdb,\n\t\t} = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst { rows: tableRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = ANY(current_schemas(false))) as exists;`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (!tableRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst { rows: colRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = $1 AND column_name = $2 AND table_schema = ${resolvedSchemaFor(\"$1\")}) as exists;`,\n\t\t\t[tableName, columnName],\n\t\t);\n\t\tif (colRows[0]?.exists)\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${columnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\n\t\tlet def = `\"${columnName}\" ${columnType}`;\n\t\tif (isArray) def += \"[]\";\n\t\tif (isPrimaryKey) def += \" PRIMARY KEY\";\n\t\tif (isUnique && !isPrimaryKey) def += \" UNIQUE\";\n\t\tif (!isNullable) def += \" NOT NULL\";\n\t\tif (isIdentity) def += \" GENERATED ALWAYS AS IDENTITY\";\n\t\tif (defaultValue?.trim() && !isIdentity) def += ` DEFAULT ${defaultValue.trim()}`;\n\n\t\tawait pool.query(`ALTER TABLE \"${tableName}\" ADD COLUMN ${def}`);\n\t}\n\n\tasync deleteColumn(params: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\tconst { tableName, columnName, cascade, db } = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst { rows: tableRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = ANY(current_schemas(false))) as exists;`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (!tableRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst { rows: colRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = $1 AND column_name = $2 AND table_schema = ${resolvedSchemaFor(\"$1\")}) as exists;`,\n\t\t\t[tableName, columnName],\n\t\t);\n\t\tif (!colRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\n\t\tconst { rowCount } = await pool.query(\n\t\t\t`ALTER TABLE \"${tableName}\" DROP COLUMN \"${columnName}\" ${cascade ? \"CASCADE\" : \"RESTRICT\"}`,\n\t\t);\n\t\treturn { deletedCount: rowCount ?? 0 };\n\t}\n\n\tasync alterColumn(params: AlterColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, columnType, isNullable, defaultValue, db } = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst { rows: tableRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = ANY(current_schemas(false))) as exists;`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (!tableRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst { rows: colRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = $1 AND column_name = $2 AND table_schema = ${resolvedSchemaFor(\"$1\")}) as exists;`,\n\t\t\t[tableName, columnName],\n\t\t);\n\t\tif (!colRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\n\t\tconst client = await pool.connect();\n\t\ttry {\n\t\t\tawait client.query(\"BEGIN\");\n\t\t\tawait client.query(\n\t\t\t\t`ALTER TABLE \"${tableName}\" ALTER COLUMN \"${columnName}\" TYPE ${columnType}`,\n\t\t\t);\n\t\t\tawait client.query(\n\t\t\t\t`ALTER TABLE \"${tableName}\" ALTER COLUMN \"${columnName}\" ${isNullable ? \"DROP\" : \"SET\"} NOT NULL`,\n\t\t\t);\n\t\t\tif (defaultValue?.trim()) {\n\t\t\t\tawait client.query(\n\t\t\t\t\t`ALTER TABLE \"${tableName}\" ALTER COLUMN \"${columnName}\" SET DEFAULT ${defaultValue.trim()}`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tawait client.query(\n\t\t\t\t\t`ALTER TABLE \"${tableName}\" ALTER COLUMN \"${columnName}\" DROP DEFAULT`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait client.query(\"COMMIT\");\n\t\t} catch (error) {\n\t\t\tawait client.query(\"ROLLBACK\");\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tclient.release();\n\t\t}\n\t}\n\n\tasync renameColumn(params: RenameColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, newColumnName, db } = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst colExistsQuery = `SELECT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = $1 AND column_name = $2 AND table_schema = ${resolvedSchemaFor(\"$1\")}) as exists;`;\n\n\t\tconst { rows: tableRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = ANY(current_schemas(false))) as exists;`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (!tableRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst { rows: curRows } = await pool.query(colExistsQuery, [tableName, columnName]);\n\t\tif (!curRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\n\t\tconst { rows: nextRows } = await pool.query(colExistsQuery, [tableName, newColumnName]);\n\t\tif (nextRows[0]?.exists)\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${newColumnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\n\t\tawait pool.query(\n\t\t\t`ALTER TABLE \"${tableName}\" RENAME COLUMN \"${columnName}\" TO \"${newColumnName}\"`,\n\t\t);\n\t}\n\n\t// --- Records ---\n\n\tasync addRecord({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\tconst { tableName, data } = params;\n\t\tconst pool = getDbPool(db);\n\t\tconst columns = Object.keys(data);\n\t\tconst values = Object.values(data);\n\t\tconst placeholders = columns.map((_, i) => `$${i + 1}`).join(\", \");\n\t\tconst colNames = columns.map((c) => `\"${c}\"`).join(\", \");\n\t\tconst result = await pool.query(\n\t\t\t`INSERT INTO \"${tableName}\" (${colNames}) VALUES (${placeholders}) RETURNING *`,\n\t\t\tvalues,\n\t\t);\n\t\tif (result.rowCount === 0)\n\t\t\tthrow new HTTPException(500, { message: `Failed to insert record into \"${tableName}\"` });\n\t\treturn { insertedCount: result.rowCount ?? 0 };\n\t}\n\n\tasync updateRecords({\n\t\tparams,\n\t\tdb,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\tconst { tableName } = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst keyColumns = this.resolveKeyColumns(params);\n\t\tconst groups = this.groupUpdatesByKey(params, keyColumns);\n\n\t\tawait pool.query(\"BEGIN\");\n\t\ttry {\n\t\t\tlet total = 0;\n\t\t\tfor (const { keyValues, rowUpdates } of groups) {\n\t\t\t\tconst setClauses = rowUpdates.map((u, i) => `\"${u.columnName}\" = $${i + 1}`);\n\t\t\t\tconst values = rowUpdates.map((u) =>\n\t\t\t\t\tu.value !== null && typeof u.value === \"object\" ? JSON.stringify(u.value) : u.value,\n\t\t\t\t);\n\t\t\t\tconst whereClauses = keyColumns.map(\n\t\t\t\t\t(column, i) => `\"${column}\" = $${values.length + i + 1}`,\n\t\t\t\t);\n\t\t\t\tvalues.push(...keyValues);\n\t\t\t\tconst result = await pool.query(\n\t\t\t\t\t`UPDATE \"${tableName}\" SET ${setClauses.join(\", \")} WHERE ${whereClauses.join(\" AND \")} RETURNING *`,\n\t\t\t\t\tvalues,\n\t\t\t\t);\n\t\t\t\tif (result.rowCount === 0)\n\t\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\t\tmessage: `Record with ${this.describeKey(keyColumns, keyValues)} not found in table \"${tableName}\"`,\n\t\t\t\t\t});\n\t\t\t\ttotal += result.rowCount ?? 0;\n\t\t\t}\n\t\t\tawait pool.query(\"COMMIT\");\n\t\t\treturn { updatedCount: total };\n\t\t} catch (error) {\n\t\t\tawait pool.query(\"ROLLBACK\");\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to update records in \"${tableName}\"` });\n\t\t}\n\t}\n\n\tasync deleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\tconst pool = getDbPool(db);\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst placeholders = pkValues.map((_, i) => `$${i + 1}`).join(\", \");\n\n\t\ttry {\n\t\t\tawait pool.query(\"BEGIN\");\n\t\t\tconst result = await pool.query(\n\t\t\t\t`DELETE FROM \"${tableName}\" WHERE \"${pkColumn}\" IN (${placeholders}) RETURNING *`,\n\t\t\t\tpkValues,\n\t\t\t);\n\t\t\tawait pool.query(\"COMMIT\");\n\t\t\treturn { deletedCount: result.rowCount ?? 0, fkViolation: false, relatedRecords: [] };\n\t\t} catch (error) {\n\t\t\tawait pool.query(\"ROLLBACK\");\n\t\t\tconst pgErr = error as { code?: string };\n\t\t\tif (pgErr.code === \"23503\") {\n\t\t\t\tconst relatedRecords = await this.getRelatedRecords(pool, tableName, primaryKeys, db);\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to delete records from \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\tasync forceDeleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<{ deletedCount: number }> {\n\t\tconst pool = getDbPool(db);\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tawait pool.query(\"BEGIN\");\n\n\t\ttry {\n\t\t\tconst fkConstraints = await this.getFkConstraints(pool, tableName);\n\t\t\tlet totalRelated = 0;\n\t\t\tconst deletedTables = new Set<string>();\n\n\t\t\tconst deleteRelated = async (\n\t\t\t\ttargetTable: string,\n\t\t\t\ttargetColumn: string,\n\t\t\t\tvalues: unknown[],\n\t\t\t) => {\n\t\t\t\tconst nested = await this.getFkConstraints(pool, targetTable);\n\t\t\t\tfor (const nfk of nested) {\n\t\t\t\t\tconst placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n\t\t\t\t\tconst { rows } = await pool.query(\n\t\t\t\t\t\t`SELECT \"${nfk.referencedColumn}\" FROM \"${targetTable}\" WHERE \"${targetColumn}\" IN (${placeholders})`,\n\t\t\t\t\t\tvalues,\n\t\t\t\t\t);\n\t\t\t\t\tconst nestedVals = rows.map((r: Record<string, unknown>) => r[nfk.referencedColumn]);\n\t\t\t\t\tif (nestedVals.length > 0)\n\t\t\t\t\t\tawait deleteRelated(nfk.referencingTable, nfk.referencingColumn, nestedVals);\n\t\t\t\t}\n\t\t\t\tconst ph = values.map((_, i) => `$${i + 1}`).join(\", \");\n\t\t\t\tconst res = await pool.query(\n\t\t\t\t\t`DELETE FROM \"${targetTable}\" WHERE \"${targetColumn}\" IN (${ph})`,\n\t\t\t\t\tvalues,\n\t\t\t\t);\n\t\t\t\ttotalRelated += res.rowCount ?? 0;\n\t\t\t\tdeletedTables.add(targetTable);\n\t\t\t};\n\n\t\t\tfor (const c of fkConstraints) {\n\t\t\t\tif (!deletedTables.has(c.referencingTable))\n\t\t\t\t\tawait deleteRelated(c.referencingTable, c.referencingColumn, pkValues);\n\t\t\t}\n\n\t\t\tconst ph = pkValues.map((_, i) => `$${i + 1}`).join(\", \");\n\t\t\tconst result = await pool.query(\n\t\t\t\t`DELETE FROM \"${tableName}\" WHERE \"${pkColumn}\" IN (${ph}) RETURNING *`,\n\t\t\t\tpkValues,\n\t\t\t);\n\t\t\tawait pool.query(\"COMMIT\");\n\t\t\treturn { deletedCount: (result.rowCount ?? 0) + totalRelated };\n\t\t} catch (error) {\n\t\t\tawait pool.query(\"ROLLBACK\");\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to force delete records from \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\tasync bulkInsertRecords({\n\t\ttableName,\n\t\trecords,\n\t\tdb,\n\t}: BulkInsertRecordsParams): Promise<BulkInsertResult> {\n\t\tif (!records || records.length === 0)\n\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\n\t\tconst pool = getDbPool(db);\n\t\tconst client = await pool.connect();\n\n\t\ttry {\n\t\t\tconst columns = Object.keys(records[0]);\n\t\t\tconst colNames = columns.map((c) => `\"${c}\"`).join(\", \");\n\t\t\tlet successCount = 0;\n\n\t\t\tawait client.query(\"BEGIN\");\n\t\t\tfor (const record of records) {\n\t\t\t\tconst values = columns.map((col) => record[col]);\n\t\t\t\tconst placeholders = columns.map((_, i) => `$${i + 1}`).join(\", \");\n\t\t\t\ttry {\n\t\t\t\t\tawait client.query(\n\t\t\t\t\t\t`INSERT INTO \"${tableName}\" (${colNames}) VALUES (${placeholders}) RETURNING *`,\n\t\t\t\t\t\tvalues,\n\t\t\t\t\t);\n\t\t\t\t\tsuccessCount++;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new HTTPException(500, {\n\t\t\t\t\t\tmessage: `Failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait client.query(\"COMMIT\");\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `Bulk insert completed: ${successCount} records inserted`,\n\t\t\t\tsuccessCount,\n\t\t\t\tfailureCount: 0,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tawait client.query(\"ROLLBACK\");\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to bulk insert records into \"${tableName}\"`,\n\t\t\t});\n\t\t} finally {\n\t\t\tclient.release();\n\t\t}\n\t}\n\n\t// --- Query ---\n\n\tasync executeQuery({\n\t\tquery,\n\t\tdb,\n\t}: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\tconst pool = getDbPool(db);\n\t\tif (!query?.trim()) throw new HTTPException(400, { message: \"Query is required\" });\n\t\tconst cleaned = query.trim().replace(/;+$/, \"\");\n\t\tconst start = performance.now();\n\t\tconst result = await pool.query(cleaned);\n\t\tconst duration = performance.now() - start;\n\t\treturn {\n\t\t\tcolumns: result.fields.map((f) => f.name),\n\t\t\trows: result.rows,\n\t\t\trowCount: result.rows.length,\n\t\t\tduration,\n\t\t\tmessage: result.rows.length === 0 ? \"OK\" : undefined,\n\t\t};\n\t}\n\n\t// =========================================================\n\t// Private helpers\n\t// =========================================================\n\n\tprivate async getPrimaryKeyColumns(pool: PgPool, tableName: string): Promise<string[]> {\n\t\tconst result = await pool.query(\n\t\t\t`SELECT a.attname as column_name\n\t\t\t FROM pg_index i\n\t\t\t JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)\n\t\t\t WHERE i.indrelid = $1::regclass AND i.indisprimary\n\t\t\t ORDER BY array_position(i.indkey, a.attnum)`,\n\t\t\t[`\"${tableName}\"`],\n\t\t);\n\t\treturn result.rows.map((row) => row.column_name);\n\t}\n\n\tprivate async getFkConstraints(\n\t\tpool: PgPool,\n\t\ttableName: string,\n\t): Promise<ForeignKeyConstraint[]> {\n\t\tconst { rows } = await pool.query(\n\t\t\t`SELECT tc.constraint_name, tc.table_name as referencing_table, kcu.column_name as referencing_column,\n\t\t\t\tccu.table_name AS referenced_table, ccu.column_name AS referenced_column\n\t\t\t FROM information_schema.table_constraints AS tc\n\t\t\t JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema\n\t\t\t JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name AND ccu.table_schema = tc.table_schema\n\t\t\t WHERE tc.constraint_type = 'FOREIGN KEY' AND ccu.table_name = $1`,\n\t\t\t[tableName],\n\t\t);\n\t\treturn rows.map((row: ForeignKeyConstraintRow) => ({\n\t\t\tconstraintName: row.constraint_name,\n\t\t\treferencingTable: row.referencing_table,\n\t\t\treferencingColumn: row.referencing_column,\n\t\t\treferencedTable: row.referenced_table,\n\t\t\treferencedColumn: row.referenced_column,\n\t\t}));\n\t}\n\n\tprivate async getFkReferencesForTable(\n\t\tpool: PgPool,\n\t\ttableName: string,\n\t): Promise<ForeignKeyConstraint[]> {\n\t\treturn this.getFkConstraints(pool, tableName);\n\t}\n\n\tprivate async getRelatedRecordsForTable(\n\t\tpool: PgPool,\n\t\ttableName: string,\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getFkReferencesForTable(pool, tableName);\n\t\tif (fks.length === 0) return [];\n\t\tconst results: RelatedRecord[] = [];\n\t\tfor (const fk of fks) {\n\t\t\tconst { rows } = await pool.query(`SELECT * FROM \"${fk.referencingTable}\" LIMIT 100`);\n\t\t\tif (rows.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: rows,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate async getRelatedRecords(\n\t\tpool: PgPool,\n\t\ttableName: string,\n\t\tprimaryKeys: DeleteRecordSchemaType[\"primaryKeys\"],\n\t\tdb: DatabaseSchemaType[\"db\"],\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getFkConstraints(pool, tableName);\n\t\tif (fks.length === 0) return [];\n\n\t\tconst results: RelatedRecord[] = [];\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst constraintsByTable = new Map<string, ForeignKeyConstraint[]>();\n\t\tfor (const fk of fks) {\n\t\t\tconst key = `${fk.referencingTable}.${fk.referencingColumn}`;\n\t\t\tconst arr = constraintsByTable.get(key) ?? [];\n\t\t\tarr.push(fk);\n\t\t\tconstraintsByTable.set(key, arr);\n\t\t}\n\n\t\tfor (const [, constraints] of constraintsByTable) {\n\t\t\tconst fk = constraints[0];\n\t\t\tif (!fk) continue;\n\t\t\tconst matchingPk = primaryKeys.find((pk) => pk.columnName === fk.referencedColumn);\n\t\t\tif (!matchingPk) continue;\n\t\t\tconst ph = pkValues.map((_, i) => `$${i + 1}`).join(\", \");\n\t\t\tconst { rows } = await pool.query(\n\t\t\t\t`SELECT * FROM \"${fk.referencingTable}\" WHERE \"${fk.referencingColumn}\" IN (${ph}) LIMIT 100`,\n\t\t\t\tpkValues,\n\t\t\t);\n\t\t\tif (rows.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: rows,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tvoid db;\n\t\treturn results;\n\t}\n\n\tprivate async getTableRowCount(pool: PgPool, tableName: string): Promise<number> {\n\t\tconst { rows } = await pool.query(`SELECT COUNT(*) as count FROM \"${tableName}\"`);\n\t\treturn Number.parseInt(rows[0]?.count ?? \"0\", 10);\n\t}\n}\n","import type { ExecuteQueryResult } from \"@db-studio/shared/types\";\n\ntype ShapeFn = (reply: unknown) => Pick<ExecuteQueryResult, \"columns\" | \"rows\" | \"rowCount\">;\n\nconst isStringArray = (v: unknown): v is string[] =>\n\tArray.isArray(v) && v.every((x) => typeof x === \"string\" || x === null);\n\nconst isFlatPairArray = (v: unknown): v is unknown[] => Array.isArray(v) && v.length % 2 === 0;\n\n/**\n * Tokenize a redis-cli style command line into an argv array.\n * Supports single and double quotes; backslash-escapes inside double quotes.\n *\n * Examples:\n * \"GET foo\" -> [\"GET\", \"foo\"]\n * 'SET foo \"hello world\"' -> [\"SET\", \"foo\", \"hello world\"]\n * \"HSET k field 'value with space'\" -> [\"HSET\", \"k\", \"field\", \"value with space\"]\n */\nexport function tokenizeCommand(input: string): string[] {\n\tconst out: string[] = [];\n\tlet cur = \"\";\n\tlet i = 0;\n\tlet inSingle = false;\n\tlet inDouble = false;\n\n\twhile (i < input.length) {\n\t\tconst ch = input[i];\n\n\t\tif (inSingle) {\n\t\t\tif (ch === \"'\") inSingle = false;\n\t\t\telse cur += ch;\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (inDouble) {\n\t\t\tif (ch === \"\\\\\" && i + 1 < input.length) {\n\t\t\t\tcur += input[i + 1];\n\t\t\t\ti += 2;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (ch === '\"') inDouble = false;\n\t\t\telse cur += ch;\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (ch === \"'\") {\n\t\t\tinSingle = true;\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '\"') {\n\t\t\tinDouble = true;\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === \" \" || ch === \"\\t\" || ch === \"\\n\") {\n\t\t\tif (cur.length > 0) {\n\t\t\t\tout.push(cur);\n\t\t\t\tcur = \"\";\n\t\t\t}\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tcur += ch;\n\t\ti++;\n\t}\n\n\tif (inSingle || inDouble) {\n\t\tthrow new Error(\"Unterminated quoted string in command\");\n\t}\n\tif (cur.length > 0) out.push(cur);\n\treturn out;\n}\n\nconst singleCellFallback: ShapeFn = (reply) => ({\n\tcolumns: [\"result\"],\n\trows: [{ result: typeof reply === \"string\" ? reply : JSON.stringify(reply, null, 2) }],\n\trowCount: 1,\n});\n\nconst scalarShape: ShapeFn = (reply) => {\n\tif (reply === null) {\n\t\treturn {\n\t\t\tcolumns: [\"value\"],\n\t\t\trows: [{ value: null }],\n\t\t\trowCount: 0,\n\t\t};\n\t}\n\treturn {\n\t\tcolumns: [\"value\"],\n\t\trows: [{ value: reply as string | number }],\n\t\trowCount: 1,\n\t};\n};\n\nconst statusShape: ShapeFn = (reply) => ({\n\tcolumns: [\"status\"],\n\trows: [{ status: reply as string }],\n\trowCount: 1,\n});\n\nconst flatArrayShape: ShapeFn = (reply) => {\n\tif (!Array.isArray(reply)) return singleCellFallback(reply);\n\treturn {\n\t\tcolumns: [\"#\", \"value\"],\n\t\trows: reply.map((v, idx) => ({ \"#\": idx, value: v as unknown })),\n\t\trowCount: reply.length,\n\t};\n};\n\nconst pairArrayShape: ShapeFn = (reply) => {\n\tif (!isFlatPairArray(reply)) return singleCellFallback(reply);\n\tconst rows: Record<string, unknown>[] = [];\n\tfor (let i = 0; i < reply.length; i += 2) {\n\t\trows.push({ field: reply[i], value: reply[i + 1] });\n\t}\n\treturn { columns: [\"field\", \"value\"], rows, rowCount: rows.length };\n};\n\nconst zrangeWithScoresShape: ShapeFn = (reply) => {\n\tif (!isFlatPairArray(reply)) return flatArrayShape(reply);\n\tconst rows: Record<string, unknown>[] = [];\n\tfor (let i = 0; i < reply.length; i += 2) {\n\t\trows.push({ member: reply[i], score: reply[i + 1] });\n\t}\n\treturn { columns: [\"member\", \"score\"], rows, rowCount: rows.length };\n};\n\nconst infoShape: ShapeFn = (reply) => {\n\tif (typeof reply !== \"string\") return singleCellFallback(reply);\n\tconst rows: Record<string, unknown>[] = [];\n\tlet section = \"\";\n\tfor (const line of reply.split(/\\r?\\n/)) {\n\t\tif (!line.trim()) continue;\n\t\tif (line.startsWith(\"#\")) {\n\t\t\tsection = line.replace(/^#\\s*/, \"\").trim();\n\t\t\tcontinue;\n\t\t}\n\t\tconst idx = line.indexOf(\":\");\n\t\tif (idx < 0) continue;\n\t\trows.push({ section, key: line.slice(0, idx), value: line.slice(idx + 1) });\n\t}\n\treturn { columns: [\"section\", \"key\", \"value\"], rows, rowCount: rows.length };\n};\n\nconst xrangeShape: ShapeFn = (reply) => {\n\tif (!Array.isArray(reply)) return singleCellFallback(reply);\n\tconst rows = reply.map((entry) => {\n\t\tif (!Array.isArray(entry) || entry.length < 2) return { id: null, fields: null };\n\t\tconst [id, fields] = entry;\n\t\tconst fieldsObj: Record<string, unknown> = {};\n\t\tif (Array.isArray(fields)) {\n\t\t\tfor (let i = 0; i < fields.length; i += 2) {\n\t\t\t\tfieldsObj[String(fields[i])] = fields[i + 1];\n\t\t\t}\n\t\t}\n\t\treturn { id, fields: fieldsObj };\n\t});\n\treturn { columns: [\"id\", \"fields\"], rows, rowCount: rows.length };\n};\n\n/**\n * Dispatch table keyed on the canonical (uppercase) command name.\n * If a command isn't found here, the reply is wrapped as a single-cell JSON row.\n */\nconst COMMAND_SHAPES: Record<string, ShapeFn> = {\n\tPING: statusShape,\n\tGET: scalarShape,\n\tSET: statusShape,\n\tTYPE: scalarShape,\n\tTTL: scalarShape,\n\tEXISTS: scalarShape,\n\tDBSIZE: scalarShape,\n\tDEL: scalarShape,\n\tINCR: scalarShape,\n\tDECR: scalarShape,\n\tSTRLEN: scalarShape,\n\tLLEN: scalarShape,\n\tSCARD: scalarShape,\n\tZCARD: scalarShape,\n\tHLEN: scalarShape,\n\n\tHGET: scalarShape,\n\tHMGET: flatArrayShape,\n\tMGET: flatArrayShape,\n\tKEYS: flatArrayShape,\n\tLRANGE: flatArrayShape,\n\tSMEMBERS: flatArrayShape,\n\n\tHGETALL: pairArrayShape,\n\tHKEYS: flatArrayShape,\n\tHVALS: flatArrayShape,\n\t\"CONFIG GET\": pairArrayShape,\n\n\tZRANGE: flatArrayShape, // becomes pair-shaped only with WITHSCORES; caller can post-process\n\tINFO: infoShape,\n\tXRANGE: xrangeShape,\n\tXREVRANGE: xrangeShape,\n};\n\n/**\n * Shape a Redis reply into ExecuteQueryResult-compatible columns/rows/rowCount.\n * Pass `argv` (already tokenized) so we can detect modifiers like `WITHSCORES`.\n */\nexport function shapeReply(\n\targv: string[],\n\treply: unknown,\n): Pick<ExecuteQueryResult, \"columns\" | \"rows\" | \"rowCount\"> {\n\tif (argv.length === 0) return singleCellFallback(reply);\n\n\tconst cmd = argv[0]?.toUpperCase() ?? \"\";\n\tconst subcmd = argv[1]?.toUpperCase();\n\n\t// Special case: ZRANGE … WITHSCORES → pair shape with {member, score}\n\tif (\n\t\t(cmd === \"ZRANGE\" || cmd === \"ZREVRANGE\" || cmd === \"ZRANGEBYSCORE\") &&\n\t\targv.some((a) => a.toUpperCase() === \"WITHSCORES\")\n\t) {\n\t\treturn zrangeWithScoresShape(reply);\n\t}\n\n\t// Two-word commands like CONFIG GET\n\tif (subcmd) {\n\t\tconst compound = `${cmd} ${subcmd}`;\n\t\tconst shaper = COMMAND_SHAPES[compound];\n\t\tif (shaper) return shaper(reply);\n\t}\n\n\tconst shaper = COMMAND_SHAPES[cmd];\n\tif (shaper) return shaper(reply);\n\n\t// Heuristic for unknown commands\n\tif (typeof reply === \"string\" || typeof reply === \"number\" || reply === null) {\n\t\treturn scalarShape(reply);\n\t}\n\tif (isStringArray(reply)) return flatArrayShape(reply);\n\n\treturn singleCellFallback(reply);\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tCellValue,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateKeySchemaType,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteKeyQuerySchemaType,\n\tDeleteKeyResultSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tKeyActionSchemaType,\n\tKeyDetailsQuerySchemaType,\n\tKeyDetailsResultSchemaType,\n\tKeyRawQuerySchemaType,\n\tKeyRawResultSchemaType,\n\tKeyScanQuerySchemaType,\n\tKeyScanResultSchemaType,\n\tKeyWriteResultSchemaType,\n\tRedisKeyTypeSchemaType,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tTableDataResultSchemaType,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { Redis } from \"ioredis\";\nimport { z } from \"zod\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport {\n\tgetIsolatedRedisClient,\n\tgetRedisClient,\n\tgetRedisDefaultDb,\n} from \"@/adapters/connections.js\";\nimport type { IKeyValueAdapter } from \"@/adapters/key-value-adapter.interface.js\";\nimport { shapeReply, tokenizeCommand } from \"./redis.command-shaper.js\";\n\n// ---------------------------------------------------------------------------\n// Constants and types\n// ---------------------------------------------------------------------------\n\nexport const REDIS_TABLES = [\n\t\"strings\",\n\t\"hashes\",\n\t\"lists\",\n\t\"sets\",\n\t\"zsets\",\n\t\"streams\",\n] as const;\nexport type RedisTable = (typeof REDIS_TABLES)[number];\n\nconst TABLE_TO_REDIS_TYPE: Record<RedisTable, string> = {\n\tstrings: \"string\",\n\thashes: \"hash\",\n\tlists: \"list\",\n\tsets: \"set\",\n\tzsets: \"zset\",\n\tstreams: \"stream\",\n};\n\nconst SCHEMA_MUTATION_MESSAGE =\n\t\"Schema is fixed for Redis tables; this operation is not supported\";\nconst SORT_UNSUPPORTED_MESSAGE = \"Sorting is not supported for Redis tables\";\nconst FILTER_UNSUPPORTED_MESSAGE = \"Filtering is not supported for Redis tables\";\nconst PREV_UNSUPPORTED_MESSAGE =\n\t\"Backward pagination is not supported for Redis tables (SCAN is forward-only)\";\nconst SCAN_ROUND_TRIP_CAP = 10;\nconst COUNT_CACHE_TTL_MS = 30_000;\nconst COUNT_SCAN_CEILING = 10_000;\nconst MAX_STRING_PREVIEW_BYTES = 256 * 1024;\nconst MAX_STRING_FULL_BYTES = 8 * 1024 * 1024;\n\nconst isRedisTable = (name: string): name is RedisTable =>\n\t(REDIS_TABLES as readonly string[]).includes(name);\n\nconst assertRedisTable = (tableName: string): RedisTable => {\n\tif (!isRedisTable(tableName)) {\n\t\tthrow new HTTPException(404, {\n\t\t\tmessage: `Table \"${tableName}\" does not exist in Redis. Valid tables: ${REDIS_TABLES.join(\", \")}`,\n\t\t});\n\t}\n\treturn tableName;\n};\n\nconst parseDbIndex = (db: string): number => {\n\tif (db === \"\") return getRedisDefaultDb();\n\tconst parsed = Number.parseInt(db, 10);\n\tif (!Number.isFinite(parsed) || parsed < 0) {\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: `Invalid Redis database index: \"${db}\". Expected a non-negative integer.`,\n\t\t});\n\t}\n\treturn parsed;\n};\n\ninterface ScanCursorEnvelope {\n\tscanCursor: string;\n\ttype: RedisTable;\n}\n\ninterface KeyBrowserCursorEnvelope {\n\tscanCursor: string;\n\tsearch?: string;\n\texactPattern: boolean;\n\ttype?: RedisKeyTypeSchemaType;\n}\n\ninterface KeyDetailsCursorEnvelope {\n\tkey: string;\n\ttype: RedisKeyTypeSchemaType;\n\tcursor: string;\n\tdirection: \"forward\" | \"backward\";\n}\n\nconst encodeKeyBrowserCursor = (env: KeyBrowserCursorEnvelope): string =>\n\tBuffer.from(JSON.stringify(env)).toString(\"base64url\");\n\nconst decodeKeyBrowserCursor = (cursor: string): KeyBrowserCursorEnvelope | null => {\n\ttry {\n\t\treturn z\n\t\t\t.object({\n\t\t\t\tscanCursor: z.string().regex(/^\\d+$/),\n\t\t\t\tsearch: z.string().max(512).optional(),\n\t\t\t\texactPattern: z.boolean(),\n\t\t\t\ttype: z.enum([\"string\", \"hash\", \"list\", \"set\", \"zset\", \"stream\"]).optional(),\n\t\t\t})\n\t\t\t.parse(JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf-8\")));\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nconst encodeKeyDetailsCursor = (env: KeyDetailsCursorEnvelope): string =>\n\tBuffer.from(JSON.stringify(env)).toString(\"base64url\");\n\nconst decodeKeyDetailsCursor = (cursor: string): KeyDetailsCursorEnvelope | null => {\n\ttry {\n\t\treturn z\n\t\t\t.object({\n\t\t\t\tkey: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.min(1)\n\t\t\t\t\t.max(16 * 1024),\n\t\t\t\ttype: z.enum([\"string\", \"hash\", \"list\", \"set\", \"zset\", \"stream\", \"unknown\"]),\n\t\t\t\tcursor: z.string().min(1).max(512),\n\t\t\t\tdirection: z.enum([\"forward\", \"backward\"]),\n\t\t\t})\n\t\t\t.parse(JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf8\")));\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nconst encodeBinaryValue = (value: Buffer): { base64: string; utf8?: string } => {\n\tconst utf8 = value.toString(\"utf8\");\n\treturn Buffer.from(utf8, \"utf8\").equals(value)\n\t\t? { base64: value.toString(\"base64url\"), utf8 }\n\t\t: { base64: value.toString(\"base64url\") };\n};\n\nconst escapeRedisGlob = (value: string): string => value.replaceAll(/[\\\\*?[\\]]/g, \"\\\\$&\");\n\nconst normalizeRedisKeyType = (value: unknown): RedisKeyTypeSchemaType => {\n\tconst type = Buffer.isBuffer(value) ? value.toString(\"utf8\") : String(value);\n\treturn ([\"string\", \"hash\", \"list\", \"set\", \"zset\", \"stream\"] as const).includes(\n\t\ttype as Exclude<RedisKeyTypeSchemaType, \"unknown\">,\n\t)\n\t\t? (type as RedisKeyTypeSchemaType)\n\t\t: \"unknown\";\n};\n\nconst decodeBinaryValue = (value: string): Buffer => Buffer.from(value, \"base64url\");\nconst decodeKeyParam = (value: string): Buffer =>\n\tvalue === \"-\" ? Buffer.alloc(0) : decodeBinaryValue(value);\n\nconst revisionForDump = (dump: Buffer): string =>\n\tcreateHash(\"sha256\").update(dump).digest(\"base64url\");\n\nconst conflict = (): HTTPException =>\n\tnew HTTPException(409, {\n\t\tmessage: \"This key changed since it was loaded. Reload it or explicitly overwrite.\",\n\t});\n\nconst isUnavailableCommandError = (error: unknown): boolean => {\n\tconst message = error instanceof Error ? error.message : String(error);\n\treturn /(NOPERM|unknown command|not allowed|unsupported)/i.test(message);\n};\n\nconst assertKeyType = (\n\tactual: RedisKeyTypeSchemaType,\n\texpected: Exclude<RedisKeyTypeSchemaType, \"unknown\">,\n): void => {\n\tif (actual !== expected) {\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: `This operation requires a ${expected} key, but the key is ${actual}.`,\n\t\t});\n\t}\n};\n\nconst assertTransactionSucceeded = (result: unknown): void => {\n\tif (result === null) throw conflict();\n\tif (!Array.isArray(result)) return;\n\tconst failed = result.find(\n\t\t(entry): entry is [Error, unknown] => Array.isArray(entry) && entry[0] instanceof Error,\n\t);\n\tif (failed) {\n\t\tthrow new HTTPException(400, { message: failed[0].message });\n\t}\n};\n\nconst encodeScanCursor = (env: ScanCursorEnvelope): string =>\n\tBuffer.from(JSON.stringify(env)).toString(\"base64url\");\n\nconst decodeScanCursor = (cursor: string): ScanCursorEnvelope | null => {\n\ttry {\n\t\treturn JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf-8\"));\n\t} catch {\n\t\treturn null;\n\t}\n};\n\ninterface CountCacheEntry {\n\ttimestamp: number;\n\tcounts: Record<RedisTable, number>;\n}\n\n// ---------------------------------------------------------------------------\n// Per-type column definitions\n// ---------------------------------------------------------------------------\n\nconst columnInfo = (\n\toverrides: Partial<ColumnInfoSchemaType> &\n\t\tPick<ColumnInfoSchemaType, \"columnName\" | \"dataType\">,\n): ColumnInfoSchemaType => ({\n\tcolumnName: overrides.columnName,\n\tdataType: overrides.dataType,\n\tdataTypeLabel:\n\t\toverrides.dataTypeLabel ??\n\t\t(overrides.dataType === \"number\"\n\t\t\t? \"int\"\n\t\t\t: overrides.dataType === \"json\"\n\t\t\t\t? \"json\"\n\t\t\t\t: overrides.dataType === \"array\"\n\t\t\t\t\t? \"array\"\n\t\t\t\t\t: \"text\"),\n\tisNullable: overrides.isNullable ?? false,\n\tcolumnDefault: overrides.columnDefault ?? null,\n\tisPrimaryKey: overrides.isPrimaryKey ?? false,\n\tisForeignKey: false,\n\treferencedTable: null,\n\treferencedColumn: null,\n\tenumValues: null,\n});\n\nconst KEY_COL = columnInfo({ columnName: \"key\", dataType: \"text\", isPrimaryKey: true });\nconst TTL_COL = columnInfo({ columnName: \"ttl\", dataType: \"number\", isNullable: true });\n\nconst TABLE_COLUMNS: Record<RedisTable, ColumnInfoSchemaType[]> = {\n\tstrings: [\n\t\tKEY_COL,\n\t\tcolumnInfo({ columnName: \"value\", dataType: \"text\", isNullable: true }),\n\t\tTTL_COL,\n\t],\n\thashes: [KEY_COL, columnInfo({ columnName: \"value\", dataType: \"json\" }), TTL_COL],\n\tlists: [KEY_COL, columnInfo({ columnName: \"value\", dataType: \"array\" }), TTL_COL],\n\tsets: [KEY_COL, columnInfo({ columnName: \"value\", dataType: \"array\" }), TTL_COL],\n\tzsets: [KEY_COL, columnInfo({ columnName: \"value\", dataType: \"json\" }), TTL_COL],\n\tstreams: [\n\t\tKEY_COL,\n\t\tcolumnInfo({ columnName: \"length\", dataType: \"number\" }),\n\t\tcolumnInfo({ columnName: \"first-id\", dataType: \"text\", isNullable: true }),\n\t\tcolumnInfo({ columnName: \"last-id\", dataType: \"text\", isNullable: true }),\n\t\tTTL_COL,\n\t],\n};\n\nconst SCHEMA_DESCRIPTIONS: Record<RedisTable, string> = {\n\tstrings: `-- Redis string keys\n-- Columns: key (text, PK), value (text), ttl (number, seconds; -1 = no TTL, -2 = missing)\n-- Backed by: GET / SET / EXPIRE`,\n\thashes: `-- Redis hash keys\n-- Columns: key (text, PK), value (json: {field: value, ...}), ttl (number)\n-- Backed by: HGETALL / HSET / EXPIRE`,\n\tlists: `-- Redis list keys\n-- Columns: key (text, PK), value (array of elements), ttl (number)\n-- Backed by: LRANGE / RPUSH / EXPIRE`,\n\tsets: `-- Redis set keys\n-- Columns: key (text, PK), value (array of members), ttl (number)\n-- Backed by: SMEMBERS / SADD / EXPIRE`,\n\tzsets: `-- Redis sorted set keys\n-- Columns: key (text, PK), value (json: [{member, score}, ...]), ttl (number)\n-- Backed by: ZRANGE WITHSCORES / ZADD / EXPIRE`,\n\tstreams: `-- Redis stream keys\n-- Columns: key (text, PK), length (number), first-id (text), last-id (text), ttl (number)\n-- Backed by: XINFO STREAM / XADD / EXPIRE (read-only — streams are append-only)`,\n};\n\n// ---------------------------------------------------------------------------\n// RedisAdapter\n// ---------------------------------------------------------------------------\n\nexport class RedisAdapter extends BaseAdapter implements IKeyValueAdapter {\n\tprivate countCache: Map<number, CountCacheEntry> = new Map();\n\n\t// -----------------------------------------------------------------------\n\t// Abstract stubs — Redis does not use SQL\n\t// -----------------------------------------------------------------------\n\n\tprotected runQuery<T>(): Promise<T> {\n\t\tthrow new HTTPException(501, { message: \"runQuery is not supported for Redis\" });\n\t}\n\n\tprotected buildTableDataQuery(_params: GetTableDataParams): QueryBundle {\n\t\tthrow new HTTPException(501, {\n\t\t\tmessage: \"buildTableDataQuery is not supported for Redis\",\n\t\t});\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn rawRows.map((row) => this.normalizeRow(row as Record<string, unknown>));\n\t}\n\n\tprotected buildCursors(): { nextCursor: string | null; prevCursor: string | null } {\n\t\treturn { nextCursor: null, prevCursor: null };\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn name;\n\t}\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\tswitch (nativeType.toLowerCase()) {\n\t\t\tcase \"string\":\n\t\t\t\treturn \"text\";\n\t\t\tcase \"hash\":\n\t\t\t\treturn \"json\";\n\t\t\tcase \"list\":\n\t\t\tcase \"set\":\n\t\t\t\treturn \"array\";\n\t\t\tcase \"zset\":\n\t\t\tcase \"stream\":\n\t\t\t\treturn \"json\";\n\t\t\tcase \"integer\":\n\t\t\tcase \"number\":\n\t\t\tcase \"ttl\":\n\t\t\t\treturn \"number\";\n\t\t\tdefault:\n\t\t\t\treturn \"text\";\n\t\t}\n\t}\n\n\tmapFromUniversalType(_universalType: string): string {\n\t\treturn \"string\";\n\t}\n\n\tasync scanKeys(params: KeyScanQuerySchemaType): Promise<KeyScanResultSchemaType> {\n\t\ttry {\n\t\t\tconst { db, limit, search, exactPattern, type, cursor } = params;\n\t\t\tconst dbIndex = parseDbIndex(db);\n\t\t\tconst client = await getRedisClient(dbIndex);\n\t\t\tlet scanCursor = \"0\";\n\n\t\t\tif (cursor) {\n\t\t\t\tconst decoded = decodeKeyBrowserCursor(cursor);\n\t\t\t\tif (\n\t\t\t\t\t!decoded ||\n\t\t\t\t\tdecoded.search !== search ||\n\t\t\t\t\tdecoded.exactPattern !== exactPattern ||\n\t\t\t\t\tdecoded.type !== type\n\t\t\t\t) {\n\t\t\t\t\tthrow new HTTPException(400, { message: \"Invalid or stale key scan cursor\" });\n\t\t\t\t}\n\t\t\t\tscanCursor = decoded.scanCursor;\n\t\t\t}\n\n\t\t\tconst pattern = search ? (exactPattern ? search : `*${escapeRedisGlob(search)}*`) : \"*\";\n\t\t\tconst scanArgs: Array<string | number> = [scanCursor, \"MATCH\", pattern, \"COUNT\", limit];\n\t\t\tif (type) scanArgs.push(\"TYPE\", type);\n\n\t\t\tconst [nextRaw, pageKeys] = (await (\n\t\t\t\tclient.scanBuffer as unknown as (\n\t\t\t\t\t...args: Array<string | number>\n\t\t\t\t) => Promise<[Buffer | string, Buffer[]]>\n\t\t\t)(...scanArgs)) as [Buffer | string, Buffer[]];\n\t\t\tconst nextScanCursor = Buffer.isBuffer(nextRaw) ? nextRaw.toString(\"utf8\") : nextRaw;\n\t\t\tconst pipeline = client.pipeline();\n\t\t\tfor (const key of pageKeys) {\n\t\t\t\tpipeline.call(\"TYPE\", key);\n\t\t\t\tpipeline.pttl(key);\n\t\t\t\tpipeline.call(\"MEMORY\", \"USAGE\", key);\n\t\t\t}\n\t\t\tconst metadata = (await pipeline.exec()) ?? [];\n\n\t\t\treturn {\n\t\t\t\tkeys: pageKeys.map((key, index) => {\n\t\t\t\t\tconst offset = index * 3;\n\t\t\t\t\tconst memory = metadata[offset + 2]?.[1];\n\t\t\t\t\treturn {\n\t\t\t\t\t\tkey: encodeBinaryValue(key),\n\t\t\t\t\t\ttype: normalizeRedisKeyType(metadata[offset]?.[1]),\n\t\t\t\t\t\tttlMs: Number(metadata[offset + 1]?.[1] ?? -2),\n\t\t\t\t\t\tmemoryBytes: memory === null || memory === undefined ? null : Number(memory),\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t\tnextCursor:\n\t\t\t\t\tnextScanCursor === \"0\"\n\t\t\t\t\t\t? null\n\t\t\t\t\t\t: encodeKeyBrowserCursor({\n\t\t\t\t\t\t\t\tscanCursor: nextScanCursor,\n\t\t\t\t\t\t\t\tsearch,\n\t\t\t\t\t\t\t\texactPattern,\n\t\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t}),\n\t\t\t\thasMore: nextScanCursor !== \"0\",\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getKeyDetails(\n\t\tparams: KeyDetailsQuerySchemaType & { key: string },\n\t): Promise<KeyDetailsResultSchemaType> {\n\t\ttry {\n\t\t\tconst { db, key: encodedKey, cursor, limit, full, direction } = params;\n\t\t\tconst key = decodeKeyParam(encodedKey);\n\t\t\tconst client = await getRedisClient(parseDbIndex(db));\n\t\t\tconst [typeRaw, ttlMs, memoryRaw, dumpRaw] = await Promise.all([\n\t\t\t\tclient.callBuffer(\"TYPE\", key),\n\t\t\t\tclient.pttl(key),\n\t\t\t\tclient.call(\"MEMORY\", \"USAGE\", key).catch(() => null),\n\t\t\t\tclient.callBuffer(\"DUMP\", key),\n\t\t\t]);\n\t\t\tconst dump = dumpRaw as Buffer | null;\n\t\t\tif (!dump) {\n\t\t\t\tthrow new HTTPException(404, { message: \"Redis key no longer exists\" });\n\t\t\t}\n\n\t\t\tconst type = normalizeRedisKeyType(typeRaw);\n\t\t\tconst summary = {\n\t\t\t\tkey: encodeBinaryValue(key),\n\t\t\t\ttype,\n\t\t\t\tttlMs: Number(ttlMs),\n\t\t\t\tmemoryBytes: memoryRaw === null ? null : Number(memoryRaw),\n\t\t\t\trevision: revisionForDump(dump),\n\t\t\t};\n\t\t\tconst decodedCursor = cursor ? decodeKeyDetailsCursor(cursor) : null;\n\t\t\tif (\n\t\t\t\tcursor &&\n\t\t\t\t(!decodedCursor ||\n\t\t\t\t\tdecodedCursor.key !== encodedKey ||\n\t\t\t\t\tdecodedCursor.type !== type ||\n\t\t\t\t\tdecodedCursor.direction !== direction)\n\t\t\t) {\n\t\t\t\tthrow new HTTPException(400, { message: \"Invalid or stale key details cursor\" });\n\t\t\t}\n\n\t\t\tif (type === \"string\") {\n\t\t\t\tconst length = await client.strlen(key);\n\t\t\t\tconst readLimit = full ? MAX_STRING_FULL_BYTES : MAX_STRING_PREVIEW_BYTES;\n\t\t\t\tconst value = await client.getrangeBuffer(key, 0, readLimit - 1);\n\t\t\t\treturn {\n\t\t\t\t\t...summary,\n\t\t\t\t\tlength,\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\tkind: \"string\",\n\t\t\t\t\t\tvalue: encodeBinaryValue(value),\n\t\t\t\t\t\ttruncated: length > readLimit,\n\t\t\t\t\t},\n\t\t\t\t\tnextCursor: null,\n\t\t\t\t\thasMore: false,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (type === \"hash\") {\n\t\t\t\tconst [length, scanResult] = await Promise.all([\n\t\t\t\t\tclient.hlen(key),\n\t\t\t\t\tclient.hscanBuffer(key, decodedCursor?.cursor ?? \"0\", \"COUNT\", String(limit)),\n\t\t\t\t]);\n\t\t\t\tconst [nextRaw, values] = scanResult as [Buffer | string, Buffer[]];\n\t\t\t\tconst next = Buffer.isBuffer(nextRaw) ? nextRaw.toString(\"utf8\") : nextRaw;\n\t\t\t\tconst entries = [];\n\t\t\t\tfor (let index = 0; index < values.length; index += 2) {\n\t\t\t\t\tentries.push({\n\t\t\t\t\t\tfield: encodeBinaryValue(values[index]),\n\t\t\t\t\t\tvalue: encodeBinaryValue(values[index + 1]),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\t...summary,\n\t\t\t\t\tlength,\n\t\t\t\t\tvalue: { kind: \"hash\", entries },\n\t\t\t\t\tnextCursor:\n\t\t\t\t\t\tnext === \"0\"\n\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t: encodeKeyDetailsCursor({ key: encodedKey, type, cursor: next, direction }),\n\t\t\t\t\thasMore: next !== \"0\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (type === \"list\") {\n\t\t\t\tconst offset = Number.parseInt(decodedCursor?.cursor ?? \"0\", 10);\n\t\t\t\tconst length = await client.llen(key);\n\t\t\t\tconst values = await client.lrangeBuffer(key, offset, offset + limit - 1);\n\t\t\t\tconst nextOffset = offset + values.length;\n\t\t\t\tconst hasMore = nextOffset < length;\n\t\t\t\treturn {\n\t\t\t\t\t...summary,\n\t\t\t\t\tlength,\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\tkind: \"list\",\n\t\t\t\t\t\tentries: values.map((value, index) => ({\n\t\t\t\t\t\t\tindex: offset + index,\n\t\t\t\t\t\t\tvalue: encodeBinaryValue(value),\n\t\t\t\t\t\t})),\n\t\t\t\t\t},\n\t\t\t\t\tnextCursor: hasMore\n\t\t\t\t\t\t? encodeKeyDetailsCursor({\n\t\t\t\t\t\t\t\tkey: encodedKey,\n\t\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t\tcursor: String(nextOffset),\n\t\t\t\t\t\t\t\tdirection,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: null,\n\t\t\t\t\thasMore,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (type === \"set\") {\n\t\t\t\tconst [length, scanResult] = await Promise.all([\n\t\t\t\t\tclient.scard(key),\n\t\t\t\t\tclient.sscanBuffer(key, decodedCursor?.cursor ?? \"0\", \"COUNT\", String(limit)),\n\t\t\t\t]);\n\t\t\t\tconst [nextRaw, members] = scanResult as [Buffer | string, Buffer[]];\n\t\t\t\tconst next = Buffer.isBuffer(nextRaw) ? nextRaw.toString(\"utf8\") : nextRaw;\n\t\t\t\treturn {\n\t\t\t\t\t...summary,\n\t\t\t\t\tlength,\n\t\t\t\t\tvalue: { kind: \"set\", members: members.map(encodeBinaryValue) },\n\t\t\t\t\tnextCursor:\n\t\t\t\t\t\tnext === \"0\"\n\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t: encodeKeyDetailsCursor({ key: encodedKey, type, cursor: next, direction }),\n\t\t\t\t\thasMore: next !== \"0\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (type === \"zset\") {\n\t\t\t\tconst [length, scanResult] = await Promise.all([\n\t\t\t\t\tclient.zcard(key),\n\t\t\t\t\tclient.zscanBuffer(key, decodedCursor?.cursor ?? \"0\", \"COUNT\", String(limit)),\n\t\t\t\t]);\n\t\t\t\tconst [nextRaw, values] = scanResult as [Buffer | string, Buffer[]];\n\t\t\t\tconst next = Buffer.isBuffer(nextRaw) ? nextRaw.toString(\"utf8\") : nextRaw;\n\t\t\t\tconst entries = [];\n\t\t\t\tfor (let index = 0; index < values.length; index += 2) {\n\t\t\t\t\tentries.push({\n\t\t\t\t\t\tmember: encodeBinaryValue(values[index]),\n\t\t\t\t\t\tscore: ((): number | \"inf\" | \"-inf\" => {\n\t\t\t\t\t\t\tconst score = values[index + 1].toString(\"utf8\");\n\t\t\t\t\t\t\tif (score === \"inf\") return \"inf\";\n\t\t\t\t\t\t\tif (score === \"-inf\") return \"-inf\";\n\t\t\t\t\t\t\treturn Number(score);\n\t\t\t\t\t\t})(),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\t...summary,\n\t\t\t\t\tlength,\n\t\t\t\t\tvalue: { kind: \"zset\", entries },\n\t\t\t\t\tnextCursor:\n\t\t\t\t\t\tnext === \"0\"\n\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t: encodeKeyDetailsCursor({ key: encodedKey, type, cursor: next, direction }),\n\t\t\t\t\thasMore: next !== \"0\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (type === \"stream\") {\n\t\t\t\tconst boundary = decodedCursor?.cursor ?? (direction === \"forward\" ? \"-\" : \"+\");\n\t\t\t\tconst [length, rawEntries] = await Promise.all([\n\t\t\t\t\tclient.xlen(key),\n\t\t\t\t\tdirection === \"forward\"\n\t\t\t\t\t\t? client.xrangeBuffer(key, boundary, \"+\", \"COUNT\", limit + 1)\n\t\t\t\t\t\t: client.xrevrangeBuffer(key, boundary, \"-\", \"COUNT\", limit + 1),\n\t\t\t\t]);\n\t\t\t\tconst hasMore = rawEntries.length > limit;\n\t\t\t\tconst page = rawEntries.slice(0, limit) as Array<[Buffer, Buffer[]]>;\n\t\t\t\tconst entries = page.map(([id, values]) => {\n\t\t\t\t\tconst fields = [];\n\t\t\t\t\tfor (let index = 0; index < values.length; index += 2) {\n\t\t\t\t\t\tfields.push({\n\t\t\t\t\t\t\tfield: encodeBinaryValue(values[index]),\n\t\t\t\t\t\t\tvalue: encodeBinaryValue(values[index + 1]),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn { id: id.toString(\"utf8\"), fields };\n\t\t\t\t});\n\t\t\t\tconst lastId = entries.at(-1)?.id;\n\t\t\t\treturn {\n\t\t\t\t\t...summary,\n\t\t\t\t\tlength,\n\t\t\t\t\tvalue: { kind: \"stream\", entries },\n\t\t\t\t\tnextCursor:\n\t\t\t\t\t\thasMore && lastId\n\t\t\t\t\t\t\t? encodeKeyDetailsCursor({\n\t\t\t\t\t\t\t\t\tkey: encodedKey,\n\t\t\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t\t\tcursor: `(${lastId}`,\n\t\t\t\t\t\t\t\t\tdirection,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\thasMore,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...summary,\n\t\t\t\tlength: null,\n\t\t\t\tvalue: { kind: \"unknown\" },\n\t\t\t\tnextCursor: null,\n\t\t\t\thasMore: false,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getStringChunk(\n\t\tparams: KeyRawQuerySchemaType & { key: string },\n\t): Promise<KeyRawResultSchemaType> {\n\t\ttry {\n\t\t\tconst client = await getRedisClient(parseDbIndex(params.db));\n\t\t\tconst key = decodeKeyParam(params.key);\n\t\t\tconst type = normalizeRedisKeyType(await client.callBuffer(\"TYPE\", key));\n\t\t\tif (type === \"unknown\") {\n\t\t\t\tthrow new HTTPException(404, { message: \"Redis key no longer exists\" });\n\t\t\t}\n\t\t\tassertKeyType(type, \"string\");\n\t\t\tif (params.expectedRevision) {\n\t\t\t\tconst dump = (await client.callBuffer(\"DUMP\", key)) as Buffer | null;\n\t\t\t\tif (!dump || revisionForDump(dump) !== params.expectedRevision) throw conflict();\n\t\t\t}\n\t\t\tconst length = await client.strlen(key);\n\t\t\tconst chunk = await client.getrangeBuffer(\n\t\t\t\tkey,\n\t\t\t\tparams.offset,\n\t\t\t\tparams.offset + params.limit - 1,\n\t\t\t);\n\t\t\tconst next = params.offset + chunk.length;\n\t\t\treturn {\n\t\t\t\tchunk: encodeBinaryValue(chunk),\n\t\t\t\tlength,\n\t\t\t\tnextOffset: next < length ? next : null,\n\t\t\t\thasMore: next < length,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync createKey(\n\t\tparams: CreateKeySchemaType & { db: string },\n\t): Promise<KeyWriteResultSchemaType> {\n\t\tlet client: Redis | null = null;\n\t\ttry {\n\t\t\tclient = await getIsolatedRedisClient(parseDbIndex(params.db));\n\t\t\tconst key = decodeBinaryValue(params.key.base64);\n\t\t\tawait client.watch(key);\n\t\t\tif ((await client.exists(key)) !== 0) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: \"A Redis key with this name already exists.\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (params.type !== params.value.kind) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: \"The initial value does not match the selected Redis key type.\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst transaction = client.multi();\n\t\t\tswitch (params.value.kind) {\n\t\t\t\tcase \"string\":\n\t\t\t\t\ttransaction.set(key, decodeBinaryValue(params.value.value.base64));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hash\":\n\t\t\t\t\ttransaction.hset(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\t...params.value.entries.flatMap(({ field, value }) => [\n\t\t\t\t\t\t\tdecodeBinaryValue(field.base64),\n\t\t\t\t\t\t\tdecodeBinaryValue(value.base64),\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"list\":\n\t\t\t\t\ttransaction.rpush(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\t...params.value.entries.map((value) => decodeBinaryValue(value.base64)),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"set\":\n\t\t\t\t\ttransaction.sadd(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\t...params.value.members.map((member) => decodeBinaryValue(member.base64)),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"zset\":\n\t\t\t\t\ttransaction.zadd(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\t...params.value.entries.flatMap(({ member, score }) => [\n\t\t\t\t\t\t\tscore,\n\t\t\t\t\t\t\tdecodeBinaryValue(member.base64),\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"stream\":\n\t\t\t\t\ttransaction.xadd(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tparams.value.id,\n\t\t\t\t\t\t...params.value.fields.flatMap(({ field, value }) => [\n\t\t\t\t\t\t\tdecodeBinaryValue(field.base64),\n\t\t\t\t\t\t\tdecodeBinaryValue(value.base64),\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (params.ttlMs !== null) transaction.pexpire(key, params.ttlMs);\n\t\t\tassertTransactionSucceeded(await transaction.exec());\n\n\t\t\tconst dump = (await client.callBuffer(\"DUMP\", key)) as Buffer | null;\n\t\t\tif (!dump) throw conflict();\n\t\t\treturn {\n\t\t\t\tkey: encodeBinaryValue(key),\n\t\t\t\trevision: revisionForDump(dump),\n\t\t\t\tdeleted: false,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t} finally {\n\t\t\tif (client) await client.quit().catch(() => client?.disconnect());\n\t\t}\n\t}\n\n\tasync applyKeyAction(\n\t\tparams: KeyActionSchemaType & { db: string; key: string },\n\t): Promise<KeyWriteResultSchemaType> {\n\t\tlet client: Redis | null = null;\n\t\ttry {\n\t\t\tclient = await getIsolatedRedisClient(parseDbIndex(params.db));\n\t\t\tconst key = decodeKeyParam(params.key);\n\t\t\tconst newKey =\n\t\t\t\tparams.operation.action === \"rename\"\n\t\t\t\t\t? decodeBinaryValue(params.operation.newKey.base64)\n\t\t\t\t\t: null;\n\t\t\tif (newKey && !newKey.equals(key)) await client.watch(key, newKey);\n\t\t\telse await client.watch(key);\n\n\t\t\tconst [dumpRaw, typeRaw, ttlMs] = await Promise.all([\n\t\t\t\tclient.callBuffer(\"DUMP\", key),\n\t\t\t\tclient.callBuffer(\"TYPE\", key),\n\t\t\t\tclient.pttl(key),\n\t\t\t]);\n\t\t\tconst dump = dumpRaw as Buffer | null;\n\t\t\tif (!dump) throw new HTTPException(404, { message: \"Redis key no longer exists\" });\n\t\t\tif (!params.force && revisionForDump(dump) !== params.expectedRevision) throw conflict();\n\t\t\tconst type = normalizeRedisKeyType(typeRaw);\n\t\t\tif (newKey && !newKey.equals(key) && (await client.exists(newKey)) !== 0) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: \"A Redis key with the new name already exists.\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst transaction = client.multi();\n\t\t\tswitch (params.operation.action) {\n\t\t\t\tcase \"rename\":\n\t\t\t\t\tif (!newKey || newKey.equals(key)) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tkey: encodeBinaryValue(key),\n\t\t\t\t\t\t\trevision: revisionForDump(dump),\n\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\ttransaction.rename(key, newKey);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"setTtl\":\n\t\t\t\t\tif (params.operation.ttlMs === null) transaction.persist(key);\n\t\t\t\t\telse transaction.pexpire(key, params.operation.ttlMs);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"setString\":\n\t\t\t\t\tassertKeyType(type, \"string\");\n\t\t\t\t\ttransaction.set(key, decodeBinaryValue(params.operation.value.base64));\n\t\t\t\t\tif (ttlMs > 0) transaction.pexpire(key, ttlMs);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"upsertHash\":\n\t\t\t\t\tassertKeyType(type, \"hash\");\n\t\t\t\t\ttransaction.hset(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tdecodeBinaryValue(params.operation.field.base64),\n\t\t\t\t\t\tdecodeBinaryValue(params.operation.value.base64),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"deleteHash\":\n\t\t\t\t\tassertKeyType(type, \"hash\");\n\t\t\t\t\ttransaction.hdel(key, decodeBinaryValue(params.operation.field.base64));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"pushList\":\n\t\t\t\t\tassertKeyType(type, \"list\");\n\t\t\t\t\tif (params.operation.side === \"left\") {\n\t\t\t\t\t\ttransaction.lpush(key, decodeBinaryValue(params.operation.value.base64));\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttransaction.rpush(key, decodeBinaryValue(params.operation.value.base64));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"setList\":\n\t\t\t\t\tassertKeyType(type, \"list\");\n\t\t\t\t\ttransaction.lset(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tparams.operation.index,\n\t\t\t\t\t\tdecodeBinaryValue(params.operation.value.base64),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"deleteList\": {\n\t\t\t\t\tassertKeyType(type, \"list\");\n\t\t\t\t\tconst marker = Buffer.concat([\n\t\t\t\t\t\tBuffer.from(\"db-studio:list-delete:\"),\n\t\t\t\t\t\trandomBytes(32),\n\t\t\t\t\t]);\n\t\t\t\t\ttransaction.lset(key, params.operation.index, marker);\n\t\t\t\t\ttransaction.lrem(key, 1, marker);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"addSet\":\n\t\t\t\t\tassertKeyType(type, \"set\");\n\t\t\t\t\ttransaction.sadd(key, decodeBinaryValue(params.operation.member.base64));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"removeSet\":\n\t\t\t\t\tassertKeyType(type, \"set\");\n\t\t\t\t\ttransaction.srem(key, decodeBinaryValue(params.operation.member.base64));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"upsertZset\":\n\t\t\t\t\tassertKeyType(type, \"zset\");\n\t\t\t\t\ttransaction.zadd(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tparams.operation.score,\n\t\t\t\t\t\tdecodeBinaryValue(params.operation.member.base64),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"removeZset\":\n\t\t\t\t\tassertKeyType(type, \"zset\");\n\t\t\t\t\ttransaction.zrem(key, decodeBinaryValue(params.operation.member.base64));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"appendStream\":\n\t\t\t\t\tassertKeyType(type, \"stream\");\n\t\t\t\t\ttransaction.xadd(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tparams.operation.id,\n\t\t\t\t\t\t...params.operation.fields.flatMap(({ field, value }) => [\n\t\t\t\t\t\t\tdecodeBinaryValue(field.base64),\n\t\t\t\t\t\t\tdecodeBinaryValue(value.base64),\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"deleteStream\":\n\t\t\t\t\tassertKeyType(type, \"stream\");\n\t\t\t\t\ttransaction.xdel(key, params.operation.id);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tassertTransactionSucceeded(await transaction.exec());\n\t\t\tconst resultKey = newKey && !newKey.equals(key) ? newKey : key;\n\t\t\tconst nextDump = (await client.callBuffer(\"DUMP\", resultKey)) as Buffer | null;\n\t\t\treturn {\n\t\t\t\tkey: encodeBinaryValue(resultKey),\n\t\t\t\trevision: nextDump ? revisionForDump(nextDump) : null,\n\t\t\t\tdeleted: nextDump === null,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t} finally {\n\t\t\tif (client) await client.quit().catch(() => client?.disconnect());\n\t\t}\n\t}\n\n\tasync deleteKey(\n\t\tparams: DeleteKeyQuerySchemaType & { key: string },\n\t): Promise<DeleteKeyResultSchemaType> {\n\t\tlet client: Redis | null = null;\n\t\ttry {\n\t\t\tclient = await getIsolatedRedisClient(parseDbIndex(params.db));\n\t\t\tconst key = decodeKeyParam(params.key);\n\t\t\tawait client.watch(key);\n\t\t\tconst dump = (await client.callBuffer(\"DUMP\", key)) as Buffer | null;\n\t\t\tif (!dump) throw new HTTPException(404, { message: \"Redis key no longer exists\" });\n\t\t\tif (!params.force && revisionForDump(dump) !== params.expectedRevision) throw conflict();\n\t\t\tconst transaction = client.multi().del(key);\n\t\t\tassertTransactionSucceeded(await transaction.exec());\n\t\t\treturn { deleted: true };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t} finally {\n\t\t\tif (client) await client.quit().catch(() => client?.disconnect());\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Database operations\n\t// -----------------------------------------------------------------------\n\n\toverride async getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst client = await getRedisClient(getRedisDefaultDb());\n\t\t\tlet total = 1;\n\t\t\tlet supportsLogicalDatabases = false;\n\t\t\tlet configReply: unknown = null;\n\t\t\ttry {\n\t\t\t\tconfigReply = await client.call(\"CONFIG\", \"GET\", \"databases\");\n\t\t\t} catch (error) {\n\t\t\t\tif (!isUnavailableCommandError(error)) throw error;\n\t\t\t}\n\t\t\tif (Array.isArray(configReply) && configReply.length >= 2) {\n\t\t\t\tconst parsed = Number.parseInt(String(configReply[1]), 10);\n\t\t\t\tif (Number.isFinite(parsed) && parsed > 0) {\n\t\t\t\t\ttotal = parsed;\n\t\t\t\t\tsupportsLogicalDatabases = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet keyspaceInfo = \"\";\n\t\t\ttry {\n\t\t\t\tkeyspaceInfo = await client.info(\"keyspace\");\n\t\t\t} catch (error) {\n\t\t\t\tif (!isUnavailableCommandError(error)) throw error;\n\t\t\t}\n\t\t\tconst keysPerDb = parseKeyspaceInfo(keyspaceInfo);\n\n\t\t\tconst databases = supportsLogicalDatabases\n\t\t\t\t? Array.from({ length: total }, (_, index) => index)\n\t\t\t\t: [getRedisDefaultDb()];\n\t\t\treturn databases.map((index) => ({\n\t\t\t\tname: String(index),\n\t\t\t\tsize: `${keysPerDb.get(index) ?? 0} keys`,\n\t\t\t\towner: \"n/a\",\n\t\t\t\tencoding: \"n/a\",\n\t\t\t}));\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\treturn { db: String(getRedisDefaultDb()) };\n\t}\n\n\toverride async getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\ttry {\n\t\t\tconst client = await getRedisClient(getRedisDefaultDb());\n\t\t\tconst [serverInfo, clientsInfo] = await Promise.all([\n\t\t\t\tclient.info(\"server\"),\n\t\t\t\tclient.info(\"clients\"),\n\t\t\t]);\n\t\t\tconst server = parseInfoSection(serverInfo);\n\t\t\tconst clients = parseInfoSection(clientsInfo);\n\n\t\t\tlet maxclients = Number.parseInt(clients.maxclients ?? \"0\", 10);\n\t\t\tif (!Number.isFinite(maxclients) || maxclients === 0) {\n\t\t\t\tconst reply = await client.call(\"CONFIG\", \"GET\", \"maxclients\").catch((error) => {\n\t\t\t\t\tif (!isUnavailableCommandError(error)) throw error;\n\t\t\t\t\treturn null;\n\t\t\t\t});\n\t\t\t\tif (Array.isArray(reply) && reply.length >= 2) {\n\t\t\t\t\tmaxclients = Number.parseInt(String(reply[1]), 10) || 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst opts = client.options;\n\t\t\treturn {\n\t\t\t\thost: opts.host ?? null,\n\t\t\t\tport: opts.port ?? null,\n\t\t\t\tuser: opts.username || \"default\",\n\t\t\t\tdatabase: String(opts.db ?? getRedisDefaultDb()),\n\t\t\t\tversion: server.redis_version ?? \"unknown\",\n\t\t\t\tactive_connections: Number.parseInt(clients.connected_clients ?? \"0\", 10) || 0,\n\t\t\t\tmax_connections: maxclients || 0,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Table operations\n\t// -----------------------------------------------------------------------\n\n\toverride async getTablesList(db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst dbIndex = parseDbIndex(db);\n\t\t\tconst counts = await this.getCachedCounts(dbIndex);\n\t\t\treturn REDIS_TABLES.map((tableName) => ({\n\t\t\t\ttableName,\n\t\t\t\trowCount: counts[tableName],\n\t\t\t}));\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async createTable(): Promise<void> {\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: \"Redis tables are fixed; cannot create new ones\",\n\t\t});\n\t}\n\n\toverride async deleteTable(_params: DeleteTableParams): Promise<DeleteTableResult> {\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage:\n\t\t\t\t\"Bulk deletion of Redis tables is not supported. Use FLUSHDB from the query runner to clear the entire logical database.\",\n\t\t});\n\t}\n\n\toverride async renameTable(_params: RenameTableParamsSchemaType): Promise<void> {\n\t\tthrow new HTTPException(400, { message: SCHEMA_MUTATION_MESSAGE });\n\t}\n\n\toverride async getTableSchema({\n\t\ttableName,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\tconst table = assertRedisTable(tableName);\n\t\treturn SCHEMA_DESCRIPTIONS[table];\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Column operations — all schema mutations throw 400\n\t// -----------------------------------------------------------------------\n\n\toverride async getTableColumns({\n\t\ttableName,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\tconst table = assertRedisTable(tableName);\n\t\treturn TABLE_COLUMNS[table];\n\t}\n\n\toverride async addColumn(_params: AddColumnParamsSchemaType): Promise<void> {\n\t\tthrow new HTTPException(400, { message: SCHEMA_MUTATION_MESSAGE });\n\t}\n\n\toverride async deleteColumn(\n\t\t_params: DeleteColumnParamsSchemaType,\n\t): Promise<{ deletedCount: number }> {\n\t\tthrow new HTTPException(400, { message: SCHEMA_MUTATION_MESSAGE });\n\t}\n\n\toverride async alterColumn(_params: AlterColumnParamsSchemaType): Promise<void> {\n\t\tthrow new HTTPException(400, { message: SCHEMA_MUTATION_MESSAGE });\n\t}\n\n\toverride async renameColumn(_params: RenameColumnParamsSchemaType): Promise<void> {\n\t\tthrow new HTTPException(400, { message: SCHEMA_MUTATION_MESSAGE });\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// getTableData — forward-only SCAN with envelope cursor\n\t// -----------------------------------------------------------------------\n\n\toverride async getTableData(params: GetTableDataParams): Promise<TableDataResultSchemaType> {\n\t\ttry {\n\t\t\tconst { tableName, db, cursor, limit = 50, direction = \"asc\", sort, filters } = params;\n\n\t\t\tif (direction === \"desc\") {\n\t\t\t\tthrow new HTTPException(400, { message: PREV_UNSUPPORTED_MESSAGE });\n\t\t\t}\n\t\t\tif (sort && (typeof sort === \"string\" ? sort.length > 0 : sort.length > 0)) {\n\t\t\t\tthrow new HTTPException(400, { message: SORT_UNSUPPORTED_MESSAGE });\n\t\t\t}\n\t\t\tif (filters && filters.length > 0) {\n\t\t\t\tthrow new HTTPException(400, { message: FILTER_UNSUPPORTED_MESSAGE });\n\t\t\t}\n\n\t\t\tconst table = assertRedisTable(tableName);\n\t\t\tconst redisType = TABLE_TO_REDIS_TYPE[table];\n\t\t\tconst dbIndex = parseDbIndex(db);\n\t\t\tconst client = await getRedisClient(dbIndex);\n\n\t\t\tlet scanCursor = \"0\";\n\t\t\tif (cursor) {\n\t\t\t\tconst decoded = decodeScanCursor(cursor);\n\t\t\t\tif (!decoded || decoded.type !== table) {\n\t\t\t\t\tthrow new HTTPException(400, { message: \"Invalid or mismatched cursor\" });\n\t\t\t\t}\n\t\t\t\tscanCursor = decoded.scanCursor;\n\t\t\t}\n\n\t\t\tconst collectedKeys: string[] = [];\n\t\t\tlet rounds = 0;\n\t\t\tlet scanComplete = false;\n\n\t\t\twhile (collectedKeys.length < limit && rounds < SCAN_ROUND_TRIP_CAP) {\n\t\t\t\tconst [next, batch] = (await client.scan(\n\t\t\t\t\tscanCursor,\n\t\t\t\t\t\"MATCH\",\n\t\t\t\t\t\"*\",\n\t\t\t\t\t\"COUNT\",\n\t\t\t\t\tMath.max(limit * 2, 100),\n\t\t\t\t\t\"TYPE\",\n\t\t\t\t\tredisType,\n\t\t\t\t)) as [string, string[]];\n\t\t\t\tcollectedKeys.push(...batch);\n\t\t\t\tscanCursor = next;\n\t\t\t\trounds++;\n\t\t\t\tif (next === \"0\") {\n\t\t\t\t\tscanComplete = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst pageKeys = collectedKeys.slice(0, limit);\n\t\t\tconst overflow = collectedKeys.slice(limit);\n\t\t\tconst rows = await this.hydrateRows(client, table, pageKeys);\n\n\t\t\tconst total = await client.dbsize();\n\t\t\tconst hasNextPage = !scanComplete || overflow.length > 0;\n\t\t\tconst nextCursor =\n\t\t\t\thasNextPage && !scanComplete ? encodeScanCursor({ scanCursor, type: table }) : null;\n\n\t\t\treturn {\n\t\t\t\tdata: rows,\n\t\t\t\tmeta: {\n\t\t\t\t\tlimit,\n\t\t\t\t\ttotal,\n\t\t\t\t\thasNextPage,\n\t\t\t\t\thasPreviousPage: false,\n\t\t\t\t\tnextCursor,\n\t\t\t\t\tprevCursor: null,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tprivate async hydrateRows(\n\t\tclient: Redis,\n\t\ttable: RedisTable,\n\t\tkeys: string[],\n\t): Promise<NormalizedRow[]> {\n\t\tif (keys.length === 0) return [];\n\n\t\tconst ttlPipeline = client.pipeline();\n\t\tfor (const key of keys) ttlPipeline.ttl(key);\n\t\tconst ttlResults = (await ttlPipeline.exec()) ?? [];\n\n\t\tconst valuePipeline = client.pipeline();\n\t\tfor (const key of keys) {\n\t\t\tswitch (table) {\n\t\t\t\tcase \"strings\":\n\t\t\t\t\tvaluePipeline.get(key);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hashes\":\n\t\t\t\t\tvaluePipeline.hgetall(key);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"lists\":\n\t\t\t\t\tvaluePipeline.lrange(key, 0, -1);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"sets\":\n\t\t\t\t\tvaluePipeline.smembers(key);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"zsets\":\n\t\t\t\t\tvaluePipeline.zrange(key, 0, -1, \"WITHSCORES\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"streams\":\n\t\t\t\t\tvaluePipeline.xinfo(\"STREAM\", key);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tconst valueResults = (await valuePipeline.exec()) ?? [];\n\n\t\treturn keys.map((key, i) => {\n\t\t\tconst ttl = (ttlResults[i]?.[1] as number | null) ?? -2;\n\t\t\tconst raw = valueResults[i]?.[1];\n\n\t\t\tif (table === \"streams\") {\n\t\t\t\tconst info = streamInfoToObject(raw);\n\t\t\t\treturn this.normalizeRow({\n\t\t\t\t\tkey,\n\t\t\t\t\tlength: info.length,\n\t\t\t\t\t\"first-id\": info.firstId,\n\t\t\t\t\t\"last-id\": info.lastId,\n\t\t\t\t\tttl,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlet value: unknown;\n\t\t\tswitch (table) {\n\t\t\t\tcase \"strings\":\n\t\t\t\t\tvalue = (raw as string | null) ?? null;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hashes\":\n\t\t\t\t\tvalue = raw as Record<string, unknown>;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"lists\":\n\t\t\t\tcase \"sets\":\n\t\t\t\t\tvalue = raw as unknown[];\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"zsets\":\n\t\t\t\t\tvalue = flatPairsToZsetEntries(raw as string[] | undefined);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn this.normalizeRow({ key, value, ttl } as Record<string, unknown>);\n\t\t});\n\t}\n\n\tprivate async getCachedCounts(dbIndex: number): Promise<Record<RedisTable, number>> {\n\t\tconst cached = this.countCache.get(dbIndex);\n\t\tif (cached && Date.now() - cached.timestamp < COUNT_CACHE_TTL_MS) {\n\t\t\treturn cached.counts;\n\t\t}\n\n\t\tconst client = await getRedisClient(dbIndex);\n\t\tconst counts = {} as Record<RedisTable, number>;\n\t\tconst pipeline = client.pipeline();\n\t\tfor (const table of REDIS_TABLES) {\n\t\t\tpipeline.scan(\n\t\t\t\t\"0\",\n\t\t\t\t\"MATCH\",\n\t\t\t\t\"*\",\n\t\t\t\t\"COUNT\",\n\t\t\t\tCOUNT_SCAN_CEILING,\n\t\t\t\t\"TYPE\",\n\t\t\t\tTABLE_TO_REDIS_TYPE[table],\n\t\t\t);\n\t\t}\n\t\tconst results = (await pipeline.exec()) ?? [];\n\t\tREDIS_TABLES.forEach((table, i) => {\n\t\t\tconst reply = results[i]?.[1] as [string, string[]] | undefined;\n\t\t\tcounts[table] = reply?.[1]?.length ?? 0;\n\t\t});\n\n\t\tthis.countCache.set(dbIndex, { timestamp: Date.now(), counts });\n\t\treturn counts;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Record operations\n\t// -----------------------------------------------------------------------\n\n\toverride async addRecord({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\ttry {\n\t\t\tconst { tableName, data } = params;\n\t\t\tconst table = assertRedisTable(tableName);\n\t\t\tconst key = extractKey(data);\n\t\t\tconst ttl = extractTtl(data);\n\t\t\tconst client = await getRedisClient(parseDbIndex(db));\n\n\t\t\tawait this.writeRecord(client, table, key, data.value, { mode: \"create\", ttl });\n\t\t\tthis.countCache.delete(parseDbIndex(db));\n\t\t\treturn { insertedCount: 1 };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async updateRecords({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\ttry {\n\t\t\tconst { tableName, updates, primaryKey, primaryKeys } = params;\n\t\t\tconst table = assertRedisTable(tableName);\n\t\t\tconst pkField = primaryKeys?.[0] || primaryKey || \"key\";\n\t\t\tconst client = await getRedisClient(parseDbIndex(db));\n\n\t\t\tconst updatesByKey = new Map<string, Record<string, unknown>>();\n\t\t\tfor (const u of updates) {\n\t\t\t\tconst k = u.rowData[pkField];\n\t\t\t\tif (k === undefined || k === null) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: `Primary key \"${pkField}\" not found in row data`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst keyStr = String(k);\n\t\t\t\tconst existing = updatesByKey.get(keyStr) ?? { ...u.rowData };\n\t\t\t\texisting[u.columnName] = u.value;\n\t\t\t\tupdatesByKey.set(keyStr, existing);\n\t\t\t}\n\n\t\t\tlet updatedCount = 0;\n\t\t\tfor (const [key, row] of updatesByKey.entries()) {\n\t\t\t\tconst value = row.value;\n\t\t\t\tconst ttl = extractTtl(row);\n\t\t\t\tawait this.writeRecord(client, table, key, value, { mode: \"update\", ttl });\n\n\t\t\t\t// Editing the `key` column is a rename, not a write to the old key.\n\t\t\t\tconst nextKeyRaw = row[pkField];\n\t\t\t\tconst nextKey =\n\t\t\t\t\tnextKeyRaw === undefined || nextKeyRaw === null ? key : String(nextKeyRaw);\n\t\t\t\tif (nextKey !== key) {\n\t\t\t\t\tconst renamed = await client.renamenx(key, nextKey);\n\t\t\t\t\tif (renamed === 0) {\n\t\t\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\t\t\tmessage: `Key \"${nextKey}\" already exists`,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tupdatedCount++;\n\t\t\t}\n\t\t\treturn { updatedCount };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async deleteRecords(params: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\ttry {\n\t\t\tconst { tableName, primaryKeys, db } = params;\n\t\t\tassertRedisTable(tableName);\n\t\t\tconst client = await getRedisClient(parseDbIndex(db));\n\t\t\tconst keys = primaryKeys.map((pk) => String(pk.value));\n\t\t\tif (keys.length === 0)\n\t\t\t\treturn { deletedCount: 0, fkViolation: false, relatedRecords: [] };\n\t\t\tconst deletedCount = await client.del(...keys);\n\t\t\tthis.countCache.delete(parseDbIndex(db));\n\t\t\treturn { deletedCount, fkViolation: false, relatedRecords: [] };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async forceDeleteRecords(\n\t\tparams: DeleteRecordParams,\n\t): Promise<{ deletedCount: number }> {\n\t\tconst result = await this.deleteRecords(params);\n\t\treturn { deletedCount: result.deletedCount };\n\t}\n\n\toverride async bulkInsertRecords(\n\t\tparams: BulkInsertRecordsParams,\n\t): Promise<BulkInsertResult> {\n\t\ttry {\n\t\t\tconst { tableName, records, db } = params;\n\t\t\tif (!records || records.length === 0) {\n\t\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\t\t\t}\n\t\t\tconst table = assertRedisTable(tableName);\n\t\t\tconst client = await getRedisClient(parseDbIndex(db));\n\n\t\t\tconst errors: Array<{ recordIndex: number; error: string }> = [];\n\t\t\tlet successCount = 0;\n\n\t\t\tfor (let i = 0; i < records.length; i++) {\n\t\t\t\tconst record = records[i] as Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tconst key = extractKey(record);\n\t\t\t\t\tconst ttl = extractTtl(record);\n\t\t\t\t\tawait this.writeRecord(client, table, key, record.value, { mode: \"create\", ttl });\n\t\t\t\t\tsuccessCount++;\n\t\t\t\t} catch (e) {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\trecordIndex: i,\n\t\t\t\t\t\terror: e instanceof Error ? e.message : String(e),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.countCache.delete(parseDbIndex(db));\n\t\t\treturn {\n\t\t\t\tsuccess: errors.length === 0,\n\t\t\t\tmessage: `Inserted ${successCount} of ${records.length} record${records.length === 1 ? \"\" : \"s\"}`,\n\t\t\t\tsuccessCount,\n\t\t\t\tfailureCount: errors.length,\n\t\t\t\t...(errors.length > 0 ? { errors } : {}),\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async exportTableData({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<{ cols: string[]; rows: Record<string, unknown>[] }> {\n\t\ttry {\n\t\t\tconst table = assertRedisTable(tableName);\n\t\t\tconst dbIndex = parseDbIndex(db);\n\t\t\tconst client = await getRedisClient(dbIndex);\n\t\t\tconst redisType = TABLE_TO_REDIS_TYPE[table];\n\n\t\t\tconst allKeys: string[] = [];\n\t\t\tlet scanCursor = \"0\";\n\t\t\tdo {\n\t\t\t\tconst [next, batch] = (await client.scan(\n\t\t\t\t\tscanCursor,\n\t\t\t\t\t\"MATCH\",\n\t\t\t\t\t\"*\",\n\t\t\t\t\t\"COUNT\",\n\t\t\t\t\t1000,\n\t\t\t\t\t\"TYPE\",\n\t\t\t\t\tredisType,\n\t\t\t\t)) as [string, string[]];\n\t\t\t\tallKeys.push(...batch);\n\t\t\t\tscanCursor = next;\n\t\t\t} while (scanCursor !== \"0\");\n\n\t\t\tif (allKeys.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Table \"${tableName}\" has no data`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst rows = await this.hydrateRows(client, table, allKeys);\n\t\t\tconst cols = TABLE_COLUMNS[table].map((c) => c.columnName);\n\t\t\treturn { cols, rows: rows as Record<string, CellValue>[] };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tprivate async writeRecord(\n\t\tclient: Redis,\n\t\ttable: RedisTable,\n\t\tkey: string,\n\t\tvalue: unknown,\n\t\topts: { mode: \"create\" | \"update\"; ttl: number | null },\n\t): Promise<void> {\n\t\tif (table === \"streams\" && opts.mode === \"update\") {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: \"Streams are append-only; updating a stream record is not supported\",\n\t\t\t});\n\t\t}\n\n\t\tif (opts.mode === \"create\") {\n\t\t\tif (table === \"strings\") {\n\t\t\t\tconst result = await client.set(\n\t\t\t\t\tkey,\n\t\t\t\t\ttypeof value === \"string\" ? value : JSON.stringify(value),\n\t\t\t\t\t\"NX\",\n\t\t\t\t);\n\t\t\t\tif (result === null) {\n\t\t\t\t\tthrow new HTTPException(409, { message: `Key \"${key}\" already exists` });\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst exists = await client.exists(key);\n\t\t\t\tif (exists) {\n\t\t\t\t\tthrow new HTTPException(409, { message: `Key \"${key}\" already exists` });\n\t\t\t\t}\n\t\t\t\tawait this.writeCollectionValue(client, table, key, value);\n\t\t\t}\n\t\t} else {\n\t\t\tif (table === \"strings\") {\n\t\t\t\tconst result = await client.set(\n\t\t\t\t\tkey,\n\t\t\t\t\ttypeof value === \"string\" ? value : JSON.stringify(value),\n\t\t\t\t\t\"XX\",\n\t\t\t\t);\n\t\t\t\tif (result === null) {\n\t\t\t\t\tthrow new HTTPException(404, { message: `Key \"${key}\" does not exist` });\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst exists = await client.exists(key);\n\t\t\t\tif (!exists) {\n\t\t\t\t\tthrow new HTTPException(404, { message: `Key \"${key}\" does not exist` });\n\t\t\t\t}\n\t\t\t\tawait client.del(key);\n\t\t\t\tawait this.writeCollectionValue(client, table, key, value);\n\t\t\t}\n\t\t}\n\n\t\tif (opts.ttl !== null && opts.ttl > 0) {\n\t\t\tawait client.expire(key, opts.ttl);\n\t\t}\n\t}\n\n\tprivate async writeCollectionValue(\n\t\tclient: Redis,\n\t\ttable: RedisTable,\n\t\tkey: string,\n\t\tvalue: unknown,\n\t): Promise<void> {\n\t\tswitch (table) {\n\t\t\tcase \"hashes\": {\n\t\t\t\tconst obj = coerceObject(value, \"hash\");\n\t\t\t\tconst flat: string[] = [];\n\t\t\t\tfor (const [field, val] of Object.entries(obj)) {\n\t\t\t\t\tflat.push(field, stringifyValue(val));\n\t\t\t\t}\n\t\t\t\tif (flat.length === 0) {\n\t\t\t\t\tthrow new HTTPException(400, { message: \"Hash must have at least one field\" });\n\t\t\t\t}\n\t\t\t\tawait client.hset(key, ...flat);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase \"lists\": {\n\t\t\t\tconst arr = coerceArray(value, \"list\");\n\t\t\t\tif (arr.length === 0) {\n\t\t\t\t\tthrow new HTTPException(400, { message: \"List must have at least one element\" });\n\t\t\t\t}\n\t\t\t\tawait client.rpush(key, ...arr.map(stringifyValue));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase \"sets\": {\n\t\t\t\tconst arr = coerceArray(value, \"set\");\n\t\t\t\tif (arr.length === 0) {\n\t\t\t\t\tthrow new HTTPException(400, { message: \"Set must have at least one member\" });\n\t\t\t\t}\n\t\t\t\tawait client.sadd(key, ...arr.map(stringifyValue));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase \"zsets\": {\n\t\t\t\tconst entries = coerceZsetEntries(value);\n\t\t\t\tif (entries.length === 0) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: \"Sorted set must have at least one member\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst args: (string | number)[] = [];\n\t\t\t\tfor (const e of entries) {\n\t\t\t\t\targs.push(e.score, e.member);\n\t\t\t\t}\n\t\t\t\tawait client.zadd(key, ...(args as [string, ...string[]]));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase \"streams\": {\n\t\t\t\tconst obj = coerceObject(value, \"stream\");\n\t\t\t\tconst flat: string[] = [];\n\t\t\t\tfor (const [field, val] of Object.entries(obj)) {\n\t\t\t\t\tflat.push(field, stringifyValue(val));\n\t\t\t\t}\n\t\t\t\tif (flat.length === 0) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: \"Stream entry must have at least one field\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait client.xadd(key, \"*\", ...(flat as [string, ...string[]]));\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Query execution\n\t// -----------------------------------------------------------------------\n\n\toverride async executeQuery({\n\t\tquery,\n\t\tdb,\n\t}: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\tconst startTime = performance.now();\n\t\ttry {\n\t\t\tif (!query?.trim()) {\n\t\t\t\tthrow new HTTPException(400, { message: \"Query is required\" });\n\t\t\t}\n\n\t\t\tlet argv: string[];\n\t\t\ttry {\n\t\t\t\targv = tokenizeCommand(query.trim());\n\t\t\t} catch (e) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: e instanceof Error ? e.message : \"Invalid Redis command\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (argv.length === 0) {\n\t\t\t\tthrow new HTTPException(400, { message: \"Empty command\" });\n\t\t\t}\n\n\t\t\tconst client = await getRedisClient(parseDbIndex(db));\n\t\t\tconst [cmd, ...rest] = argv;\n\n\t\t\tlet reply: unknown;\n\t\t\ttry {\n\t\t\t\treply = await client.call(cmd, ...rest);\n\t\t\t} catch (e) {\n\t\t\t\tconst message = e instanceof Error ? e.message : String(e);\n\t\t\t\treturn {\n\t\t\t\t\tcolumns: [\"error\"],\n\t\t\t\t\trows: [{ error: message }],\n\t\t\t\t\trowCount: 0,\n\t\t\t\t\tduration: performance.now() - startTime,\n\t\t\t\t\terror: message,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst shaped = shapeReply(argv, reply);\n\t\t\treturn {\n\t\t\t\t...shaped,\n\t\t\t\tduration: performance.now() - startTime,\n\t\t\t\tmessage: typeof reply === \"string\" ? reply : undefined,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction parseInfoSection(info: string): Record<string, string> {\n\tconst out: Record<string, string> = {};\n\tfor (const line of info.split(/\\r?\\n/)) {\n\t\tif (!line || line.startsWith(\"#\")) continue;\n\t\tconst idx = line.indexOf(\":\");\n\t\tif (idx < 0) continue;\n\t\tout[line.slice(0, idx)] = line.slice(idx + 1);\n\t}\n\treturn out;\n}\n\nfunction parseKeyspaceInfo(info: string): Map<number, number> {\n\tconst out = new Map<number, number>();\n\tfor (const line of info.split(/\\r?\\n/)) {\n\t\tconst match = line.match(/^db(\\d+):keys=(\\d+)/);\n\t\tif (match) out.set(Number(match[1]), Number(match[2]));\n\t}\n\treturn out;\n}\n\nfunction extractKey(data: Record<string, unknown>): string {\n\tconst k = data.key;\n\tif (k === undefined || k === null || k === \"\") {\n\t\tthrow new HTTPException(400, { message: \"Field 'key' is required\" });\n\t}\n\treturn String(k);\n}\n\nfunction extractTtl(data: Record<string, unknown>): number | null {\n\tconst t = data.ttl;\n\tif (t === undefined || t === null || t === \"\") return null;\n\tconst parsed = typeof t === \"number\" ? t : Number.parseInt(String(t), 10);\n\tif (!Number.isFinite(parsed)) return null;\n\treturn parsed;\n}\n\nfunction stringifyValue(v: unknown): string {\n\tif (typeof v === \"string\") return v;\n\tif (v === null || v === undefined) return \"\";\n\tif (typeof v === \"object\") return JSON.stringify(v);\n\treturn String(v);\n}\n\nfunction coerceObject(value: unknown, kind: string): Record<string, unknown> {\n\tif (typeof value === \"string\") {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(value);\n\t\t\tif (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n\t\t\t\treturn parsed as Record<string, unknown>;\n\t\t\t}\n\t\t} catch {\n\t\t\t// fall through\n\t\t}\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: `Value for ${kind} must be a JSON object`,\n\t\t});\n\t}\n\tif (value && typeof value === \"object\" && !Array.isArray(value)) {\n\t\treturn value as Record<string, unknown>;\n\t}\n\tthrow new HTTPException(400, { message: `Value for ${kind} must be a JSON object` });\n}\n\nfunction coerceArray(value: unknown, kind: string): unknown[] {\n\tif (Array.isArray(value)) return value;\n\tif (typeof value === \"string\") {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(value);\n\t\t\tif (Array.isArray(parsed)) return parsed;\n\t\t} catch {\n\t\t\t// fall through\n\t\t}\n\t}\n\tthrow new HTTPException(400, { message: `Value for ${kind} must be a JSON array` });\n}\n\nfunction coerceZsetEntries(value: unknown): { member: string; score: number }[] {\n\tlet arr: unknown[];\n\tif (Array.isArray(value)) {\n\t\tarr = value;\n\t} else if (typeof value === \"string\") {\n\t\ttry {\n\t\t\tarr = JSON.parse(value);\n\t\t} catch {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: \"Value for zset must be an array of {member, score} entries\",\n\t\t\t});\n\t\t}\n\t} else {\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: \"Value for zset must be an array of {member, score} entries\",\n\t\t});\n\t}\n\n\tconst out: { member: string; score: number }[] = [];\n\tfor (const entry of arr) {\n\t\tif (!entry || typeof entry !== \"object\") {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: \"Each zset entry must be an object with 'member' and 'score'\",\n\t\t\t});\n\t\t}\n\t\tconst obj = entry as { member?: unknown; score?: unknown };\n\t\tif (obj.member === undefined || obj.score === undefined) {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: \"Each zset entry must include 'member' and 'score'\",\n\t\t\t});\n\t\t}\n\t\tconst score = typeof obj.score === \"number\" ? obj.score : Number(obj.score);\n\t\tif (!Number.isFinite(score)) {\n\t\t\tthrow new HTTPException(400, { message: `Invalid score: ${String(obj.score)}` });\n\t\t}\n\t\tout.push({ member: String(obj.member), score });\n\t}\n\treturn out;\n}\n\nfunction flatPairsToZsetEntries(\n\treply: string[] | undefined,\n): { member: string; score: number }[] {\n\tif (!reply) return [];\n\tconst out: { member: string; score: number }[] = [];\n\tfor (let i = 0; i < reply.length; i += 2) {\n\t\tconst score = Number(reply[i + 1]);\n\t\tout.push({ member: reply[i], score: Number.isFinite(score) ? score : 0 });\n\t}\n\treturn out;\n}\n\nfunction streamInfoToObject(reply: unknown): {\n\tlength: number;\n\tfirstId: string | null;\n\tlastId: string | null;\n} {\n\tif (!Array.isArray(reply)) return { length: 0, firstId: null, lastId: null };\n\tconst obj: Record<string, unknown> = {};\n\tfor (let i = 0; i < reply.length; i += 2) {\n\t\tobj[String(reply[i])] = reply[i + 1];\n\t}\n\tconst length =\n\t\ttypeof obj.length === \"number\"\n\t\t\t? obj.length\n\t\t\t: Number.parseInt(String(obj.length ?? \"0\"), 10) || 0;\n\tconst firstEntry = obj[\"first-entry\"];\n\tconst lastEntry = obj[\"last-entry\"];\n\tconst idOf = (entry: unknown): string | null =>\n\t\tArray.isArray(entry) && typeof entry[0] === \"string\" ? entry[0] : null;\n\treturn { length, firstId: idOf(firstEntry), lastId: idOf(lastEntry) };\n}\n","import type { CursorData, FilterType, SortDirection, SortType } from \"@db-studio/shared/types\";\n\nexport function buildWhereClause(filters: FilterType[]): {\n\tclause: string;\n\tvalues: unknown[];\n} {\n\tif (!filters.length) return { clause: \"\", values: [] };\n\n\tconst conditions: string[] = [];\n\tconst values: unknown[] = [];\n\n\tfor (const filter of filters) {\n\t\tconst col = `\"${filter.columnName}\"`;\n\t\tswitch (filter.operator) {\n\t\t\tcase \"=\":\n\t\t\tcase \"!=\":\n\t\t\tcase \">\":\n\t\t\tcase \">=\":\n\t\t\tcase \"<\":\n\t\t\tcase \"<=\":\n\t\t\t\tconditions.push(`${col} ${filter.operator} ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"is\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${col} IS NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} = ?`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"is not\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${col} IS NOT NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} != ?`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"like\":\n\t\t\t\tconditions.push(`CAST(${col} AS TEXT) LIKE ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"not like\":\n\t\t\t\tconditions.push(`CAST(${col} AS TEXT) NOT LIKE ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"ilike\":\n\t\t\t\tconditions.push(`CAST(${col} AS TEXT) LIKE ? COLLATE NOCASE`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"not ilike\":\n\t\t\t\tconditions.push(`CAST(${col} AS TEXT) NOT LIKE ? COLLATE NOCASE`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!conditions.length) return { clause: \"\", values: [] };\n\treturn { clause: `WHERE ${conditions.join(\" AND \")}`, values };\n}\n\nexport function buildSortClause(sorts: SortType[] | string, order: SortDirection): string {\n\tif (Array.isArray(sorts)) {\n\t\tif (!sorts.length) return \"\";\n\t\treturn `ORDER BY ${sorts.map((s) => `\"${s.columnName}\" ${s.direction.toUpperCase()}`).join(\", \")}`;\n\t}\n\tif (sorts && typeof sorts === \"string\") {\n\t\treturn `ORDER BY \"${sorts}\" ${order?.toUpperCase() || \"ASC\"}`;\n\t}\n\treturn \"\";\n}\n\n/**\n * Builds cursor WHERE clause using SQLite row-value comparison (supported since 3.15.0).\n * Uses `?` positional placeholders.\n */\nexport function buildCursorWhereClause(\n\tcursorData: CursorData,\n\tdirection: SortDirection,\n\tsortDirection: SortDirection,\n): { clause: string; values: unknown[] } {\n\tconst { values, sortColumns } = cursorData;\n\tif (!sortColumns.length) return { clause: \"\", values: [] };\n\n\tconst isAscending = sortDirection === \"asc\";\n\tconst isForward = direction === \"asc\";\n\tconst useGreaterThan = isAscending === isForward;\n\tconst operator = useGreaterThan ? \">\" : \"<\";\n\n\tconst columnList = sortColumns.map((col) => `\"${col}\"`).join(\", \");\n\tconst placeholders = sortColumns.map(() => \"?\").join(\", \");\n\tconst queryValues = sortColumns.map((col) => values[col]);\n\n\treturn {\n\t\tclause: `(${columnList}) ${operator} (${placeholders})`,\n\t\tvalues: queryValues,\n\t};\n}\n","import { statSync } from \"node:fs\";\nimport type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tCursorData,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tFieldDataType,\n\tForeignKeyConstraint,\n\tForeignKeyDataType,\n\tRelatedRecord,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tSortDirection,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { mapSqliteToDataType, standardizeSqliteDataTypeLabel } from \"@db-studio/shared/types\";\nimport type Database from \"better-sqlite3\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getSqliteDb } from \"@/adapters/connections.js\";\nimport {\n\tbuildCursorWhereClause,\n\tbuildSortClause,\n\tbuildWhereClause,\n} from \"./sqlite.query-builder.js\";\n\ninterface TableInfoRow {\n\tcid: number;\n\tname: string;\n\ttype: string;\n\tnotnull: number;\n\tdflt_value: string | null;\n\tpk: number;\n}\n\ninterface FkRow {\n\tid: number;\n\tseq: number;\n\ttable: string;\n\tfrom: string;\n\tto: string;\n\ton_update: string;\n\ton_delete: string;\n}\n\nexport class SqliteAdapter extends BaseAdapter {\n\t// =========================================================\n\t// Abstract method implementations\n\t// =========================================================\n\n\tprotected async runQuery<T>(_db: string, sql: string, values: unknown[]): Promise<T> {\n\t\tconst sqliteDb = getSqliteDb();\n\t\tconst stmt = sqliteDb.prepare(sql);\n\t\t// biome-ignore lint/suspicious/noExplicitAny: better-sqlite3 requires spreading unknown[]\n\t\treturn stmt.all(...(values as any[])) as T;\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn `\"${name}\"`;\n\t}\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\treturn mapSqliteToDataType(nativeType);\n\t}\n\n\tmapFromUniversalType(universalType: string): string {\n\t\tconst map: Record<string, string> = {\n\t\t\ttext: \"TEXT\",\n\t\t\tnumber: \"INTEGER\",\n\t\t\tboolean: \"INTEGER\",\n\t\t\tjson: \"TEXT\",\n\t\t\tdate: \"TEXT\",\n\t\t\tarray: \"TEXT\",\n\t\t\tenum: \"TEXT\",\n\t\t};\n\t\treturn map[universalType] ?? \"TEXT\";\n\t}\n\n\tprotected buildTableDataQuery(params: GetTableDataParams): QueryBundle {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tcursor = \"\",\n\t\t\tlimit = 50,\n\t\t\tdirection = \"asc\",\n\t\t\tsort = [],\n\t\t\torder = \"asc\",\n\t\t\tfilters = [],\n\t\t} = params;\n\n\t\tlet sortColumns: string[] = [];\n\t\tlet effectiveSortDirection: SortDirection = order;\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t\teffectiveSortDirection = sort[0].direction;\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\t\tif (!sortColumns.length) sortColumns = [\"rowid\"];\n\n\t\tconst { clause: filterWhere, values: filterValues } = buildWhereClause(filters);\n\n\t\tlet cursorWhere = \"\";\n\t\tlet cursorValues: unknown[] = [];\n\t\tif (cursor) {\n\t\t\tconst cursorData = this.decodeCursor(cursor);\n\t\t\tif (cursorData) {\n\t\t\t\tconst res = buildCursorWhereClause(cursorData, direction, effectiveSortDirection);\n\t\t\t\tcursorWhere = res.clause;\n\t\t\t\tcursorValues = res.values;\n\t\t\t}\n\t\t}\n\n\t\tlet combinedWhere = \"\";\n\t\tif (filterWhere && cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${filterWhere.replace(/^WHERE\\s+/i, \"\")} AND ${cursorWhere}`;\n\t\t} else if (filterWhere) {\n\t\t\tcombinedWhere = filterWhere;\n\t\t} else if (cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${cursorWhere}`;\n\t\t}\n\n\t\tconst sortClause = buildSortClause(Array.isArray(sort) ? sort : sort, order);\n\t\tlet effectiveSortClause = sortClause;\n\n\t\tif (direction === \"desc\") {\n\t\t\tif (sortClause) {\n\t\t\t\teffectiveSortClause = sortClause\n\t\t\t\t\t.replace(/\\bASC\\b/gi, \"TEMP_DESC\")\n\t\t\t\t\t.replace(/\\bDESC\\b/gi, \"ASC\")\n\t\t\t\t\t.replace(/TEMP_DESC/g, \"DESC\");\n\t\t\t} else {\n\t\t\t\teffectiveSortClause = `ORDER BY ${sortColumns.map((col) => `\"${col}\" ${effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\"}`).join(\", \")}`;\n\t\t\t}\n\t\t} else if (!sortClause) {\n\t\t\teffectiveSortClause = `ORDER BY ${sortColumns.map((col) => `\"${col}\" ${effectiveSortDirection.toUpperCase()}`).join(\", \")}`;\n\t\t}\n\n\t\tconst sql = `SELECT * FROM \"${tableName}\" ${combinedWhere} ${effectiveSortClause} LIMIT ?`;\n\t\tconst values = [...filterValues, ...cursorValues, limit + 1];\n\t\tconst countSql = `SELECT COUNT(*) as total FROM \"${tableName}\" ${filterWhere}`;\n\n\t\treturn { sql, values, countSql, countValues: filterValues };\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn (rawRows as Record<string, unknown>[]).map((row) => this.normalizeRow(row));\n\t}\n\n\tprotected buildCursors(\n\t\tparams: GetTableDataParams,\n\t\trows: NormalizedRow[],\n\t\thasMore: boolean,\n\t): { nextCursor: string | null; prevCursor: string | null } {\n\t\tif (!rows.length) return { nextCursor: null, prevCursor: null };\n\n\t\tconst { direction = \"asc\", sort = [], cursor } = params;\n\t\tlet sortColumns: string[] = [];\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\t\tif (!sortColumns.length) sortColumns = [\"rowid\"];\n\n\t\tconst createCursor = (row: NormalizedRow): string => {\n\t\t\tconst data: CursorData = {\n\t\t\t\tvalues: Object.fromEntries(sortColumns.map((col) => [col, row[col]])),\n\t\t\t\tsortColumns,\n\t\t\t};\n\t\t\treturn this.encodeCursor(data);\n\t\t};\n\n\t\tconst firstRow = rows[0];\n\t\tconst lastRow = rows[rows.length - 1];\n\t\tlet nextCursor: string | null = null;\n\t\tlet prevCursor: string | null = null;\n\n\t\tif (direction === \"asc\") {\n\t\t\tif (hasMore) nextCursor = createCursor(lastRow);\n\t\t\tif (cursor) prevCursor = createCursor(firstRow);\n\t\t} else {\n\t\t\tif (cursor) nextCursor = createCursor(lastRow);\n\t\t\tif (hasMore) prevCursor = createCursor(firstRow);\n\t\t}\n\n\t\treturn { nextCursor, prevCursor };\n\t}\n\n\t// =========================================================\n\t// Override getTableData to use primary key columns for stable pagination\n\t// =========================================================\n\n\toverride async getTableData(params: GetTableDataParams) {\n\t\ttry {\n\t\t\tconst {\n\t\t\t\ttableName,\n\t\t\t\tdb,\n\t\t\t\tlimit = 50,\n\t\t\t\tdirection = \"asc\",\n\t\t\t\tsort = [],\n\t\t\t\torder = \"asc\",\n\t\t\t\tcursor,\n\t\t\t\tfilters = [],\n\t\t\t} = params;\n\n\t\t\tconst sqliteDb = getSqliteDb();\n\n\t\t\tconst colInfoRows = sqliteDb\n\t\t\t\t.prepare(`PRAGMA table_info(\"${tableName}\")`)\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: PRAGMA returns untyped rows\n\t\t\t\t.all() as any[];\n\t\t\tconst pkColumns: string[] = colInfoRows\n\t\t\t\t.filter((c) => c.pk > 0)\n\t\t\t\t.sort((a, b) => a.pk - b.pk)\n\t\t\t\t.map((c) => c.name);\n\n\t\t\tlet sortColumns: string[] = [];\n\t\t\tlet effectiveSortDirection: SortDirection = order;\n\t\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t\t\teffectiveSortDirection = sort[0].direction;\n\t\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\t\tsortColumns = [sort];\n\t\t\t}\n\n\t\t\tconst cursorColumns = [\n\t\t\t\t...sortColumns,\n\t\t\t\t...pkColumns.filter((pk) => !sortColumns.includes(pk)),\n\t\t\t];\n\t\t\tconst useRowid = cursorColumns.length === 0;\n\t\t\tif (useRowid) cursorColumns.push(\"rowid\");\n\n\t\t\tconst { clause: filterWhere, values: filterValues } = buildWhereClause(filters);\n\n\t\t\tlet cursorWhere = \"\";\n\t\t\tlet cursorValues: unknown[] = [];\n\t\t\tif (cursor) {\n\t\t\t\tconst cursorData = this.decodeCursor(cursor);\n\t\t\t\tif (cursorData) {\n\t\t\t\t\tconst res = buildCursorWhereClause(cursorData, direction, effectiveSortDirection);\n\t\t\t\t\tcursorWhere = res.clause;\n\t\t\t\t\tcursorValues = res.values;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet combinedWhere = \"\";\n\t\t\tif (filterWhere && cursorWhere) {\n\t\t\t\tcombinedWhere = `WHERE ${filterWhere.replace(/^WHERE\\s+/i, \"\")} AND ${cursorWhere}`;\n\t\t\t} else if (filterWhere) {\n\t\t\t\tcombinedWhere = filterWhere;\n\t\t\t} else if (cursorWhere) {\n\t\t\t\tcombinedWhere = `WHERE ${cursorWhere}`;\n\t\t\t}\n\n\t\t\tconst sortClause = buildSortClause(Array.isArray(sort) ? sort : sort, order);\n\t\t\tconst pkTieBreakerCols = pkColumns.filter((pk) => !sortColumns.includes(pk));\n\t\t\tlet effectiveSortClause = sortClause;\n\n\t\t\tif (direction === \"desc\") {\n\t\t\t\tif (sortClause) {\n\t\t\t\t\teffectiveSortClause = sortClause\n\t\t\t\t\t\t.replace(/\\bASC\\b/gi, \"TEMP_DESC\")\n\t\t\t\t\t\t.replace(/\\bDESC\\b/gi, \"ASC\")\n\t\t\t\t\t\t.replace(/TEMP_DESC/g, \"DESC\");\n\t\t\t\t\tif (pkTieBreakerCols.length) {\n\t\t\t\t\t\tconst tbDir = effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\";\n\t\t\t\t\t\teffectiveSortClause += `, ${pkTieBreakerCols.map((col) => `\"${col}\" ${tbDir}`).join(\", \")}`;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\teffectiveSortClause = `ORDER BY ${cursorColumns.map((col) => `\"${col}\" ${effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\"}`).join(\", \")}`;\n\t\t\t\t}\n\t\t\t} else if (!sortClause) {\n\t\t\t\teffectiveSortClause = `ORDER BY ${cursorColumns.map((col) => `\"${col}\" ${effectiveSortDirection.toUpperCase()}`).join(\", \")}`;\n\t\t\t} else if (pkTieBreakerCols.length) {\n\t\t\t\teffectiveSortClause += `, ${pkTieBreakerCols.map((col) => `\"${col}\" ${effectiveSortDirection.toUpperCase()}`).join(\", \")}`;\n\t\t\t}\n\n\t\t\tconst countRow = sqliteDb\n\t\t\t\t.prepare(`SELECT COUNT(*) as total FROM \"${tableName}\" ${filterWhere}`)\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: better-sqlite3 spread\n\t\t\t\t.get(...(filterValues as any[])) as { total: number } | undefined;\n\t\t\tconst total = Number(countRow?.total ?? 0);\n\n\t\t\t// When falling back to rowid for cursor, include it in SELECT so buildCursors can read it\n\t\t\tconst selectClause = useRowid ? \"*, rowid\" : \"*\";\n\t\t\tconst dataRows = sqliteDb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT ${selectClause} FROM \"${tableName}\" ${combinedWhere} ${effectiveSortClause} LIMIT ?`,\n\t\t\t\t)\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: better-sqlite3 spread\n\t\t\t\t.all(...([...filterValues, ...cursorValues, limit + 1] as any[])) as Record<\n\t\t\t\tstring,\n\t\t\t\tunknown\n\t\t\t>[];\n\n\t\t\tconst hasMore = dataRows.length > limit;\n\t\t\tlet rows = hasMore ? dataRows.slice(0, limit) : dataRows;\n\t\t\tif (direction === \"desc\") rows = rows.reverse();\n\n\t\t\tconst createCursor = (row: Record<string, unknown>): CursorData => ({\n\t\t\t\tvalues: Object.fromEntries(cursorColumns.map((col) => [col, row[col]])),\n\t\t\t\tsortColumns: cursorColumns,\n\t\t\t});\n\n\t\t\tlet nextCursor: string | null = null;\n\t\t\tlet prevCursor: string | null = null;\n\n\t\t\tif (rows.length > 0) {\n\t\t\t\tconst firstRow = rows[0];\n\t\t\t\tconst lastRow = rows[rows.length - 1];\n\t\t\t\tif (direction === \"asc\") {\n\t\t\t\t\tif (hasMore) nextCursor = this.encodeCursor(createCursor(lastRow));\n\t\t\t\t\tif (cursor) prevCursor = this.encodeCursor(createCursor(firstRow));\n\t\t\t\t} else {\n\t\t\t\t\tif (cursor) nextCursor = this.encodeCursor(createCursor(lastRow));\n\t\t\t\t\tif (hasMore) prevCursor = this.encodeCursor(createCursor(firstRow));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Strip the synthetic rowid from output rows if we added it\n\t\t\tconst finalRows = useRowid ? rows.map(({ rowid: _r, ...rest }) => rest) : rows;\n\n\t\t\tvoid db;\n\t\t\treturn {\n\t\t\t\tdata: finalRows as NormalizedRow[],\n\t\t\t\tmeta: {\n\t\t\t\t\tlimit,\n\t\t\t\t\ttotal,\n\t\t\t\t\thasNextPage: direction === \"asc\" ? hasMore : !!cursor,\n\t\t\t\t\thasPreviousPage: direction === \"asc\" ? !!cursor : hasMore,\n\t\t\t\t\tnextCursor,\n\t\t\t\t\tprevCursor,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// IDbAdapter — Databases\n\t// =========================================================\n\n\tasync getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst sqliteDb = getSqliteDb();\n\t\t\tconst rows = sqliteDb.prepare(\"PRAGMA database_list\").all() as Array<{\n\t\t\t\tseq: number;\n\t\t\t\tname: string;\n\t\t\t\tfile: string;\n\t\t\t}>;\n\n\t\t\tif (!rows.length)\n\t\t\t\tthrow new HTTPException(500, { message: \"No databases returned from SQLite\" });\n\n\t\t\t// Hide SQLite's internal temp database. `PRAGMA database_list` always\n\t\t\t// reports `main`, so filtering can never empty the list.\n\t\t\treturn rows\n\t\t\t\t.filter((row) => row.name !== \"temp\")\n\t\t\t\t.map((row) => ({\n\t\t\t\t\tname: row.name,\n\t\t\t\t\tsize: this.getFileSize(row.file),\n\t\t\t\t\towner: \"\",\n\t\t\t\t\tencoding: \"UTF-8\",\n\t\t\t\t}));\n\t\t} catch (e) {\n\t\t\tif (e instanceof HTTPException) throw e;\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\ttry {\n\t\t\tconst sqliteDb = getSqliteDb();\n\t\t\tconst rows = sqliteDb.prepare(\"PRAGMA database_list\").all() as Array<{ name: string }>;\n\t\t\tconst main = rows.find((r) => r.name === \"main\");\n\t\t\treturn { db: main?.name ?? \"main\" };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\ttry {\n\t\t\tconst sqliteDb = getSqliteDb();\n\t\t\tconst versionRow = sqliteDb.prepare(\"SELECT sqlite_version() as version\").get() as {\n\t\t\t\tversion: string;\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\thost: null,\n\t\t\t\tport: null,\n\t\t\t\tuser: \"\",\n\t\t\t\tdatabase: \"main\",\n\t\t\t\tversion: `SQLite ${versionRow.version}`,\n\t\t\t\tactive_connections: 1,\n\t\t\t\tmax_connections: 1,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// IDbAdapter — Tables\n\t// =========================================================\n\n\tasync getTablesList(_db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst sqliteDb = getSqliteDb();\n\t\t\tconst tables = sqliteDb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name`,\n\t\t\t\t)\n\t\t\t\t.all() as Array<{ name: string }>;\n\n\t\t\treturn tables.map((t) => {\n\t\t\t\tconst countRow = sqliteDb\n\t\t\t\t\t.prepare(`SELECT COUNT(*) as count FROM \"${t.name}\"`)\n\t\t\t\t\t.get() as { count: number };\n\t\t\t\treturn { tableName: t.name, rowCount: countRow?.count ?? 0 };\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync createTable({\n\t\ttableData,\n\t\tdb,\n\t}: {\n\t\ttableData: CreateTableSchemaType;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<void> {\n\t\tconst { tableName, fields, foreignKeys } = tableData;\n\t\tconst sqliteDb = getSqliteDb();\n\n\t\tconst columnDefs = fields.map((field: FieldDataType) => {\n\t\t\t// SQLite AUTOINCREMENT requires \"INTEGER PRIMARY KEY AUTOINCREMENT\"\n\t\t\tif (field.isPrimaryKey && field.isIdentity) {\n\t\t\t\treturn `\"${field.columnName}\" INTEGER PRIMARY KEY AUTOINCREMENT`;\n\t\t\t}\n\t\t\tlet def = `\"${field.columnName}\" ${field.columnType}`;\n\t\t\tif (field.isPrimaryKey) def += \" PRIMARY KEY\";\n\t\t\tif (field.isUnique && !field.isPrimaryKey) def += \" UNIQUE\";\n\t\t\tif (!field.isNullable && !field.isPrimaryKey) def += \" NOT NULL\";\n\t\t\tif (field.defaultValue?.trim() && !field.isIdentity)\n\t\t\t\tdef += ` DEFAULT ${field.defaultValue.trim()}`;\n\t\t\treturn def;\n\t\t});\n\n\t\tconst fkDefs =\n\t\t\tforeignKeys?.map(\n\t\t\t\t(fk: ForeignKeyDataType) =>\n\t\t\t\t\t`FOREIGN KEY (\"${fk.columnName}\") REFERENCES \"${fk.referencedTable}\" (\"${fk.referencedColumn}\") ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}`,\n\t\t\t) ?? [];\n\n\t\tsqliteDb\n\t\t\t.prepare(`CREATE TABLE \"${tableName}\" (${[...columnDefs, ...fkDefs].join(\", \")})`)\n\t\t\t.run();\n\n\t\tvoid db;\n\t}\n\n\tasync deleteTable(params: DeleteTableParams): Promise<DeleteTableResult> {\n\t\tconst { tableName, cascade } = params;\n\t\tconst sqliteDb = getSqliteDb();\n\n\t\tconst tableRow = sqliteDb\n\t\t\t.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`)\n\t\t\t.get(tableName);\n\t\tif (!tableRow)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst countRow = sqliteDb\n\t\t\t.prepare(`SELECT COUNT(*) as count FROM \"${tableName}\"`)\n\t\t\t.get() as { count: number };\n\t\tconst rowCount = countRow?.count ?? 0;\n\n\t\tif (!cascade) {\n\t\t\tconst related = this.getFkReferencesForTable(sqliteDb, tableName);\n\t\t\tif (related.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\tdeletedCount: 0,\n\t\t\t\t\tfkViolation: true,\n\t\t\t\t\trelatedRecords: this.getRelatedRecordsForTable(sqliteDb, tableName),\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tsqliteDb.prepare(`DROP TABLE \"${tableName}\"`).run();\n\t\t\treturn { deletedCount: rowCount, fkViolation: false, relatedRecords: [] };\n\t\t} catch (error) {\n\t\t\tconst errMsg = error instanceof Error ? error.message : String(error);\n\t\t\tif (errMsg.includes(\"FOREIGN KEY constraint\")) {\n\t\t\t\treturn {\n\t\t\t\t\tdeletedCount: 0,\n\t\t\t\t\tfkViolation: true,\n\t\t\t\t\trelatedRecords: this.getRelatedRecordsForTable(sqliteDb, tableName),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to delete table \"${tableName}\"` });\n\t\t}\n\t}\n\n\tasync renameTable(params: RenameTableParamsSchemaType): Promise<void> {\n\t\tconst { tableName, newTableName, db } = params;\n\t\tthis.assertDifferentTableName(tableName, newTableName);\n\t\tconst sqliteDb = getSqliteDb();\n\n\t\tconst tableRow = sqliteDb\n\t\t\t.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`)\n\t\t\t.get(tableName);\n\t\tif (!tableRow)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst targetRow = sqliteDb\n\t\t\t.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`)\n\t\t\t.get(newTableName);\n\t\tif (targetRow)\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Table \"${newTableName}\" already exists`,\n\t\t\t});\n\n\t\ttry {\n\t\t\t// Identifiers cannot be bound as parameters — escape the quote character.\n\t\t\tconst escapeIdent = (s: string) => s.replaceAll('\"', '\"\"');\n\t\t\tsqliteDb\n\t\t\t\t.prepare(\n\t\t\t\t\t`ALTER TABLE \"${escapeIdent(tableName)}\" RENAME TO \"${escapeIdent(newTableName)}\"`,\n\t\t\t\t)\n\t\t\t\t.run();\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\n\t\tvoid db;\n\t}\n\n\tasync getTableSchema({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\ttry {\n\t\t\tconst sqliteDb = getSqliteDb();\n\t\t\tconst row = sqliteDb\n\t\t\t\t.prepare(`SELECT sql FROM sqlite_master WHERE type='table' AND name=?`)\n\t\t\t\t.get(tableName) as { sql: string } | undefined;\n\t\t\tif (!row)\n\t\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t\tvoid db;\n\t\t\treturn row.sql;\n\t\t} catch (e) {\n\t\t\tif (e instanceof HTTPException) throw e;\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// IDbAdapter — Columns\n\t// =========================================================\n\n\tasync getTableColumns({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst sqliteDb = getSqliteDb();\n\n\t\t\tconst tableRow = sqliteDb\n\t\t\t\t.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`)\n\t\t\t\t.get(tableName);\n\t\t\tif (!tableRow)\n\t\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\t\tconst columns = sqliteDb\n\t\t\t\t.prepare(`PRAGMA table_info(\"${tableName}\")`)\n\t\t\t\t.all() as TableInfoRow[];\n\t\t\tconst fks = sqliteDb.prepare(`PRAGMA foreign_key_list(\"${tableName}\")`).all() as FkRow[];\n\n\t\t\tconst fkMap = new Map<string, FkRow>();\n\t\t\tfor (const fk of fks) {\n\t\t\t\tfkMap.set(fk.from, fk);\n\t\t\t}\n\n\t\t\tvoid db;\n\t\t\treturn columns.map((col) => {\n\t\t\t\tconst fk = fkMap.get(col.name);\n\t\t\t\tconst nativeType = col.type.toLowerCase();\n\t\t\t\treturn {\n\t\t\t\t\tcolumnName: col.name,\n\t\t\t\t\tdataType: mapSqliteToDataType(nativeType),\n\t\t\t\t\tdataTypeLabel: standardizeSqliteDataTypeLabel(nativeType),\n\t\t\t\t\tisNullable: col.notnull === 0 && col.pk === 0,\n\t\t\t\t\tcolumnDefault: col.dflt_value,\n\t\t\t\t\tisPrimaryKey: col.pk > 0,\n\t\t\t\t\tisForeignKey: fkMap.has(col.name),\n\t\t\t\t\treferencedTable: fk?.table ?? null,\n\t\t\t\t\treferencedColumn: fk?.to ?? null,\n\t\t\t\t\tenumValues: null,\n\t\t\t\t};\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tif (e instanceof HTTPException) throw e;\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync addColumn(params: AddColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, columnType, defaultValue, isNullable, isUnique, db } =\n\t\t\tparams;\n\t\tconst sqliteDb = getSqliteDb();\n\n\t\tconst tableRow = sqliteDb\n\t\t\t.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`)\n\t\t\t.get(tableName);\n\t\tif (!tableRow)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst colInfo = sqliteDb.prepare(`PRAGMA table_info(\"${tableName}\")`).all() as Array<{\n\t\t\tname: string;\n\t\t}>;\n\t\tif (colInfo.some((c) => c.name === columnName)) {\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${columnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\tlet def = `\"${columnName}\" ${columnType}`;\n\t\tif (isUnique) def += \" UNIQUE\";\n\t\tif (!isNullable) def += \" NOT NULL\";\n\t\tif (defaultValue?.trim()) def += ` DEFAULT ${defaultValue.trim()}`;\n\n\t\ttry {\n\t\t\tsqliteDb.prepare(`ALTER TABLE \"${tableName}\" ADD COLUMN ${def}`).run();\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\n\t\tvoid db;\n\t}\n\n\tasync deleteColumn(params: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\tconst { tableName, columnName, db } = params;\n\t\tconst sqliteDb = getSqliteDb();\n\n\t\tconst tableRow = sqliteDb\n\t\t\t.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`)\n\t\t\t.get(tableName);\n\t\tif (!tableRow)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst colInfo = sqliteDb.prepare(`PRAGMA table_info(\"${tableName}\")`).all() as Array<{\n\t\t\tname: string;\n\t\t}>;\n\t\tif (!colInfo.some((c) => c.name === columnName)) {\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tsqliteDb.prepare(`ALTER TABLE \"${tableName}\" DROP COLUMN \"${columnName}\"`).run();\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\n\t\tvoid db;\n\t\treturn { deletedCount: 1 };\n\t}\n\n\tasync alterColumn(params: AlterColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, columnType, isNullable, defaultValue, db } = params;\n\t\tconst sqliteDb = getSqliteDb();\n\n\t\tconst tableRow = sqliteDb\n\t\t\t.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`)\n\t\t\t.get(tableName);\n\t\tif (!tableRow)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst colInfo = sqliteDb\n\t\t\t.prepare(`PRAGMA table_info(\"${tableName}\")`)\n\t\t\t.all() as TableInfoRow[];\n\t\tif (!colInfo.some((c) => c.name === columnName)) {\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\t// SQLite doesn't support ALTER COLUMN — use the recreate-table approach\n\t\tconst pkCols = colInfo.filter((c) => c.pk > 0).sort((a, b) => a.pk - b.pk);\n\t\tconst hasCompositePk = pkCols.length > 1;\n\n\t\tconst newColDefs = colInfo.map((col) => {\n\t\t\tconst isTarget = col.name === columnName;\n\t\t\tconst type = isTarget ? columnType : col.type;\n\t\t\tconst nullable = isTarget ? isNullable : col.notnull === 0;\n\t\t\tconst defVal = isTarget ? defaultValue?.trim() || null : col.dflt_value;\n\t\t\tconst isPk = col.pk > 0;\n\n\t\t\tlet def = `\"${col.name}\" ${type}`;\n\t\t\tif (!hasCompositePk && isPk) def += \" PRIMARY KEY\";\n\t\t\tif (!isPk && !nullable) def += \" NOT NULL\";\n\t\t\tif (defVal) def += ` DEFAULT ${defVal}`;\n\t\t\treturn def;\n\t\t});\n\n\t\tif (hasCompositePk) {\n\t\t\tnewColDefs.push(`PRIMARY KEY (${pkCols.map((c) => `\"${c.name}\"`).join(\", \")})`);\n\t\t}\n\n\t\tconst fks = sqliteDb.prepare(`PRAGMA foreign_key_list(\"${tableName}\")`).all() as FkRow[];\n\t\tconst fksByGroup = new Map<number, FkRow[]>();\n\t\tfor (const fk of fks) {\n\t\t\tconst arr = fksByGroup.get(fk.id) ?? [];\n\t\t\tarr.push(fk);\n\t\t\tfksByGroup.set(fk.id, arr);\n\t\t}\n\t\tconst fkDefs = Array.from(fksByGroup.values()).map((group) => {\n\t\t\tconst from = group.map((f) => `\"${f.from}\"`).join(\", \");\n\t\t\tconst to = group.map((f) => `\"${f.to}\"`).join(\", \");\n\t\t\tconst { table, on_update, on_delete } = group[0];\n\t\t\treturn `FOREIGN KEY (${from}) REFERENCES \"${table}\" (${to}) ON UPDATE ${on_update} ON DELETE ${on_delete}`;\n\t\t});\n\n\t\tconst colNames = colInfo.map((c) => `\"${c.name}\"`).join(\", \");\n\t\tconst tempName = `${tableName}_alter_${Date.now()}`;\n\n\t\tconst existingIndexes = sqliteDb\n\t\t\t.prepare(\n\t\t\t\t`SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name=? AND sql IS NOT NULL`,\n\t\t\t)\n\t\t\t.all(tableName) as Array<{ sql: string }>;\n\t\tconst existingTriggers = sqliteDb\n\t\t\t.prepare(`SELECT sql FROM sqlite_master WHERE type='trigger' AND tbl_name=?`)\n\t\t\t.all(tableName) as Array<{ sql: string }>;\n\n\t\tsqliteDb.pragma(\"foreign_keys = OFF\");\n\t\tconst doAlter = sqliteDb.transaction(() => {\n\t\t\tsqliteDb\n\t\t\t\t.prepare(`CREATE TABLE \"${tempName}\" (${[...newColDefs, ...fkDefs].join(\", \")})`)\n\t\t\t\t.run();\n\t\t\tsqliteDb\n\t\t\t\t.prepare(\n\t\t\t\t\t`INSERT INTO \"${tempName}\" (${colNames}) SELECT ${colNames} FROM \"${tableName}\"`,\n\t\t\t\t)\n\t\t\t\t.run();\n\t\t\tsqliteDb.prepare(`DROP TABLE \"${tableName}\"`).run();\n\t\t\tsqliteDb.prepare(`ALTER TABLE \"${tempName}\" RENAME TO \"${tableName}\"`).run();\n\t\t});\n\n\t\ttry {\n\t\t\tdoAlter();\n\t\t\tfor (const { sql } of existingIndexes) {\n\t\t\t\tsqliteDb.prepare(sql).run();\n\t\t\t}\n\t\t\tfor (const { sql } of existingTriggers) {\n\t\t\t\tsqliteDb.prepare(sql).run();\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tif (e instanceof HTTPException) throw e;\n\t\t\tthrow this.wrapError(e);\n\t\t} finally {\n\t\t\tsqliteDb.pragma(\"foreign_keys = ON\");\n\t\t}\n\n\t\tvoid db;\n\t}\n\n\tasync renameColumn(params: RenameColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, newColumnName, db } = params;\n\t\tconst sqliteDb = getSqliteDb();\n\n\t\tconst tableRow = sqliteDb\n\t\t\t.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`)\n\t\t\t.get(tableName);\n\t\tif (!tableRow)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst colInfo = sqliteDb.prepare(`PRAGMA table_info(\"${tableName}\")`).all() as Array<{\n\t\t\tname: string;\n\t\t}>;\n\t\tif (!colInfo.some((c) => c.name === columnName)) {\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t\tif (colInfo.some((c) => c.name === newColumnName)) {\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${newColumnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tsqliteDb\n\t\t\t\t.prepare(\n\t\t\t\t\t`ALTER TABLE \"${tableName}\" RENAME COLUMN \"${columnName}\" TO \"${newColumnName}\"`,\n\t\t\t\t)\n\t\t\t\t.run();\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\n\t\tvoid db;\n\t}\n\n\t// =========================================================\n\t// IDbAdapter — Records\n\t// =========================================================\n\n\tasync addRecord({\n\t\tparams,\n\t}: {\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\tconst { tableName, data } = params;\n\t\tconst sqliteDb = getSqliteDb();\n\t\tconst columns = Object.keys(data);\n\t\tif (!columns.length)\n\t\t\tthrow new HTTPException(400, { message: \"No data provided for insert\" });\n\n\t\tconst values = Object.values(data).map((v) =>\n\t\t\tv !== null && typeof v === \"object\" ? JSON.stringify(v) : v,\n\t\t);\n\t\tconst colNames = columns.map((c) => `\"${c}\"`).join(\", \");\n\t\tconst placeholders = columns.map(() => \"?\").join(\", \");\n\n\t\ttry {\n\t\t\tconst result = sqliteDb\n\t\t\t\t.prepare(`INSERT INTO \"${tableName}\" (${colNames}) VALUES (${placeholders})`)\n\t\t\t\t.run(...values);\n\t\t\tif (result.changes === 0)\n\t\t\t\tthrow new HTTPException(500, {\n\t\t\t\t\tmessage: `Failed to insert record into \"${tableName}\"`,\n\t\t\t\t});\n\t\t\treturn { insertedCount: result.changes };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync updateRecords({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\tconst { tableName } = params;\n\t\tconst sqliteDb = getSqliteDb();\n\n\t\tconst keyColumns = this.resolveKeyColumns(params);\n\t\tconst groups = this.groupUpdatesByKey(params, keyColumns);\n\n\t\tconst doUpdate = sqliteDb.transaction(() => {\n\t\t\tlet total = 0;\n\t\t\tfor (const { keyValues, rowUpdates } of groups) {\n\t\t\t\tconst setClauses = rowUpdates.map((u) => `\"${u.columnName}\" = ?`).join(\", \");\n\t\t\t\tconst values = [\n\t\t\t\t\t...rowUpdates.map((u) =>\n\t\t\t\t\t\tu.value !== null && typeof u.value === \"object\"\n\t\t\t\t\t\t\t? JSON.stringify(u.value)\n\t\t\t\t\t\t\t: u.value,\n\t\t\t\t\t),\n\t\t\t\t\t...keyValues,\n\t\t\t\t];\n\t\t\t\tconst whereClauses = keyColumns.map((column) => `\"${column}\" = ?`).join(\" AND \");\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: better-sqlite3 spread\n\t\t\t\tconst result = sqliteDb\n\t\t\t\t\t.prepare(`UPDATE \"${tableName}\" SET ${setClauses} WHERE ${whereClauses}`)\n\t\t\t\t\t.run(...(values as any[]));\n\t\t\t\tif (result.changes === 0) {\n\t\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\t\tmessage: `Record with ${this.describeKey(keyColumns, keyValues)} not found in table \"${tableName}\"`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\ttotal += result.changes;\n\t\t\t}\n\t\t\treturn total;\n\t\t});\n\n\t\ttry {\n\t\t\tconst total = doUpdate();\n\t\t\tvoid db;\n\t\t\treturn { updatedCount: total };\n\t\t} catch (e) {\n\t\t\tif (e instanceof HTTPException) throw e;\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync deleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\tconst sqliteDb = getSqliteDb();\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst placeholders = pkValues.map(() => \"?\").join(\", \");\n\n\t\tconst doDelete = sqliteDb.transaction(() => {\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: better-sqlite3 spread\n\t\t\treturn sqliteDb\n\t\t\t\t.prepare(`DELETE FROM \"${tableName}\" WHERE \"${pkColumn}\" IN (${placeholders})`)\n\t\t\t\t.run(...(pkValues as any[])).changes;\n\t\t});\n\n\t\ttry {\n\t\t\tconst changes = doDelete();\n\t\t\tvoid db;\n\t\t\treturn { deletedCount: changes, fkViolation: false, relatedRecords: [] };\n\t\t} catch (e) {\n\t\t\tconst errMsg = e instanceof Error ? e.message : String(e);\n\t\t\tif (errMsg.includes(\"FOREIGN KEY constraint failed\")) {\n\t\t\t\tconst relatedRecords = this.getRelatedRecords(sqliteDb, tableName, primaryKeys);\n\t\t\t\tvoid db;\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync forceDeleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<{ deletedCount: number }> {\n\t\tconst sqliteDb = getSqliteDb();\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\n\t\tsqliteDb.pragma(\"foreign_keys = OFF\");\n\t\tconst doForceDelete = sqliteDb.transaction(() => {\n\t\t\tconst fkRefs = this.getFkReferencesForTable(sqliteDb, tableName);\n\t\t\tlet totalRelated = 0;\n\n\t\t\tfor (const fk of fkRefs) {\n\t\t\t\tconst ph = pkValues.map(() => \"?\").join(\", \");\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: better-sqlite3 spread\n\t\t\t\tconst res = sqliteDb\n\t\t\t\t\t.prepare(\n\t\t\t\t\t\t`DELETE FROM \"${fk.referencingTable}\" WHERE \"${fk.referencingColumn}\" IN (${ph})`,\n\t\t\t\t\t)\n\t\t\t\t\t.run(...(pkValues as any[]));\n\t\t\t\ttotalRelated += res.changes;\n\t\t\t}\n\n\t\t\tconst ph = pkValues.map(() => \"?\").join(\", \");\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: better-sqlite3 spread\n\t\t\tconst result = sqliteDb\n\t\t\t\t.prepare(`DELETE FROM \"${tableName}\" WHERE \"${pkColumn}\" IN (${ph})`)\n\t\t\t\t.run(...(pkValues as any[]));\n\t\t\treturn result.changes + totalRelated;\n\t\t});\n\n\t\ttry {\n\t\t\tconst deletedCount = doForceDelete();\n\t\t\tvoid db;\n\t\t\treturn { deletedCount };\n\t\t} catch (e) {\n\t\t\tif (e instanceof HTTPException) throw e;\n\t\t\tthrow this.wrapError(e);\n\t\t} finally {\n\t\t\tsqliteDb.pragma(\"foreign_keys = ON\");\n\t\t}\n\t}\n\n\tasync bulkInsertRecords({\n\t\ttableName,\n\t\trecords,\n\t\tdb,\n\t}: BulkInsertRecordsParams): Promise<BulkInsertResult> {\n\t\tif (!records?.length)\n\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\n\t\tconst sqliteDb = getSqliteDb();\n\t\tconst columns = Object.keys(records[0]);\n\t\tconst colNames = columns.map((c) => `\"${c}\"`).join(\", \");\n\t\tconst placeholders = columns.map(() => \"?\").join(\", \");\n\t\tconst stmt = sqliteDb.prepare(\n\t\t\t`INSERT INTO \"${tableName}\" (${colNames}) VALUES (${placeholders})`,\n\t\t);\n\n\t\tconst doInsert = sqliteDb.transaction((recs: typeof records) => {\n\t\t\tlet count = 0;\n\t\t\tfor (const record of recs) {\n\t\t\t\tconst values = columns.map((col) => {\n\t\t\t\t\tconst v = record[col];\n\t\t\t\t\treturn v !== null && typeof v === \"object\" ? JSON.stringify(v) : v;\n\t\t\t\t});\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: better-sqlite3 spread\n\t\t\t\tstmt.run(...(values as any[]));\n\t\t\t\tcount++;\n\t\t\t}\n\t\t\treturn count;\n\t\t});\n\n\t\ttry {\n\t\t\tconst successCount = doInsert(records);\n\t\t\tvoid db;\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `Bulk insert completed: ${successCount} records inserted`,\n\t\t\t\tsuccessCount,\n\t\t\t\tfailureCount: 0,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tif (e instanceof HTTPException) throw e;\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// IDbAdapter — Query\n\t// =========================================================\n\n\tasync executeQuery({\n\t\tquery,\n\t\tdb,\n\t}: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\tconst sqliteDb = getSqliteDb();\n\t\tif (!query?.trim()) throw new HTTPException(400, { message: \"Query is required\" });\n\n\t\tconst cleaned = query.trim().replace(/;+$/, \"\");\n\t\tconst start = performance.now();\n\n\t\ttry {\n\t\t\tconst stmt = sqliteDb.prepare(cleaned);\n\t\t\tif (stmt.reader) {\n\t\t\t\tconst rows = stmt.all() as Record<string, unknown>[];\n\t\t\t\tconst duration = performance.now() - start;\n\t\t\t\tvoid db;\n\t\t\t\treturn {\n\t\t\t\t\tcolumns: rows.length > 0 ? Object.keys(rows[0]) : [],\n\t\t\t\t\trows,\n\t\t\t\t\trowCount: rows.length,\n\t\t\t\t\tduration,\n\t\t\t\t\tmessage: rows.length === 0 ? \"OK\" : undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst info = stmt.run();\n\t\t\tconst duration = performance.now() - start;\n\t\t\tvoid db;\n\t\t\treturn {\n\t\t\t\tcolumns: [],\n\t\t\t\trows: [],\n\t\t\t\trowCount: info.changes,\n\t\t\t\tduration,\n\t\t\t\tmessage: `OK (${info.changes} rows affected)`,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// Private helpers\n\t// =========================================================\n\n\tprivate getFileSize(filePath: string): string {\n\t\tif (!filePath) return \"in-memory\";\n\t\ttry {\n\t\t\tconst stats = statSync(filePath);\n\t\t\tconst bytes = stats.size;\n\t\t\tif (bytes < 1024) return `${bytes} B`;\n\t\t\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\t\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n\t\t} catch {\n\t\t\treturn \"N/A\";\n\t\t}\n\t}\n\n\tprivate getFkReferencesForTable(\n\t\tsqliteDb: Database.Database,\n\t\ttableName: string,\n\t): ForeignKeyConstraint[] {\n\t\tconst allTables = sqliteDb\n\t\t\t.prepare(\n\t\t\t\t`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'`,\n\t\t\t)\n\t\t\t.all() as Array<{ name: string }>;\n\n\t\tconst references: ForeignKeyConstraint[] = [];\n\t\tfor (const table of allTables) {\n\t\t\tif (table.name === tableName) continue;\n\t\t\tconst fks = sqliteDb\n\t\t\t\t.prepare(`PRAGMA foreign_key_list(\"${table.name}\")`)\n\t\t\t\t.all() as FkRow[];\n\t\t\tfor (const fk of fks) {\n\t\t\t\tif (fk.table === tableName) {\n\t\t\t\t\treferences.push({\n\t\t\t\t\t\tconstraintName: `fk_${table.name}_${fk.from}_${tableName}_${fk.to}`,\n\t\t\t\t\t\treferencingTable: table.name,\n\t\t\t\t\t\treferencingColumn: fk.from,\n\t\t\t\t\t\treferencedTable: tableName,\n\t\t\t\t\t\treferencedColumn: fk.to,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn references;\n\t}\n\n\tprivate getRelatedRecordsForTable(\n\t\tsqliteDb: Database.Database,\n\t\ttableName: string,\n\t): RelatedRecord[] {\n\t\tconst fks = this.getFkReferencesForTable(sqliteDb, tableName);\n\t\tif (!fks.length) return [];\n\n\t\tconst results: RelatedRecord[] = [];\n\t\tfor (const fk of fks) {\n\t\t\tconst rows = sqliteDb\n\t\t\t\t.prepare(`SELECT * FROM \"${fk.referencingTable}\" LIMIT 100`)\n\t\t\t\t.all() as Record<string, unknown>[];\n\t\t\tif (rows.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: rows,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate getRelatedRecords(\n\t\tsqliteDb: Database.Database,\n\t\ttableName: string,\n\t\tprimaryKeys: DeleteRecordParams[\"primaryKeys\"],\n\t): RelatedRecord[] {\n\t\tconst fks = this.getFkReferencesForTable(sqliteDb, tableName);\n\t\tif (!fks.length) return [];\n\n\t\tconst results: RelatedRecord[] = [];\n\t\tfor (const fk of fks) {\n\t\t\tconst matchingPk = primaryKeys.find((pk) => pk.columnName === fk.referencedColumn);\n\t\t\tif (!matchingPk) continue;\n\t\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\t\tconst ph = pkValues.map(() => \"?\").join(\", \");\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: better-sqlite3 spread\n\t\t\tconst rows = sqliteDb\n\t\t\t\t.prepare(\n\t\t\t\t\t`SELECT * FROM \"${fk.referencingTable}\" WHERE \"${fk.referencingColumn}\" IN (${ph}) LIMIT 100`,\n\t\t\t\t)\n\t\t\t\t.all(...(pkValues as any[])) as Record<string, unknown>[];\n\t\t\tif (rows.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: rows,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n}\n","import { adapterRegistry } from \"@/adapters/adapter.registry.js\";\nimport { MongoAdapter } from \"@/adapters/mongo/mongo.adapter.js\";\nimport { MsSqlAdapter } from \"@/adapters/mssql/mssql.adapter.js\";\nimport { MySqlAdapter } from \"@/adapters/mysql/mysql.adapter.js\";\nimport { PgAdapter } from \"@/adapters/pg/pg.adapter.js\";\nimport { RedisAdapter } from \"@/adapters/redis/redis.adapter.js\";\nimport { SqliteAdapter } from \"@/adapters/sqlite/sqlite.adapter.js\";\n\n/**\n * Registers all DB adapters with the registry before routes are mounted.\n */\nexport function registerAdapters(): void {\n\tadapterRegistry.register(\"pg\", new PgAdapter());\n\tadapterRegistry.register(\"mysql\", new MySqlAdapter());\n\tadapterRegistry.register(\"mssql\", new MsSqlAdapter());\n\tadapterRegistry.register(\"mongodb\", new MongoAdapter());\n\tadapterRegistry.register(\"sqlite\", new SqliteAdapter());\n\tadapterRegistry.register(\"redis\", new RedisAdapter());\n}\n","import type { ApiError } from \"@db-studio/shared/types/api-response.types.js\";\nimport type { Context } from \"hono\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { DatabaseError } from \"pg\";\nimport { ZodError } from \"zod\";\nimport {\n\tcaptureServerError,\n\tdatabaseTypeForRequest,\n\toperationForRequest,\n\twriteOperationalLog,\n} from \"@/observability.js\";\n\n/** HTTPException leaves `name` as \"Error\", so it needs an explicit check. */\nconst errorTypeName = (e: unknown): string => {\n\tif (e instanceof HTTPException) return \"HTTPException\";\n\treturn e instanceof Error ? e.name : \"UnknownError\";\n};\n\nconst isConnectionError = (e: Error): boolean => {\n\tconst mysqlError = e as Error & { code?: string; errno?: number };\n\tconst isMysqlConnectionError =\n\t\tmysqlError.code === \"ECONNREFUSED\" ||\n\t\tmysqlError.code === \"ENOTFOUND\" ||\n\t\tmysqlError.code === \"ETIMEDOUT\" ||\n\t\tmysqlError.code === \"ER_ACCESS_DENIED_ERROR\" ||\n\t\tmysqlError.code === \"ER_BAD_HOST_ERROR\" ||\n\t\tmysqlError.code === \"ECONNRESET\" ||\n\t\tmysqlError.errno === 1045 ||\n\t\tmysqlError.errno === 2003 ||\n\t\tmysqlError.errno === 2002;\n\n\treturn (\n\t\tisMysqlConnectionError ||\n\t\te.message.includes(\"ECONNREFUSED\") ||\n\t\te.message.includes(\"connection refused\") ||\n\t\te.message.includes(\"timeout expired\") ||\n\t\te.message.includes(\"Connection terminated\") ||\n\t\te.message.includes(\"MongoNetworkError\") ||\n\t\te.message.includes(\"MongoServerSelectionError\") ||\n\t\t(e instanceof DatabaseError && e.code?.startsWith(\"08\") === true)\n\t);\n};\n\nconst statusForError = (e: unknown): number => {\n\tif (e instanceof HTTPException) return e.status;\n\tif (e instanceof ZodError) return 400;\n\tif (e instanceof Error && isConnectionError(e)) return 503;\n\treturn 500;\n};\n\n/**\n * Centralized error handler for the application\n */\nexport function handleError(e: Error | unknown, c: Context) {\n\tconst operation = operationForRequest(c.req.method, c.req.path);\n\tconst errorType = errorTypeName(e);\n\tconst status = statusForError(e);\n\twriteOperationalLog(\"error\", \"request_failed\", { operation, error_type: errorType });\n\tcaptureServerError(e, {\n\t\toperation,\n\t\tstatus,\n\t\tdbType: databaseTypeForRequest(c.req.path),\n\t});\n\n\tif (e instanceof HTTPException) {\n\t\treturn c.json<ApiError>(\n\t\t\t{\n\t\t\t\terror: e.message ?? \"Internal server error\",\n\t\t\t},\n\t\t\te.status,\n\t\t);\n\t}\n\n\tif (e instanceof ZodError) {\n\t\tconst issue = e.issues[0];\n\t\treturn c.json<ApiError>(\n\t\t\t{\n\t\t\t\terror: \"Validation error\",\n\t\t\t\tdetails: issue.message,\n\t\t\t},\n\t\t\t400,\n\t\t);\n\t}\n\n\tif (e instanceof Error) {\n\t\tif (isConnectionError(e)) {\n\t\t\treturn c.json<ApiError>(\n\t\t\t\t{ error: \"Database connection failed\", details: e.message },\n\t\t\t\t503,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn c.json<ApiError>(\n\t\t{\n\t\t\terror: e instanceof Error ? e.message : \"Internal server error\",\n\t\t},\n\t\t500,\n\t);\n}\n\nexport const validationHook = (\n\tresult: {\n\t\tsuccess: boolean;\n\t\tdata?: unknown;\n\t\terror?: { issues: { message: string }[] };\n\t},\n\tc: Context,\n): Response | undefined => {\n\tif (!result.success) {\n\t\tconst issue = result.error?.issues[0];\n\t\treturn c.json<ApiError>(\n\t\t\t{\n\t\t\t\terror: \"Validation error\",\n\t\t\t\tdetails: issue?.message ?? \"Unknown validation error\",\n\t\t\t},\n\t\t\t400,\n\t\t);\n\t}\n};\n","import type { DatabaseSchema } from \"@db-studio/shared/types\";\n\n/**\n * Generate system prompt with database context\n */\nexport function generateSystemPrompt(schema: DatabaseSchema | null): string {\n\tif (!schema) {\n\t\treturn `You are a database assistant for db-studio. Keep answers concise and focused.\n\nThe user chose not to share their database schema. Do not claim to know their table or column names. Ask for the minimum missing details needed to answer accurately, generate queries in fenced code blocks, and warn before potentially destructive or expensive operations.`;\n\t}\n\n\tconst dbTypeLower = schema.dbType.toLowerCase();\n\tconst dbTypeLabel = schema.dbType === \"pg\" ? \"PostgreSQL\" : schema.dbType;\n\tif (dbTypeLower.includes(\"mongo\")) {\n\t\treturn `You are a database assistant for db-studio. Your responses must be CONCISE and FOCUSED.\n\n**Your Role:**\n1. Keep responses SHORT - 2-3 sentences maximum unless generating a query\n2. When generating MongoDB queries:\n - Provide 1 sentence explanation\n - The MongoDB query in a JSON code block\n - 1 sentence about expected results\n3. Use exact collection/field names from the schema\n4. If query is unclear, ask ONE specific clarifying question\n5. No preamble, no apologies, get straight to the answer\n6. IMPORTANT: When the user asks about collections, fields, or any schema information, answer DIRECTLY from the \"Database Context\" above — do NOT generate a query to retrieve schema info you already have\n\n**Database Context:**\n${formatSchemaForPrompt(schema)}\n\n**Guidelines:**\n1. Always generate syntactically correct MongoDB queries\n2. Use proper collection/field names exactly as defined in the schema\n3. When generating queries, wrap them in \\`\\`\\`json code blocks\n4. Explain what the query does in plain language\n5. Suggest relevant follow-up questions or analyses\n6. If a request is ambiguous, ask clarifying questions\n7. Warn about potentially expensive operations (collection scans, large aggregations)\n8. Consider data privacy - remind users not to share sensitive data externally\n\n**Query Format:**\nReturn a JSON object with the following shape:\n{\n \"collection\": \"collectionName\",\n \"operation\": \"find|aggregate|insertOne|insertMany|updateOne|updateMany|deleteOne|deleteMany|count\",\n \"filter\": { ... },\n \"pipeline\": [ ... ],\n \"document\": { ... } | [ ... ],\n \"update\": { ... },\n \"options\": { ... },\n \"sort\": { \"field\": 1 },\n \"limit\": 100,\n \"skip\": 0\n}\n\nOnly include the fields needed for the chosen operation.\n\n**Example:**\nUser: \"Show me the top 5 customers by revenue\"\n\nResponse: \"I'll aggregate orders to calculate total revenue per customer.\n\n\\`\\`\\`json\n{\n \"collection\": \"orders\",\n \"operation\": \"aggregate\",\n \"pipeline\": [\n { \"$group\": { \"_id\": \"$customer_id\", \"total\": { \"$sum\": \"$total_amount\" } } },\n { \"$sort\": { \"total\": -1 } },\n { \"$limit\": 5 }\n ]\n}\n\\`\\`\\`\n\nThis will return the top 5 customers by revenue.\"`;\n\t}\n\n\treturn `You are a database assistant for db-studio. Your responses must be CONCISE and FOCUSED.\n\n**Your Role:**\n1. Keep responses SHORT - 2-3 sentences maximum unless generating SQL\n2. When generating SQL:\n - Provide 1 sentence explanation\n - The SQL query in a code block\n - 1 sentence about expected results\n - NO verbose explanations\n3. Use exact table/column names from the schema\n4. Generate valid ${dbTypeLabel} syntax\n5. If query is unclear, ask ONE specific clarifying question\n6. No preamble, no apologies, get straight to the answer\n7. IMPORTANT: When the user asks about tables, columns, relationships, or any schema information, answer DIRECTLY from the \"Database Context\" above — do NOT generate a SQL query to retrieve schema info you already have\n\n**Database Context:**\n${formatSchemaForPrompt(schema)}\n\n**Guidelines:**\n1. Always generate syntactically correct SQL for the database type (${dbTypeLabel})\n2. Use proper table/column names exactly as defined in the schema\n3. When generating queries, wrap them in \\`\\`\\`sql code blocks\n4. Explain what the query does in plain language\n5. Suggest relevant follow-up questions or analyses\n6. If a request is ambiguous, ask clarifying questions\n7. For complex queries, break down the logic step-by-step\n8. Warn about potentially expensive operations (full table scans, etc.)\n9. Consider data privacy - remind users not to share sensitive data externally\n\n**Response Format:**\nWhen generating queries, use this structure:\n- Brief explanation of what you'll do\n- The SQL query in a code block\n- Expected results description\n- Optional: suggestions for related queries\n\n**Example:**\nUser: \"Show me the top 5 customers by revenue\"\n\nResponse: \"I'll query the orders and customers tables to find your highest-value customers.\n\n\\`\\`\\`sql\nSELECT \n c.customer_name,\n SUM(o.total_amount) as total_revenue\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.customer_name\nORDER BY total_revenue DESC\nLIMIT 5;\n\\`\\`\\`\n\nThis will return the 5 customers with the highest total order value. You might also want to see:\n- Revenue trends over time for these customers\n- Their most frequently ordered products\"`;\n}\n\n/**\n * Format schema information for the prompt\n */\nfunction formatSchemaForPrompt(schema: DatabaseSchema): string {\n\tconst dbTypeLabel = schema.dbType === \"pg\" ? \"PostgreSQL\" : schema.dbType;\n\tlet output = `Database Type: ${dbTypeLabel}\\n\\n`;\n\n\toutput += \"**Tables and Columns:**\\n\";\n\tfor (const table of schema.tables) {\n\t\toutput += `\\n### ${table.name}\\n`;\n\t\tif (table.description) {\n\t\t\toutput += `Description: ${table.description}\\n`;\n\t\t}\n\t\toutput += \"Columns:\\n\";\n\n\t\tfor (const col of table.columns) {\n\t\t\tconst pkIndicator = col.isPrimaryKey ? \" [PRIMARY KEY]\" : \"\";\n\t\t\tconst fkIndicator = col.foreignKey ? ` [FK -> ${col.foreignKey}]` : \"\";\n\t\t\tconst nullable = col.nullable ? \"NULL\" : \"NOT NULL\";\n\n\t\t\toutput += ` - ${col.name}: ${col.type} ${nullable}${pkIndicator}${fkIndicator}\\n`;\n\t\t\tif (col.description) {\n\t\t\t\toutput += ` ${col.description}\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Add sample data if available\n\t\tif (table.sampleData && table.sampleData.length > 0) {\n\t\t\toutput += `Sample data (${table.sampleData.length} rows):\\n`;\n\t\t\toutput += `${JSON.stringify(table.sampleData.slice(0, 3), null, 2)}\\n`;\n\t\t}\n\t}\n\n\t// Add relationships\n\tif (schema.relationships && schema.relationships.length > 0) {\n\t\toutput += \"\\n**Relationships:**\\n\";\n\t\tfor (const rel of schema.relationships) {\n\t\t\toutput += ` - ${rel.fromTable}.${rel.fromColumn} -> ${rel.toTable}.${rel.toColumn}\\n`;\n\t\t}\n\t}\n\n\treturn output;\n}\n","import type {\n\tColumn,\n\tColumnInfoSchemaType,\n\tDatabaseSchema,\n\tDatabaseSchemaType,\n\tRelationship,\n\tTable,\n} from \"@db-studio/shared/types\";\nimport type { IDbAdapter } from \"@/adapters/adapter.interface.js\";\nimport { getAdapter } from \"@/adapters/adapter.registry.js\";\nimport { getDbType } from \"@/db-manager.js\";\n\nfunction convertColumnInfo(col: ColumnInfoSchemaType): Column {\n\tconst column: Column = {\n\t\tname: col.columnName,\n\t\ttype: col.dataTypeLabel,\n\t\tnullable: col.isNullable,\n\t};\n\n\tif (col.isPrimaryKey) {\n\t\tcolumn.isPrimaryKey = true;\n\t}\n\n\tif (col.isForeignKey && col.referencedTable && col.referencedColumn) {\n\t\tcolumn.foreignKey = `${col.referencedTable}.${col.referencedColumn}`;\n\t}\n\n\tif (col.enumValues && col.enumValues.length > 0) {\n\t\tcolumn.enumValues = col.enumValues;\n\t\tcolumn.description = `Enum values: ${col.enumValues.join(\", \")}`;\n\t}\n\n\treturn column;\n}\n\nfunction extractRelationships(tables: Table[]): Relationship[] {\n\tconst relationships: Relationship[] = [];\n\n\tfor (const table of tables) {\n\t\tfor (const column of table.columns) {\n\t\t\tif (column.foreignKey) {\n\t\t\t\tconst [toTable, toColumn] = column.foreignKey.split(\".\");\n\t\t\t\trelationships.push({\n\t\t\t\t\tfromTable: table.name,\n\t\t\t\t\tfromColumn: column.name,\n\t\t\t\t\ttoTable,\n\t\t\t\t\ttoColumn,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn relationships;\n}\n\nfunction stringifySampleValue(value: unknown): string {\n\tif (value == null) {\n\t\treturn \"\";\n\t}\n\n\tif (value instanceof Date) {\n\t\treturn value.toISOString();\n\t}\n\n\tif (typeof value === \"bigint\") {\n\t\treturn value.toString();\n\t}\n\n\tif (typeof value === \"object\") {\n\t\ttry {\n\t\t\treturn JSON.stringify(value);\n\t\t} catch {\n\t\t\treturn String(value);\n\t\t}\n\t}\n\n\treturn String(value);\n}\n\nasync function getSampleData(\n\tadapter: IDbAdapter,\n\ttableName: string,\n\tdb: DatabaseSchemaType[\"db\"],\n): Promise<Record<string, string>[]> {\n\ttry {\n\t\tconst result = await adapter.getTableData({ tableName, db, limit: 3 });\n\t\treturn result.data.map((row) =>\n\t\t\tObject.fromEntries(\n\t\t\t\tObject.entries(row).map(([key, value]) => [key, stringifySampleValue(value)]),\n\t\t\t),\n\t\t);\n\t} catch (error) {\n\t\tconsole.warn(`Could not fetch sample data for table ${tableName}:`, error);\n\t\treturn [];\n\t}\n}\n\nasync function getTableColumns(\n\tadapter: IDbAdapter,\n\ttableName: string,\n\tdb: DatabaseSchemaType[\"db\"],\n): Promise<ColumnInfoSchemaType[]> {\n\ttry {\n\t\treturn await adapter.getTableColumns({ tableName, db });\n\t} catch (error) {\n\t\tconsole.warn(`Could not fetch columns for table ${tableName}:`, error);\n\t\treturn [];\n\t}\n}\n\nasync function getDatabaseSchema(\n\tdb: DatabaseSchemaType[\"db\"],\n\toptions: {\n\t\tincludeSampleData?: boolean;\n\t\tincludeDescriptions?: boolean;\n\t\tmaxTables?: number;\n\t} = {},\n): Promise<DatabaseSchema> {\n\tconst dbType = getDbType();\n\tconst { includeSampleData = false, maxTables } = options;\n\tconst adapter = getAdapter(dbType);\n\n\ttry {\n\t\tconst tablesList = await adapter.getTablesList(db);\n\t\tconst selectedTables = tablesList.slice(0, maxTables ?? tablesList.length);\n\n\t\tconst tablePromises = selectedTables.map(async ({ schemaName, tableName }) => {\n\t\t\tconst [columns, sampleData] = await Promise.all([\n\t\t\t\tgetTableColumns(adapter, tableName, db),\n\t\t\t\tincludeSampleData ? getSampleData(adapter, tableName, db) : Promise.resolve([]),\n\t\t\t]);\n\n\t\t\tconst table: Table = {\n\t\t\t\tname: schemaName ? `${schemaName}.${tableName}` : tableName,\n\t\t\t\tcolumns: columns.map(convertColumnInfo),\n\t\t\t};\n\n\t\t\tif (sampleData.length > 0) {\n\t\t\t\ttable.sampleData = sampleData;\n\t\t\t}\n\n\t\t\treturn table;\n\t\t});\n\n\t\tconst tables = await Promise.all(tablePromises);\n\t\tconst relationships = extractRelationships(tables);\n\n\t\treturn { dbType, tables, relationships };\n\t} catch (error) {\n\t\tconsole.error(\"Error fetching database schema:\", error);\n\t\tthrow new Error(\n\t\t\t`Failed to fetch database schema: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t);\n\t}\n}\n\nexport async function getDetailedSchema(\n\tdb: DatabaseSchemaType[\"db\"],\n): Promise<DatabaseSchema> {\n\treturn getDatabaseSchema(db, {\n\t\tincludeSampleData: true,\n\t\tincludeDescriptions: true,\n\t});\n}\n","import { DEFAULTS, LIMIT } from \"@db-studio/shared/constants\";\nimport { chatSchema } from \"@db-studio/shared/types\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { RouteEnv } from \"@/app.types.js\";\nimport { generateSystemPrompt } from \"@/utils/system-prompt-generator.js\";\nimport { getDetailedSchema } from \"@/utils/table-details-schema.js\";\n\nconst LOOPBACK_HOSTNAMES = new Set([\"localhost\", \"127.0.0.1\", \"::1\", \"[::1]\"]);\n\n/**\n * BYOK API keys are forwarded to the proxy as request headers, so the\n * destination must be encrypted. `DB_STUDIO_PROXY_URL` can override the HTTPS\n * default, so plain HTTP is only tolerated when it points at loopback — the\n * local `bun run dev` proxy.\n */\nconst resolveProxyUrl = (): string => {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(DEFAULTS.PROXY_URL);\n\t} catch {\n\t\tthrow new HTTPException(500, {\n\t\t\tmessage: \"DB_STUDIO_PROXY_URL is not a valid URL\",\n\t\t});\n\t}\n\n\tconst isLoopback =\n\t\tLOOPBACK_HOSTNAMES.has(url.hostname) || url.hostname.endsWith(\".localhost\");\n\tif (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && isLoopback)) {\n\t\tthrow new HTTPException(500, {\n\t\t\tmessage: \"DB_STUDIO_PROXY_URL must use HTTPS unless it points at loopback\",\n\t\t});\n\t}\n\n\treturn url.origin;\n};\n\nexport const chatRoutes = new Hono<RouteEnv>()\n\t/**\n\t * Base path for the endpoints, /:dbType/chat/...\n\t */\n\t.basePath(\"/chat\")\n\n\t/**\n\t * GET /chat/limit - Proxy rate limit check to Cloudflare Worker\n\t */\n\t.get(\"/limit\", async (c) => {\n\t\t// Outside the try: a misconfigured proxy URL is a server error, not an\n\t\t// exhausted quota, so it must not be masked by the fallback below.\n\t\tconst proxyUrl = resolveProxyUrl();\n\n\t\ttry {\n\t\t\tconst proxyResponse = await fetch(`${proxyUrl}/chat/limit`, {\n\t\t\t\theaders: {\n\t\t\t\t\t\"cf-connecting-ip\": c.req.header(\"cf-connecting-ip\") ?? \"\",\n\t\t\t\t\t\"x-real-ip\": c.req.header(\"x-real-ip\") ?? \"\",\n\t\t\t\t\t\"x-forwarded-for\": c.req.header(\"x-forwarded-for\") ?? \"\",\n\t\t\t\t\t\"x-api-key\": c.req.header(\"x-api-key\") ?? \"\",\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (!proxyResponse.ok) {\n\t\t\t\treturn c.json({ limit: LIMIT, used: LIMIT, remaining: 0 }, 200);\n\t\t\t}\n\t\t\treturn c.json(await proxyResponse.json(), 200);\n\t\t} catch {\n\t\t\treturn c.json({ limit: LIMIT, used: LIMIT, remaining: 0 }, 200);\n\t\t}\n\t})\n\n\t/**\n\t * POST /chat - Handle AI chat requests with streaming\n\t * Proxies to the Cloudflare Worker which has the Gemini API key\n\t */\n\t.post(\"/\", zValidator(\"json\", chatSchema), async (c) => {\n\t\tconst { messages, data, provider, model } = c.req.valid(\"json\");\n\t\tconst { db, conversationId, includeSchema } = data;\n\n\t\t// Get the database schema and generate system prompt\n\t\tconst schema = includeSchema ? await getDetailedSchema(db) : null;\n\t\tconst systemPrompt = generateSystemPrompt(schema);\n\n\t\tconst payload = {\n\t\t\tmessages,\n\t\t\tconversationId,\n\t\t\tsystemPrompt,\n\t\t\tprovider,\n\t\t\tmodel,\n\t\t};\n\n\t\t// Forward request to the proxy with the system prompt.\n\t\t// Pass through IP headers so the proxy rate-limiter keys on the real user IP.\n\t\tconst proxyResponse = await fetch(`${resolveProxyUrl()}/chat`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"cf-connecting-ip\": c.req.header(\"cf-connecting-ip\") ?? \"\",\n\t\t\t\t\"x-real-ip\": c.req.header(\"x-real-ip\") ?? \"\",\n\t\t\t\t\"x-forwarded-for\": c.req.header(\"x-forwarded-for\") ?? \"\",\n\t\t\t\t\"x-api-key\": c.req.header(\"x-api-key\") ?? \"\",\n\t\t\t\t\"x-byok-gemini\": c.req.header(\"x-byok-gemini\") ?? \"\",\n\t\t\t\t\"x-byok-openai\": c.req.header(\"x-byok-openai\") ?? \"\",\n\t\t\t\t\"x-byok-anthropic\": c.req.header(\"x-byok-anthropic\") ?? \"\",\n\t\t\t\t\"x-byok-grok\": c.req.header(\"x-byok-grok\") ?? \"\",\n\t\t\t\t\"x-byok-openrouter\": c.req.header(\"x-byok-openrouter\") ?? \"\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(payload),\n\t\t});\n\n\t\tif (!proxyResponse.ok) {\n\t\t\tconst errorData = await proxyResponse.json();\n\t\t\treturn c.json(\n\t\t\t\t{ error: errorData.error || \"Proxy request failed\" },\n\t\t\t\tproxyResponse.status as 400 | 401 | 500,\n\t\t\t);\n\t\t}\n\n\t\t// Relay the original stream directly. A detached pipe can reject after this\n\t\t// handler returns, which makes the browser see only a generic body-read error.\n\t\treturn new Response(proxyResponse.body, {\n\t\t\tstatus: proxyResponse.status,\n\t\t\theaders: proxyResponse.headers,\n\t\t});\n\t});\n\nexport type ChatRoutes = typeof chatRoutes;\n","import type {\n\tConnectionInfoSchemaType,\n\tCurrentDatabaseSchemaType,\n\tDatabaseListSchemaType,\n} from \"@db-studio/shared/types\";\nimport { Hono } from \"hono\";\nimport { getAdapter } from \"@/adapters/adapter.registry.js\";\nimport type { ApiHandler } from \"@/app.types.js\";\nimport { getDbType } from \"@/db-manager.js\";\n\n/**\n * /databases routes (at root level, no dbType required)\n * GET /databases - Get list of user-visible databases on the server (name, size, owner, encoding).\n * System databases are hidden unless currently connected (pg: postgres, rdsadmin, mysql:\n * information_schema/mysql/performance_schema/sys, mssql: database_id <= 4,\n * mongo: admin/config/local, sqlite: temp).\n * GET /databases/current - Get the name of the database we are currently connected to\n * GET /databases/connection - Get connection details and server information\n */\nexport const databasesRoutes = new Hono()\n\t/**\n\t * Base path for the endpoints, /databases/...\n\t */\n\t.basePath(\"/databases\")\n\n\t/**\n\t * GET /databases\n\t * Returns list of user-visible databases on the server (name, size, owner, encoding) and the database type\n\t */\n\t.get(\"/\", async (c): ApiHandler<DatabaseListSchemaType> => {\n\t\tconst dbType = getDbType();\n\t\tconst dao = getAdapter(dbType);\n\t\tconst databases = await dao.getDatabasesList();\n\t\treturn c.json({ data: { databases, dbType } }, 200);\n\t})\n\n\t/**\n\t * GET /databases/current\n\t * Returns the name of the database we are currently connected to and the database type\n\t */\n\t.get(\"/current\", async (c): ApiHandler<CurrentDatabaseSchemaType> => {\n\t\tconst dbType = getDbType();\n\t\tconst dao = getAdapter(dbType);\n\t\tconst current = await dao.getCurrentDatabase();\n\t\treturn c.json({ data: { db: current.db, dbType } }, 200);\n\t})\n\n\t/**\n\t * GET /databases/connection\n\t * Returns connection details and server information\n\t */\n\t.get(\"/connection\", async (c): ApiHandler<ConnectionInfoSchemaType> => {\n\t\tconst dbType = getDbType();\n\t\tconst dao = getAdapter(dbType);\n\t\tconst info = await dao.getDatabaseConnectionInfo();\n\t\treturn c.json({ data: info }, 200);\n\t});\n\nexport type DatabasesRoutes = typeof databasesRoutes.routes;\n","import {\n\tcreateKeySchema,\n\ttype DeleteKeyResultSchemaType,\n\tdatabaseSchema,\n\tdeleteKeyQuerySchema,\n\ttype KeyDetailsResultSchemaType,\n\ttype KeyRawResultSchemaType,\n\ttype KeyScanResultSchemaType,\n\ttype KeyWriteResultSchemaType,\n\tkeyActionSchema,\n\tkeyDetailsQuerySchema,\n\tkeyParamSchema,\n\tkeyRawQuerySchema,\n\tkeyScanQuerySchema,\n} from \"@db-studio/shared/types\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { assertKeyValueAdapter, getAdapter } from \"@/adapters/adapter.registry.js\";\nimport type { ApiHandler, RouteEnv } from \"@/app.types.js\";\n\nexport const keysRoutes = new Hono<RouteEnv>()\n\t.basePath(\"/keys\")\n\t.get(\n\t\t\"/\",\n\t\tzValidator(\"query\", keyScanQuerySchema),\n\t\tasync (c): ApiHandler<KeyScanResultSchemaType> => {\n\t\t\tconst query = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst adapter = assertKeyValueAdapter(getAdapter(dbType), dbType);\n\t\t\treturn c.json({ data: await adapter.scanKeys(query) }, 200);\n\t\t},\n\t)\n\t.post(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", createKeySchema),\n\t\tasync (c): ApiHandler<KeyWriteResultSchemaType> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst adapter = assertKeyValueAdapter(getAdapter(dbType), dbType);\n\t\t\treturn c.json({ data: await adapter.createKey({ db, ...body }) }, 200);\n\t\t},\n\t)\n\t.get(\n\t\t\"/:key/raw\",\n\t\tzValidator(\"param\", keyParamSchema),\n\t\tzValidator(\"query\", keyRawQuerySchema),\n\t\tasync (c): ApiHandler<KeyRawResultSchemaType> => {\n\t\t\tconst { key } = c.req.valid(\"param\");\n\t\t\tconst query = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst adapter = assertKeyValueAdapter(getAdapter(dbType), dbType);\n\t\t\treturn c.json({ data: await adapter.getStringChunk({ ...query, key }) }, 200);\n\t\t},\n\t)\n\t.get(\n\t\t\"/:key\",\n\t\tzValidator(\"param\", keyParamSchema),\n\t\tzValidator(\"query\", keyDetailsQuerySchema),\n\t\tasync (c): ApiHandler<KeyDetailsResultSchemaType> => {\n\t\t\tconst { key } = c.req.valid(\"param\");\n\t\t\tconst query = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst adapter = assertKeyValueAdapter(getAdapter(dbType), dbType);\n\t\t\treturn c.json({ data: await adapter.getKeyDetails({ ...query, key }) }, 200);\n\t\t},\n\t)\n\t.post(\n\t\t\"/:key/actions\",\n\t\tzValidator(\"param\", keyParamSchema),\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", keyActionSchema),\n\t\tasync (c): ApiHandler<KeyWriteResultSchemaType> => {\n\t\t\tconst { key } = c.req.valid(\"param\");\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst adapter = assertKeyValueAdapter(getAdapter(dbType), dbType);\n\t\t\treturn c.json({ data: await adapter.applyKeyAction({ db, key, ...body }) }, 200);\n\t\t},\n\t)\n\t.delete(\n\t\t\"/:key\",\n\t\tzValidator(\"param\", keyParamSchema),\n\t\tzValidator(\"query\", deleteKeyQuerySchema),\n\t\tasync (c): ApiHandler<DeleteKeyResultSchemaType> => {\n\t\t\tconst { key } = c.req.valid(\"param\");\n\t\t\tconst query = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst adapter = assertKeyValueAdapter(getAdapter(dbType), dbType);\n\t\t\treturn c.json({ data: await adapter.deleteKey({ ...query, key }) }, 200);\n\t\t},\n\t);\n\nexport type KeysRoutes = typeof keysRoutes.routes;\n","import {\n\tdatabaseSchema,\n\ttype ExecuteQueryResult,\n\texecuteQuerySchema,\n} from \"@db-studio/shared/types\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { getAdapter } from \"@/adapters/adapter.registry.js\";\nimport type { ApiHandler, RouteEnv } from \"@/app.types.js\";\n\nexport const queryRoutes = new Hono<RouteEnv>()\n\t/**\n\t * Base path for the endpoints, /:dbType/query/...\n\t */\n\t.basePath(\"/query\")\n\n\t/**\n\t * POST /query\n\t * Executes a SQL query on the currently connected database\n\t */\n\t.post(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", executeQuerySchema),\n\t\tasync (c): ApiHandler<ExecuteQueryResult> => {\n\t\t\tconst { query } = c.req.valid(\"json\");\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst data = await dao.executeQuery({ query, db });\n\t\t\treturn c.json({ data }, 200);\n\t\t},\n\t);\n\nexport type QueryRoutes = typeof queryRoutes;\n","import {\n\taddRecordSchema,\n\tbulkInsertRecordsSchema,\n\ttype DeleteRecordResult,\n\tdatabaseSchema,\n\tdeleteRecordSchema,\n\tupdateRecordsSchema,\n} from \"@db-studio/shared/types\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { getAdapter } from \"@/adapters/adapter.registry.js\";\nimport type { ApiHandler, RouteEnv } from \"@/app.types.js\";\n\nexport const recordsRoutes = new Hono<RouteEnv>()\n\t/**\n\t * Base path for the endpoints, /:dbType/records/...\n\t */\n\t.basePath(\"/records\")\n\n\t/**\n\t * POST /records\n\t * Adds a new record into a table\n\t */\n\t.post(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", addRecordSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName, data } = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst { insertedCount } = await dao.addRecord({ db, params: { tableName, data } });\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Record inserted into \"${tableName}\" with ${insertedCount} rows inserted`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * PATCH /records\n\t * Updates one or more cells in a table\n\t */\n\t.patch(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", updateRecordsSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName, primaryKey, updates } = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst { updatedCount } = await dao.updateRecords({\n\t\t\t\tparams: { tableName, primaryKey, updates },\n\t\t\t\tdb,\n\t\t\t});\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Updated ${updatedCount} records in \"${tableName}\"`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * DELETE /records\n\t * Deletes records from a table\n\t */\n\t.delete(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", deleteRecordSchema),\n\t\tasync (c): ApiHandler<DeleteRecordResult, 409 | 200> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName, primaryKeys } = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst { deletedCount, fkViolation, relatedRecords } = await dao.deleteRecords({\n\t\t\t\ttableName,\n\t\t\t\tprimaryKeys,\n\t\t\t\tdb,\n\t\t\t});\n\t\t\tif (fkViolation) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tdeletedCount: 0,\n\t\t\t\t\t\t\tfkViolation: true,\n\t\t\t\t\t\t\trelatedRecords,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t409,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdeletedCount,\n\t\t\t\t\t\tfkViolation: false,\n\t\t\t\t\t\trelatedRecords: [],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * DELETE /records/force\n\t * Force deletes records and all related FK records\n\t */\n\t.delete(\n\t\t\"/force\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", deleteRecordSchema),\n\t\tasync (c): ApiHandler<{ deletedCount: number }> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName, primaryKeys } = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst deletedCount = await dao.forceDeleteRecords({ tableName, primaryKeys, db });\n\t\t\treturn c.json({ data: deletedCount }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * POST /records/bulk\n\t * Bulk inserts multiple records into a table\n\t */\n\t.post(\n\t\t\"/bulk\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", bulkInsertRecordsSchema),\n\t\tasync (c): ApiHandler<object> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName, records } = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst result = await dao.bulkInsertRecords({ tableName, records, db });\n\t\t\tconsole.log(\"result\", result);\n\t\t\treturn c.json({ data: result }, 200);\n\t\t},\n\t);\n\nexport type RecordsRoutes = typeof recordsRoutes;\n","import type { CellValue, FormatType } from \"@db-studio/shared/types\";\nimport { utils, write } from \"xlsx\";\n\ninterface ExportFileOptions {\n\tcols: string[];\n\trows: Record<string, unknown>[];\n\tformat: FormatType;\n\ttableName: string;\n}\n\n/**\n * Flatten a value into the scalar `CellValue` contract that the sheet writer\n * accepts. Arrays and nested objects (Mongo documents, Postgres `jsonb`, MySQL\n * `json`) are JSON-serialized so they no longer land in the sheet as\n * \"[object Object]\", and binary columns render as `0x`-prefixed hex rather than\n * a serialized Buffer. Scalars pass through untouched.\n *\n * Only CSV and XLSX need this — the JSON export keeps the nested structure.\n */\nconst toCellValue = (value: unknown): CellValue => {\n\tif (value === null || value === undefined) return value;\n\tif (value instanceof Date) return value;\n\t// BLOB/bytea/varbinary arrive as Buffers from better-sqlite3, mssql and mysql2.\n\t// JSON.stringify would turn them into {\"type\":\"Buffer\",\"data\":[...]}.\n\tif (Buffer.isBuffer(value)) return `0x${value.toString(\"hex\")}`;\n\tif (typeof value === \"object\") return JSON.stringify(value);\n\tif (typeof value === \"bigint\") return value.toString();\n\treturn value as CellValue;\n};\n\nconst toSheetData = (cols: string[], rows: Record<string, unknown>[]): CellValue[][] => [\n\tcols,\n\t...(rows?.map((row) => cols?.map((col) => toCellValue(row[col]))) ?? []),\n];\n\n/**\n * Converts table data to the specified export format (CSV, XLSX, or JSON)\n *\n * @param options - The export options\n * @param options.cols - Array of column names\n * @param options.rows - Array of row data objects\n * @param options.format - The export format ('csv', 'xlsx', or 'json')\n * @param options.tableName - The name of the table being exported\n * @returns The file content as a Uint8Array\n */\nexport function getExportFile({ cols, rows, format, tableName }: ExportFileOptions): BodyInit {\n\tswitch (format) {\n\t\tcase \"json\": {\n\t\t\tconst jsonContent = JSON.stringify(rows ?? [], null, 2);\n\t\t\treturn new Uint8Array(Buffer.from(jsonContent, \"utf-8\"));\n\t\t}\n\n\t\tcase \"csv\": {\n\t\t\tconst worksheet = utils.aoa_to_sheet(toSheetData(cols, rows));\n\t\t\tconst csvContent = utils.sheet_to_csv(worksheet);\n\t\t\treturn new Uint8Array(Buffer.from(csvContent, \"utf-8\"));\n\t\t}\n\n\t\tcase \"xlsx\": {\n\t\t\tconst worksheet = utils.aoa_to_sheet(toSheetData(cols, rows));\n\t\t\tconst workbook = utils.book_new();\n\t\t\tutils.book_append_sheet(workbook, worksheet, tableName.slice(0, 31));\n\t\t\tconst buffer = write(workbook, {\n\t\t\t\tbookType: \"xlsx\",\n\t\t\t\ttype: \"buffer\",\n\t\t\t}) as Buffer;\n\t\t\treturn new Uint8Array(buffer);\n\t\t}\n\t}\n}\n","import {\n\taddColumnSchema,\n\talterColumnSchema,\n\ttype ColumnInfoSchemaType,\n\tcreateTableSchema,\n\ttype DeleteTableResult,\n\tdatabaseSchema,\n\tdeleteColumnParamSchema,\n\tdeleteColumnQuerySchema,\n\tdeleteTableQuerySchema,\n\texportTableSchema,\n\trenameColumnSchema,\n\trenameTableSchema,\n\ttype TableDataResultSchemaType,\n\ttype TableInfoSchemaType,\n\ttype TableSchemaResult,\n\ttableDataQuerySchema,\n\ttableNameSchema,\n} from \"@db-studio/shared/types\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { getAdapter } from \"@/adapters/adapter.registry.js\";\nimport type { ApiHandler, RouteEnv } from \"@/app.types.js\";\nimport { getExportFile } from \"@/utils/get-export-file.js\";\n\nexport const tablesRoutes = new Hono<RouteEnv>()\n\t/**\n\t * Base path for the endpoints, /:dbType/tables/...\n\t */\n\t.basePath(\"/tables\")\n\n\t/**\n\t * GET /tables\n\t * Returns list of all tables in the currently connected database\n\t */\n\t.get(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tasync (c): ApiHandler<TableInfoSchemaType[]> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst tablesList = await dao.getTablesList(db);\n\t\t\treturn c.json({ data: tablesList }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * POST /tables\n\t * Creates a new table in the currently connected database\n\t */\n\t.post(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", createTableSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tawait dao.createTable({ tableData: body, db });\n\t\t\treturn c.json({ data: `Table ${body.tableName} created successfully` }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * DELETE /tables/:tableName\n\t * Deletes a table from the database\n\t */\n\t.delete(\n\t\t\"/:tableName\",\n\t\tzValidator(\"query\", deleteTableQuerySchema),\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tasync (c): ApiHandler<DeleteTableResult> => {\n\t\t\tconst { db, cascade } = c.req.valid(\"query\");\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst result = await dao.deleteTable({ tableName, db, cascade });\n\t\t\treturn c.json({ data: result }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * PATCH /tables/:tableName/rename\n\t * Renames a table\n\t */\n\t.patch(\n\t\t\"/:tableName/rename\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tzValidator(\"json\", renameTableSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tawait dao.renameTable({ tableName, db, ...body });\n\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Table \"${tableName}\" renamed to \"${body.newTableName}\"`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * DELETE /tables/:tableName/columns/:columnName\n\t * Deletes a column from a table\n\t */\n\t.delete(\n\t\t\"/:tableName/columns/:columnName\",\n\t\tzValidator(\"query\", deleteColumnQuerySchema),\n\t\tzValidator(\"param\", deleteColumnParamSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db, cascade } = c.req.valid(\"query\");\n\t\t\tconst { tableName, columnName } = c.req.valid(\"param\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst { deletedCount } = await dao.deleteColumn({ tableName, columnName, cascade, db });\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Column \"${columnName}\" deleted successfully from table \"${tableName}\" with ${deletedCount} rows deleted`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * POST /tables/:tableName/columns\n\t * Adds a column to a table\n\t */\n\t.post(\n\t\t\"/:tableName/columns\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tzValidator(\"json\", addColumnSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tawait dao.addColumn({ tableName, db, ...body });\n\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Column \"${body.columnName}\" added successfully to table \"${tableName}\"`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * PATCH /tables/:tableName/columns/:columnName/rename\n\t * Renames a column in a table\n\t */\n\t.patch(\n\t\t\"/:tableName/columns/:columnName/rename\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"param\", deleteColumnParamSchema),\n\t\tzValidator(\"json\", renameColumnSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName, columnName } = c.req.valid(\"param\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tawait dao.renameColumn({ tableName, columnName, db, ...body });\n\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Column \"${columnName}\" renamed to \"${body.newColumnName}\" in table \"${tableName}\"`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * PATCH /tables/:tableName/columns/:columnName\n\t * Alters a column in a table\n\t */\n\t.patch(\n\t\t\"/:tableName/columns/:columnName\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"param\", deleteColumnParamSchema),\n\t\tzValidator(\"json\", alterColumnSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName, columnName } = c.req.valid(\"param\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tawait dao.alterColumn({ tableName, columnName, db, ...body });\n\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Column \"${columnName}\" updated successfully in table \"${tableName}\"`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * GET /tables/:tableName/columns\n\t * Returns list of all columns in a table\n\t */\n\t.get(\n\t\t\"/:tableName/columns\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tasync (c): ApiHandler<ColumnInfoSchemaType[]> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst columns = await dao.getTableColumns({ tableName, db });\n\t\t\treturn c.json({ data: columns }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * GET /tables/:tableName/schema\n\t * Returns the CREATE TABLE schema for a table\n\t */\n\t.get(\n\t\t\"/:tableName/schema\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tasync (c): ApiHandler<TableSchemaResult> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst schema = await dao.getTableSchema({ tableName, db });\n\t\t\treturn c.json({ data: { schema } }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * GET /tables/:tableName/data\n\t * Get cursor-paginated data for a table\n\t */\n\t.get(\n\t\t\"/:tableName/data\",\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tzValidator(\"query\", tableDataQuerySchema),\n\t\tasync (c): ApiHandler<TableDataResultSchemaType> => {\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst { cursor, limit, direction, sort, order, filters, db } = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst tableData = await dao.getTableData({\n\t\t\t\ttableName,\n\t\t\t\tcursor,\n\t\t\t\tlimit,\n\t\t\t\tdirection,\n\t\t\t\tsort,\n\t\t\t\torder,\n\t\t\t\tfilters,\n\t\t\t\tdb,\n\t\t\t});\n\t\t\treturn c.json({ data: tableData }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * GET /tables/:tableName/export\n\t * Export table data to CSV or XLSX format\n\t */\n\t.get(\n\t\t\"/:tableName/export\",\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tzValidator(\"query\", exportTableSchema),\n\t\tasync (c) => {\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst { db, format } = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\n\t\t\tconst { cols, rows } = await dao.exportTableData({ tableName, db });\n\t\t\tconst fileContent = getExportFile({ cols, rows, format, tableName });\n\t\t\tlet contentType: string | undefined;\n\n\t\t\tswitch (format) {\n\t\t\t\tcase \"csv\":\n\t\t\t\t\tcontentType = \"text/csv\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"xlsx\":\n\t\t\t\t\tcontentType = \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"json\":\n\t\t\t\t\tcontentType = \"application/json\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn new Response(fileContent, {\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": contentType ?? \"\",\n\t\t\t\t\t\"Content-Disposition\": `attachment; filename=\"${tableName}_export.${format}\"`,\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t);\n\nexport type TablesRoutes = typeof tablesRoutes.routes;\n","import { Hono } from \"hono\";\nimport { z } from \"zod\";\nimport type { ApiHandler } from \"@/app.types.js\";\nimport {\n\tcaptureInstallationActive,\n\tgetTelemetryConfig,\n\tresetTelemetryId,\n\tsetTelemetryEnabled,\n} from \"@/observability.js\";\n\nconst preferenceSchema = z.object({ enabled: z.boolean() }).strict();\n\nexport const telemetryRoutes = new Hono()\n\t.basePath(\"/telemetry\")\n\t.get(\"/config\", async (c): ApiHandler<ReturnType<typeof getTelemetryConfig>> => {\n\t\tif (c.req.header(\"x-db-studio-gpc\") === \"1\" || c.req.header(\"sec-gpc\") === \"1\") {\n\t\t\tsetTelemetryEnabled(false);\n\t\t}\n\t\tcaptureInstallationActive();\n\t\treturn c.json({ data: getTelemetryConfig() }, 200);\n\t})\n\t.put(\n\t\t\"/preference\",\n\t\tasync (c): ApiHandler<ReturnType<typeof getTelemetryConfig>, 200 | 400> => {\n\t\t\tconst parsed = preferenceSchema.safeParse(await c.req.json().catch(() => undefined));\n\t\t\tif (!parsed.success) return c.json({ error: \"Invalid telemetry preference\" }, 400);\n\t\t\tsetTelemetryEnabled(parsed.data.enabled);\n\t\t\treturn c.json({ data: getTelemetryConfig() }, 200);\n\t\t},\n\t)\n\t.post(\n\t\t\"/reset\",\n\t\tasync (c): ApiHandler<{ installationId: string }> =>\n\t\t\tc.json({ data: { installationId: resetTelemetryId() } }, 200),\n\t);\n\nexport type TelemetryRoutes = typeof telemetryRoutes.routes;\n","import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { DEFAULTS } from \"@db-studio/shared/constants\";\nimport type { DatabaseTypeSchema } from \"@db-studio/shared/types\";\nimport { serveStatic } from \"@hono/node-server/serve-static\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { logger } from \"hono/logger\";\nimport { prettyJSON } from \"hono/pretty-json\";\nimport { z } from \"zod\";\nimport { adapterRegistry } from \"@/adapters/adapter.registry.js\";\nimport { registerAdapters } from \"@/adapters/register.js\";\nimport type { AppType } from \"@/app.types.js\";\nimport { handleError } from \"@/middlewares/error-handler.js\";\nimport {\n\tcaptureServerEvent,\n\tdurationBucket,\n\toperationForRequest,\n\toutcomeForStatus,\n\tstartServerSpan,\n} from \"@/observability.js\";\nimport { chatRoutes } from \"@/routes/chat.routes.js\";\nimport { databasesRoutes } from \"@/routes/databases.routes.js\";\nimport { keysRoutes } from \"@/routes/keys.routes.js\";\nimport { queryRoutes } from \"@/routes/query.routes.js\";\nimport { recordsRoutes } from \"@/routes/records.routes.js\";\nimport { tablesRoutes } from \"@/routes/tables.routes.js\";\nimport { telemetryRoutes } from \"@/routes/telemetry.routes.js\";\n\nconst { API_PREFIX } = DEFAULTS;\n\n/**\n * Get the path to the web app distribution directory.\n */\nconst getWebDistPath = () => {\n\tif (process.env.NODE_ENV === \"development\") {\n\t\treturn path.resolve(process.cwd(), \"../web/dist\");\n\t}\n\n\tconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\tconst bundledWebDistPath = path.resolve(__dirname, \"./web-dist\");\n\tconst localWebDistPath = path.resolve(process.cwd(), \"../web/dist\");\n\n\tconst bundledIndexPath = path.resolve(bundledWebDistPath, \"index.html\");\n\tconst localIndexPath = path.resolve(localWebDistPath, \"index.html\");\n\n\tif (!existsSync(bundledIndexPath) && existsSync(localIndexPath)) {\n\t\treturn localWebDistPath;\n\t}\n\n\treturn bundledWebDistPath;\n};\n\nconst databaseTypeParamSchema = z.object({\n\tdbType: z\n\t\t.string()\n\t\t.refine(\n\t\t\t(type): type is DatabaseTypeSchema =>\n\t\t\t\tadapterRegistry.getSupportedTypes().includes(type as DatabaseTypeSchema),\n\t\t\t{\n\t\t\t\tmessage: `Invalid database type. Supported types: ${adapterRegistry\n\t\t\t\t\t.getSupportedTypes()\n\t\t\t\t\t.join(\", \")}`,\n\t\t\t},\n\t\t),\n});\n\nexport const createServer = () => {\n\tregisterAdapters();\n\n\tconst app = new Hono<AppType>({ strict: false })\n\t\t/**\n\t\t * Enable CORS.\n\t\t *\n\t\t * Same-origin by default: the SPA is served from the same origin as the\n\t\t * API, so no cross-origin access is needed. An empty allowlist means no\n\t\t * allow-origin header is emitted for cross-origin requests, which\n\t\t * prevents drive-by-localhost attacks (any other browser tab issuing\n\t\t * cross-origin reads/edits/drops against the user's DB).\n\t\t *\n\t\t * Deployments that genuinely need cross-origin access (e.g. a hosted\n\t\t * fork serving the SPA from a different origin) set `ALLOWED_ORIGINS` to\n\t\t * a comma-separated list of explicit origins. Never `*`.\n\t\t */\n\t\t.use(\n\t\t\t\"/*\",\n\t\t\tcors({\n\t\t\t\torigin: (origin) => {\n\t\t\t\t\tif (!origin) return undefined;\n\t\t\t\t\tconst allowed =\n\t\t\t\t\t\tprocess.env.ALLOWED_ORIGINS?.split(\",\")\n\t\t\t\t\t\t\t.map((o) => o.trim())\n\t\t\t\t\t\t\t.filter(Boolean) ?? [];\n\t\t\t\t\tif (allowed.includes(origin)) return origin;\n\t\t\t\t\tif (process.env.NODE_ENV === \"development\") {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst url = new URL(origin);\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\turl.hostname === \"localhost\" ||\n\t\t\t\t\t\t\t\turl.hostname.endsWith(\".localhost\") ||\n\t\t\t\t\t\t\t\turl.hostname === \"127.0.0.1\"\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn origin;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {}\n\t\t\t\t\t}\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t\tallowMethods: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"],\n\t\t\t\tallowHeaders: [\n\t\t\t\t\t\"Content-Type\",\n\t\t\t\t\t\"X-Run-Id\",\n\t\t\t\t\t\"X-DB-Studio-GPC\",\n\t\t\t\t\t\"x-byok-gemini\",\n\t\t\t\t\t\"x-byok-openai\",\n\t\t\t\t\t\"x-byok-anthropic\",\n\t\t\t\t\t\"x-byok-grok\",\n\t\t\t\t\t\"x-byok-openrouter\",\n\t\t\t\t],\n\t\t\t\tmaxAge: 600,\n\t\t\t}),\n\t\t)\n\n\t\t/**\n\t\t * Pretty print the JSON response\n\t\t */\n\t\t.use(prettyJSON({ space: 2 }))\n\n\t\t/**\n\t\t * Enable logger in development mode\n\t\t */\n\t\t.use(process.env.NODE_ENV === \"development\" ? logger() : (_, next) => next())\n\n\t\t.use(`${API_PREFIX}/*`, async (c, next) => {\n\t\t\tif (c.req.path.startsWith(`${API_PREFIX}/telemetry`)) return next();\n\t\t\tconst startedAt = performance.now();\n\t\t\tconst operation = operationForRequest(c.req.method, c.req.path);\n\t\t\tconst rawType = c.req.path.split(\"/\")[2];\n\t\t\tconst dbType = adapterRegistry\n\t\t\t\t.getSupportedTypes()\n\t\t\t\t.find((candidate) => candidate === rawType);\n\t\t\tawait startServerSpan(operation, dbType, next);\n\t\t\tcaptureServerEvent({\n\t\t\t\tevent: \"server_operation\",\n\t\t\t\tproperties: {\n\t\t\t\t\toperation,\n\t\t\t\t\tmethod: c.req.method,\n\t\t\t\t\toutcome: outcomeForStatus(c.res.status),\n\t\t\t\t\tduration_bucket: durationBucket(performance.now() - startedAt),\n\t\t\t\t\tdb_type: dbType,\n\t\t\t\t},\n\t\t\t});\n\t\t})\n\n\t\t/**\n\t\t * Serve the favicon.ico file\n\t\t */\n\t\t.use(\n\t\t\t\"/favicon.ico\",\n\t\t\tserveStatic({\n\t\t\t\tpath: path.resolve(getWebDistPath(), \"favicon.ico\"),\n\t\t\t}),\n\t\t)\n\n\t\t/**\n\t\t * Handle errors\n\t\t */\n\t\t.onError(handleError)\n\n\t\t/**\n\t\t * API routes are namespaced under API_PREFIX so they never collide with\n\t\t * client-side (SPA) routes served from the same origin. A refresh on a\n\t\t * client route like `/table/:name` must fall through to index.html, not\n\t\t * be interpreted as a `/:dbType/...` API request. See db-studio#214.\n\t\t *\n\t\t * Database routes - available at the API root (no dbType required)\n\t\t */\n\t\t.route(API_PREFIX, databasesRoutes)\n\t\t.route(API_PREFIX, chatRoutes)\n\t\t.route(API_PREFIX, telemetryRoutes)\n\n\t\t/**\n\t\t * Serve static assets (SPA-owned; live at the root, not under the API prefix)\n\t\t */\n\t\t.use(\"/assets/*\", serveStatic({ root: getWebDistPath() }))\n\t\t.use(\"/image.png\", serveStatic({ root: getWebDistPath() }))\n\n\t\t/**\n\t\t * Routes that require dbType validation - under API_PREFIX/:dbType/...\n\t\t */\n\t\t.use(\n\t\t\t`${API_PREFIX}/:dbType/*`,\n\t\t\tzValidator(\"param\", databaseTypeParamSchema, (result, c) => {\n\t\t\t\tif (!result.success) {\n\t\t\t\t\tconst rawType = c.req.param(\"dbType\");\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: `Invalid database type: \"${rawType}\". Supported types: ${adapterRegistry.getSupportedTypes().join(\", \")}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}),\n\t\t\tasync (c, next) => {\n\t\t\t\tconst { dbType } = databaseTypeParamSchema.parse({ dbType: c.req.param(\"dbType\") });\n\t\t\t\tc.set(\"dbType\", dbType);\n\t\t\t\tawait next();\n\t\t\t},\n\t\t)\n\t\t.route(`${API_PREFIX}/:dbType`, tablesRoutes)\n\t\t.route(`${API_PREFIX}/:dbType`, recordsRoutes)\n\t\t.route(`${API_PREFIX}/:dbType`, queryRoutes)\n\t\t.route(`${API_PREFIX}/:dbType`, keysRoutes);\n\n\tif (process.env.NODE_ENV !== \"test\") {\n\t\t/**\n\t\t * Any unmatched API path is a genuine 404 - respond with JSON so API\n\t\t * clients never receive the SPA's index.html HTML by mistake.\n\t\t */\n\t\tapp.all(`${API_PREFIX}/*`, (c) => c.json({ error: \"Not found\" }, 404));\n\n\t\t/**\n\t\t * SPA fallback - every non-API path serves the client app so that\n\t\t * deep-link refreshes (e.g. /table/:name) load index.html.\n\t\t */\n\t\tapp.use(\"/*\", serveStatic({ root: getWebDistPath() }));\n\t\tapp.get(\"/*\", serveStatic({ path: path.resolve(getWebDistPath(), \"index.html\") }));\n\t}\n\n\treturn { app };\n};\n\nexport type { AppType };\n\n// Export the app type for hc client\nexport type AppRoutes = ReturnType<typeof createServer>[\"app\"];\n","\n import \"_sentry-debug-id-injection-stub\";\n import * as OriginalModule from \"./src/index.ts\";\n export default OriginalModule.default;\n export * from \"./src/index.ts\";","!function(){try{var e=\"undefined\"!=typeof window?window:\"undefined\"!=typeof global?global:\"undefined\"!=typeof globalThis?globalThis:\"undefined\"!=typeof self?self:{};var n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]=\"78850f5e-49f2-47b3-b50b-976e47d75b0e\",e._sentryDebugIdIdentifier=\"sentry-dbid-78850f5e-49f2-47b3-b50b-976e47d75b0e\");}catch(e){}}();","import { intro, log, outro, spinner } from \"@clack/prompts\";\nimport { DEFAULTS } from \"@db-studio/shared/constants\";\nimport { serve } from \"@hono/node-server\";\nimport color from \"picocolors\";\nimport { args } from \"@/cmd/args.js\";\nimport { getDatabaseUrl } from \"@/cmd/get-db-url.js\";\nimport { loadEnv } from \"@/cmd/load-env.js\";\nimport { openBrowser, shouldOpenBrowser } from \"@/cmd/open-browser.js\";\nimport { sanitizeErrorMessage } from \"@/cmd/sanitize-error.js\";\nimport { showHelp } from \"@/cmd/show-help.js\";\nimport { showStatus } from \"@/cmd/show-status.js\";\nimport { showVersion } from \"@/cmd/show-version.js\";\n\nexport const main = async () => {\n\tconst { env, port, databaseUrl, varName, open, status, help, version } = args();\n\n\t// Handle help flag\n\tif (help) {\n\t\tshowHelp();\n\t\tprocess.exit(0);\n\t}\n\n\t// Handle version flag\n\tif (version) {\n\t\tshowVersion();\n\t\tprocess.exit(0);\n\t}\n\n\t// Handle status flag\n\tif (status) {\n\t\tawait showStatus(env, databaseUrl, varName);\n\t\tprocess.exit(0);\n\t}\n\n\tintro(color.inverse(\" db-studio \"));\n\n\tconst ENV = env ? await loadEnv(env) : await loadEnv();\n\n\t// Populate other env variables from .env if not already set in process.env\n\tif (ENV) {\n\t\tfor (const [key, value] of Object.entries(ENV)) {\n\t\t\tif (process.env[key] === undefined) {\n\t\t\t\tprocess.env[key] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst PORT = Number.parseInt(port ?? process.env.PORT ?? String(DEFAULTS.PORT), 10);\n\tconst HOST = process.env.HOST;\n\tconst VAR_NAME = varName || DEFAULTS.VAR_NAME;\n\tconst hasEnvFileValue = Boolean(ENV?.[VAR_NAME]);\n\tconst hasProcessValue = Boolean(process.env[VAR_NAME]);\n\tconst DATABASE_URL = databaseUrl ? databaseUrl : await getDatabaseUrl(ENV, VAR_NAME);\n\tconst configSource = databaseUrl\n\t\t? \"Using database URL from --database-url\"\n\t\t: hasEnvFileValue\n\t\t\t? `Found ${VAR_NAME} in ${env ?? \".env\"}`\n\t\t\t: hasProcessValue\n\t\t\t\t? `Found ${VAR_NAME} in environment`\n\t\t\t\t: \"Using database URL provided interactively\";\n\tlog.success(configSource);\n\n\t// Set DATABASE_URL in process.env before importing createServer\n\t// This ensures the db pool is initialized with the correct connection string\n\tprocess.env.DATABASE_URL = DATABASE_URL;\n\n\tconst { initServerObservability } = await import(\"@/observability.js\");\n\tinitServerObservability();\n\n\t// Import database modules dynamically after setting DATABASE_URL.\n\tconst { checkDatabaseConnection, getDatabaseConnectionDetails } = await import(\n\t\t\"@/cmd/check-database.js\"\n\t);\n\tconst { type, name, destination } = getDatabaseConnectionDetails(DATABASE_URL);\n\tconst connectionSpinner = spinner();\n\tconnectionSpinner.start(`Connecting to ${name}...`);\n\ttry {\n\t\tawait checkDatabaseConnection(type);\n\t\tconnectionSpinner.stop(`Connected to ${name} at ${destination}`);\n\t} catch (error) {\n\t\tconnectionSpinner.stop(`Could not connect to ${name} at ${destination}`);\n\t\tthrow error;\n\t}\n\n\tconst { createServer } = await import(\"./utils/create-server.js\");\n\tconst { app } = createServer();\n\tserve({\n\t\tfetch: app.fetch,\n\t\thostname: HOST,\n\t\tport: PORT,\n\t});\n\n\tconst serverUrl =\n\t\tprocess.env.DB_STUDIO_SERVER_URL ?? process.env.PORTLESS_URL ?? `http://localhost:${PORT}`;\n\n\tlog.success(`Server listening at ${color.cyan(serverUrl)}`);\n\n\tif (shouldOpenBrowser(open)) {\n\t\ttry {\n\t\t\tawait openBrowser(serverUrl);\n\t\t\tlog.success(\"Opened db-studio in your browser\");\n\t\t} catch {\n\t\t\tlog.warn(`Could not open your browser. Visit ${color.cyan(serverUrl)}`);\n\t\t}\n\t}\n\n\toutro(color.green(\"Ready\"));\n};\n\nif (process.env.NODE_ENV !== \"test\") {\n\tmain().catch((error: unknown) => {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\toutro(color.red(`Startup failed: ${sanitizeErrorMessage(message)}`));\n\t\tprocess.exit(1);\n\t});\n}\n","import type { Args } from \"@db-studio/shared/types\";\nimport { program } from \"commander\";\n\n/**\n * Get the arguments from the command line\n */\nexport const args = () => {\n\tprogram\n\t\t.name(\"db-studio\")\n\t\t.option(\"-e, --env <path>\", \"Path to custom .env file\")\n\t\t.option(\"-p, --port <port>\", \"Port to run the server on\")\n\t\t.option(\"-d, --database-url <url>\", \"Database URL to use\")\n\t\t.option(\n\t\t\t\"-n, --var-name <name>\",\n\t\t\t\"Custom environment variable name (default: DATABASE_URL)\",\n\t\t)\n\t\t.option(\"--open\", \"Open db-studio in the default browser\")\n\t\t.option(\"--no-open\", \"Do not open db-studio in the default browser\")\n\t\t.option(\"-s, --status\", \"Show status of the server\")\n\t\t.option(\"-h, --help\", \"Show help\")\n\t\t.option(\"-v, --version\", \"Show version\")\n\t\t.parse(process.argv);\n\n\tconst options = program.opts<Args>();\n\tconst hasOpen = process.argv.includes(\"--open\");\n\tconst hasNoOpen = process.argv.includes(\"--no-open\");\n\tif (hasOpen && hasNoOpen) {\n\t\tprogram.error(\"Do not combine --open and --no-open\");\n\t}\n\tconst open = hasOpen ? true : hasNoOpen ? false : undefined;\n\n\treturn { ...options, open };\n};\n","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport { cancel, isCancel, note, select, spinner, text } from \"@clack/prompts\";\nimport { type DotenvParseOutput, parse as parseDotenv } from \"dotenv\";\nimport color from \"picocolors\";\n\n/**\n * Get the database URL from .env file, then process.env\n */\nexport const getDatabaseUrl = async (env?: DotenvParseOutput | null, varName?: string) => {\n\tconst envVarName = varName || \"DATABASE_URL\";\n\n\tif (env?.[envVarName]) {\n\t\treturn env[envVarName];\n\t}\n\n\t// Fall back to process.env (e.g. from shell or package.json script)\n\tif (process.env[envVarName]) {\n\t\treturn process.env[envVarName];\n\t}\n\n\tconst s = spinner();\n\ts.start(\"Looking for database connection...\");\n\n\tif (!env) {\n\t\tnote(color.red(`No .env file found and ${envVarName} not set in process.env`));\n\t} else {\n\t\tnote(color.red(`${envVarName} not found in .env or process.env`));\n\t}\n\n\tconst choice = await select({\n\t\tmessage: `How do you want to provide ${envVarName}?`,\n\t\toptions: [\n\t\t\t{ value: \"manual\", label: \"Enter connection string manually\" },\n\t\t\t{ value: \"other-env\", label: \"Use different .env file\" },\n\t\t\t// todo: add multiple db connections support\n\t\t\t{ value: \"cancel\", label: \"Cancel / Exit\" },\n\t\t],\n\t\tinitialValue: \"manual\",\n\t});\n\tif (isCancel(choice) || choice === \"cancel\") {\n\t\tcancel(\"No database connection provided. Exiting...\");\n\t\tprocess.exit(0);\n\t}\n\n\tif (choice === \"other-env\") {\n\t\ts.start(\"Waiting for path...\");\n\t\tconst customPath = await text({\n\t\t\tmessage: \"Enter path to .env file\",\n\t\t\tplaceholder: \"~/projects/myapp/.env.local or ./special.env\",\n\t\t\tvalidate(value?: string) {\n\t\t\t\tif (!value?.trim()) return \"Path is required\";\n\t\t\t},\n\t\t});\n\n\t\tif (isCancel(customPath)) {\n\t\t\tcancel(\"Cancelled.\");\n\t\t\tprocess.exit(0);\n\t\t}\n\n\t\ts.stop(\"Trying custom .env...\");\n\n\t\tconst customEnvPath = resolve(customPath);\n\t\ttry {\n\t\t\tconst content = await readFile(customEnvPath, \"utf-8\");\n\t\t\tconst parsed = parseDotenv(content);\n\t\t\tif (parsed[envVarName]) {\n\t\t\t\treturn parsed[envVarName];\n\t\t\t}\n\t\t\tthrow new Error(`${envVarName} still missing in custom file`);\n\t\t} catch (e: unknown) {\n\t\t\tconst error = e as Error;\n\t\t\tcancel(`Cannot read or parse file: ${color.dim(error.message)}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\t// 3. Manual input\n\ts.stop(\"Manual input...\");\n\n\tconst dbUrl = await text({\n\t\tmessage: `Paste your ${envVarName}`,\n\t\tplaceholder:\n\t\t\t\"postgresql://user:password@localhost:5432/mydb or sqlite:///path/to/db.sqlite\",\n\t\tvalidate(value?: string) {\n\t\t\tif (!value?.trim()) return \"Connection string is required!\";\n\t\t\t// SQLite URLs are valid but may not parse with the standard URL constructor\n\t\t\tif (value.trim().startsWith(\"sqlite://\")) return undefined;\n\t\t\ttry {\n\t\t\t\tnew URL(value);\n\t\t\t\treturn undefined;\n\t\t\t} catch {\n\t\t\t\treturn \"Must be a valid URL format\";\n\t\t\t}\n\t\t},\n\t});\n\n\tif (isCancel(dbUrl)) {\n\t\tcancel(\"Cancelled.\");\n\t\tprocess.exit(0);\n\t}\n\n\treturn dbUrl.trim();\n};\n","import { access, readFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\n\nimport { parse as parseDotenv } from \"dotenv\";\n\n/**\n * Find .env path: try cwd, then walk up parent directories until root.\n */\nconst findEnvPath = async (startDir: string): Promise<string | null> => {\n\tlet dir = resolve(startDir);\n\tfor (;;) {\n\t\tconst envPath = resolve(dir, \".env\");\n\t\ttry {\n\t\t\tawait access(envPath);\n\t\t\treturn envPath;\n\t\t} catch {\n\t\t\t// ENOENT or other: try parent\n\t\t}\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) return null;\n\t\tdir = parent;\n\t}\n};\n\n/**\n * Load the environment variables from the file.\n * When no path is given: tries current directory, then parent directories until a .env is found.\n * When --env path is given: uses that path only (no walk).\n */\nexport const loadEnv = async (env?: string) => {\n\tlet envPath: string | null;\n\n\tif (env) {\n\t\tenvPath = resolve(env);\n\t} else {\n\t\tenvPath = await findEnvPath(process.cwd());\n\t}\n\n\tif (!envPath) return null;\n\n\ttry {\n\t\tconst content = await readFile(envPath, \"utf-8\");\n\t\treturn parseDotenv(content);\n\t} catch (err) {\n\t\tif (err instanceof Error && err.message.includes(\"ENOENT\")) {\n\t\t\treturn null;\n\t\t}\n\t\tthrow err;\n\t}\n};\n","import open from \"open\";\n\nexport const shouldOpenBrowser = (override?: boolean): boolean => {\n\treturn override === true;\n};\n\nexport const openBrowser = async (url: string): Promise<void> => {\n\tawait open(url);\n};\n","const CONNECTION_URL =\n\t/\\b(?:postgres(?:ql)?|mysql2?|mssql|sqlserver|mongodb(?:\\+srv)?|sqlite|rediss?):\\/\\/\\S+/gi;\n\n/**\n * Redact database connection URLs from error text before printing them.\n * The whole URL is replaced — including hosts and credentials that contain\n * `,` or `)`, such as mongodb replica set URIs — while trailing punctuation\n * that belongs to the surrounding prose is kept.\n */\nexport const sanitizeErrorMessage = (message: string): string => {\n\treturn message.replace(\n\t\tCONNECTION_URL,\n\t\t(url) => `the configured database${url.match(/[),.]+$/)?.[0] ?? \"\"}`,\n\t);\n};\n","import { intro, outro } from \"@clack/prompts\";\nimport { META } from \"@db-studio/shared/constants/meta.js\";\nimport color from \"picocolors\";\n\n/**\n * Display help information\n */\nexport const showHelp = () => {\n\tintro(color.inverse(\" db-studio \"));\n\n\tconsole.log(color.bold(\"\\nUsage:\"));\n\tconsole.log(\" db-studio [options]\\n\");\n\n\tconsole.log(color.bold(\"Supported Databases:\"));\n\tconsole.log(\" PostgreSQL, MySQL, SQL Server, MongoDB, SQLite, Redis\\n\");\n\n\tconsole.log(color.bold(\"Options:\"));\n\tconsole.log(\" -e, --env <path> Path to custom .env file\");\n\tconsole.log(\" -p, --port <port> Port to run the server on (default: 3333)\");\n\tconsole.log(\" -d, --database-url <url> Database URL to use\");\n\tconsole.log(\n\t\t\" --open Open db-studio in the default browser (off by default)\",\n\t);\n\tconsole.log(\" --no-open Do not open db-studio in the default browser\");\n\tconsole.log(\n\t\t\" -n, --var-name <name> Custom environment variable name (default: DATABASE_URL)\",\n\t);\n\tconsole.log(\" -s, --status Show status of the database connection\");\n\tconsole.log(\" -h, --help Show this help message\");\n\tconsole.log(\" -v, --version Show version number\\n\");\n\n\tconsole.log(color.bold(\"Examples:\"));\n\tconsole.log(\" db-studio\");\n\tconsole.log(\" db-studio -e .env.local\");\n\tconsole.log(\" db-studio -p 4000\");\n\tconsole.log(\" db-studio -d postgresql://user:pass@localhost:5432/mydb\");\n\tconsole.log(\" db-studio -n MY_DATABASE_URL\");\n\tconsole.log(\" db-studio -e .env.production -n PROD_DB_URL\");\n\tconsole.log(\" db-studio --status\\n\");\n\n\toutro(color.green(`For more information, visit: ${META.SITE_DOCS_LINK}`));\n};\n","import { intro, note, outro } from \"@clack/prompts\";\nimport { DEFAULTS } from \"@db-studio/shared/constants\";\nimport color from \"picocolors\";\nimport { loadEnv } from \"@/cmd/load-env.js\";\n\n/**\n * Show connection status\n */\nexport const showStatus = async (env?: string, databaseUrl?: string, varName?: string) => {\n\tintro(color.inverse(\" db-studio \"));\n\n\tconst envVarName = varName || DEFAULTS.VAR_NAME;\n\tlet foundUrl: string | null = null;\n\n\t// Check if DATABASE_URL is provided via CLI\n\tif (databaseUrl) {\n\t\tfoundUrl = databaseUrl;\n\t} else {\n\t\t// Try .env file, then process.env\n\t\tconst ENV = env ? await loadEnv(env) : await loadEnv();\n\t\tif (ENV?.[envVarName]) {\n\t\t\tfoundUrl = ENV[envVarName];\n\t\t} else if (process.env[envVarName]) {\n\t\t\tfoundUrl = process.env[envVarName] ?? null;\n\t\t}\n\t}\n\n\tif (foundUrl) {\n\t\toutro(color.green(`✓ Database connection configured (using ${envVarName})`));\n\t} else {\n\t\tnote(color.red(`✗ ${envVarName} not found`), \"Status\");\n\t\tconsole.log(color.yellow(\"\\n To configure database connection:\"));\n\t\tconsole.log(\n\t\t\tcolor.dim(\n\t\t\t\t\" • Supported databases: PostgreSQL, MySQL, SQL Server, MongoDB, SQLite, Redis\",\n\t\t\t),\n\t\t);\n\t\tconsole.log(color.dim(` • Add ${envVarName} to your .env file or set it in process.env`));\n\t\tconsole.log(color.dim(\" • Use -d flag: db-studio -d <url>\"));\n\t\tconsole.log(color.dim(\" • Use -e flag: db-studio -e <path-to-env>\"));\n\t\tconsole.log(color.dim(\" • Use -n flag: db-studio -n <var-name>\\n\"));\n\n\t\toutro(color.yellow(\"⚠ No database connection configured\"));\n\t}\n};\n","import { intro, outro } from \"@clack/prompts\";\nimport color from \"picocolors\";\nimport packageJson from \"../../package.json\" with { type: \"json\" };\n\n/**\n * Display version information\n */\nexport const showVersion = () => {\n\tintro(color.inverse(\" db-studio \"));\n\toutro(color.green(`🚀 db-studio v${packageJson.version}`));\n};\n"],"mappings":"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","names":["init_sentry_injection_stub","__esmMin","e","init_chat","__esmMin","init_sentry_injection_stub","init_column_types_mysql","__esmMin","init_sentry_injection_stub","init_column_types_pgsql","__esmMin","init_sentry_injection_stub","env","nodeEnv","DEFAULTS","init_defaults","__esmMin","init_sentry_injection_stub","init_links","__esmMin","init_sentry_injection_stub","META","init_meta","__esmMin","init_sentry_injection_stub","init_proxy_limits","__esmMin","init_sentry_injection_stub","init_constants","__esmMin","init_sentry_injection_stub","init_chat","init_column_types_mysql","init_column_types_pgsql","init_defaults","init_links","init_meta","init_proxy_limits","package_default","init_package","__esmMin","observability_exports","__export","captureInstallationActive","captureServerError","captureServerEvent","databaseTypeForRequest","durationBucket","getTelemetryConfig","initServerObservability","isTelemetryEnabled","operationForRequest","outcomeForStatus","resetTelemetryId","setTelemetryEnabled","startServerSpan","writeOperationalLog","randomUUID","existsSync","mkdirSync","readFileSync","writeFileSync","homedir","platform","path","Sentry","HTTPException","PostHog","isTestOrDevelopment","telemetryStatePath","writeState","createState","readState","state","posthog","OFFICIAL_SENTRY_DSN","OFFICIAL_POSTHOG_KEY","currentState","safeErrorType","safeErrorCode","sanitizedError","init_observability","__esmMin","init_sentry_injection_stub","init_package","base","value","file","package_default","enabled","durationMs","status","method","pathname","pathWithoutType","resource","pattern","sentryDsn","event","span","key","posthogKey","current","lastActive","error","name","code","errno","errorType","sanitized","frames","line","operation","dbType","diagnosticError","errorCode","callback","level","fields","safeFields","Database","Redis","MongoClient","ObjectId","mssql","createMysqlPool","Pool","DatabaseManager","databaseManager","getDbPool","getMysqlPool","getMssqlPool","getDbType","getSqliteDb","getMongoClient","getMongoDbName","getMongoDb","getRedisClient","getIsolatedRedisClient","getRedisDefaultDb","isValidObjectId","coerceObjectId","init_db_manager","__esmMin","init_sentry_injection_stub","url","protocol","databaseUrl","detectedType","defaultPort","error","database","filePath","db","connectionString","poolConfig","pool","client","err","dbName","config","nextClient","raw","dbIndex","index","existing","options","info","version","major","minor","path","parsed","pgClosePromises","mysqlClosePromises","mssqlClosePromises","redisClosePromises","value","check_database_exports","__export","checkDatabaseConnection","getDatabaseConnectionDetails","DATABASE_NAMES","STARTUP_TIMEOUT_MS","withStartupTimeout","init_check_database","__esmMin","init_sentry_injection_stub","init_db_manager","operation","timeout","_","reject","databaseUrl","type","getDbType","url","defaultPorts","port","getDbPool","getMysqlPool","getMssqlPool","getMongoClient","getMongoDbName","getSqliteDb","getRedisClient","HTTPException","getAdapter","dbType","adapterRegistry","assertKeyValueAdapter","adapter","isKeyValueAdapter","AdapterRegistry","init_adapter_registry","__esmMin","init_sentry_injection_stub","type","HTTPException","DatabaseError","notImplemented","method","BaseAdapter","init_base_adapter","__esmMin","init_sentry_injection_stub","err","params","keyColumns","groups","update","keyValues","column","value","groupKey","group","i","tableName","newTableName","data","cursor","row","out","k","v","db","limit","direction","bundle","countRes","total","rawRows","hasMore","rows","nextCursor","prevCursor","e","sql","_db","_params","getDbPool","getMysqlPool","getMssqlPool","getSqliteDb","getMongoClient","getMongoDbName","getMongoDb","getRedisClient","getIsolatedRedisClient","getRedisDefaultDb","init_connections","__esmMin","init_sentry_injection_stub","init_db_manager","database","dbName","dbIndex","SYSTEM_DATABASES","visibleMongoDatabases","init_mongo_database_visibility","__esmMin","init_sentry_injection_stub","databases","currentDb","visible","db","parseDatabaseUrl","databaseUrl","url","protocol","defaultPort","error","init_parse_database_url","__esmMin","init_sentry_injection_stub","buildMatchStage","filters","andConditions","filter","field","value","parseFilterValue","op","escapeRegex","buildSortStage","sort","order","s","encodeMongoCursor","offset","decodeMongoCursor","cursor","parsed","init_mongo_pipeline_builder","__esmMin","init_sentry_injection_stub","init_db_manager","raw","trimmed","asNumber","isValidObjectId","coerceObjectId","HTTPException","normalizeValue","normalizeDoc","inferValueType","dataTypeLabel","canCoerce","toMongoId","formatBytes","MONGO_BSON_TYPES","mapBsonType","inferBsonType","resolveFieldDefault","normalizeIdFilter","MongoAdapter","init_mongo_adapter","__esmMin","init_sentry_injection_stub","init_base_adapter","init_connections","init_db_manager","init_mongo_database_visibility","init_parse_database_url","init_mongo_pipeline_builder","value","item","k","v","doc","dt","isValidObjectId","coerceObjectId","bytes","units","i","rawType","n","bson","defaultValue","columnType","filter","obj","BaseAdapter","_params","rawRows","row","name","nativeType","universalType","params","tableName","db","cursor","limit","direction","sort","order","filters","collection","getMongoDb","filterObj","buildMatchStage","sortObj","buildSortStage","safeLimit","decodedOffset","decodeMongoCursor","offset","skip","total","rows","normalizedRows","nextOffset","prevOffset","encodeMongoCursor","e","normalized","databases","getMongoClient","visibleMongoDatabases","getMongoDbName","admin","urlDefaults","parseDatabaseUrl","serverStatus","error","mongoDb","collections","results","col","rowCount","tableData","fields","properties","required","field","bsonType","newTableName","docs","totalDocs","fieldTypes","fieldPresence","key","types","presence","typeList","t","isNullable","schema","documents","columnMap","ensureColumn","columnName","entry","meta","resolvedDefault","existingSchema","reqIndex","newColumnName","data","payload","totalUpdated","keyColumns","column","groups","keyValues","rowUpdates","update","updateSet","result","primaryKeys","pkColumn","pkValues","pk","records","record","query","startTime","message","duration","z","databaseSchema","DATABASE_TYPES","databaseTypeSchema","currentDatabaseSchema","databaseTypeParamSchema","tableNameSchema","init_database_types","__esmMin","init_sentry_injection_stub","z","addColumnSchema","addColumnParamSchema","addColumnParamsSchema","init_add_column_types","__esmMin","init_sentry_injection_stub","init_database_types","tableNameSchema","databaseSchema","z","addRecordSchema","init_add_record_types","__esmMin","init_sentry_injection_stub","z","AI_PROVIDERS","aiProviderSchema","AI_PROVIDER_OPTIONS","getDefaultAiModel","init_ai_provider_types","__esmMin","init_sentry_injection_stub","provider","option","z","deleteColumnQuerySchema","deleteColumnParamSchema","deleteColumnParamsSchema","deleteColumnSuccessResponseSchema","init_delete_column_types","__esmMin","init_sentry_injection_stub","init_database_types","databaseSchema","val","z","alterColumnSchema","alterColumnParamSchema","alterColumnParamsSchema","init_alter_column_types","__esmMin","init_sentry_injection_stub","init_database_types","init_delete_column_types","deleteColumnParamSchema","databaseSchema","init_api_response_types","__esmMin","init_sentry_injection_stub","z","bulkInsertRecordsSchema","init_bulk_insert_records_type","__esmMin","init_sentry_injection_stub","z","messagePart","chatBodySchema","chatSchema","init_chat_types","__esmMin","init_sentry_injection_stub","init_ai_provider_types","init_database_types","aiProviderSchema","databaseSchema","body","getDefaultAiModel","init_cmd_args_types","__esmMin","init_sentry_injection_stub","z","dataTypes","dataTypesSchema","DataTypes","standardizedDataTypes","standardizedDataTypeSchema","columnInfoSchema","init_column_info_types","__esmMin","init_sentry_injection_stub","mapPostgresToDataType","pgType","normalized","DataTypes","standardizeDataTypeLabel","StandardizedDataType","mapMysqlToDataType","mysqlDataType","columnType","fullType","standardizeMysqlDataTypeLabel","mapMssqlToDataType","mssqlDataType","standardizeMssqlDataTypeLabel","mapSqliteToDataType","sqliteType","standardizeSqliteDataTypeLabel","init_column_type","__esmMin","init_sentry_injection_stub","init_column_info_types","z","FOREIGN_KEY_ACTIONS","foreignKeyActionSchema","fieldDataSchema","foreignKeyDataSchema","createTableSchema","init_create_table_types","__esmMin","init_sentry_injection_stub","hasDatabaseCapability","dbType","capability","DATABASE_CAPABILITIES","init_database_capabilities_types","__esmMin","init_sentry_injection_stub","z","databaseInfoSchema","databaseListSchema","connectionInfoSchema","init_database_list_types","__esmMin","init_sentry_injection_stub","init_database_types","databaseTypeSchema","init_database_schema_type","__esmMin","init_sentry_injection_stub","z","deleteRecordSchema","init_delete_record_types","__esmMin","init_sentry_injection_stub","z","deleteTableQuerySchema","init_delete_table_types","__esmMin","init_sentry_injection_stub","init_database_types","databaseSchema","val","z","executeQuerySchema","init_execute_query_types","__esmMin","init_sentry_injection_stub","z","FORMAT_TYPES","exportTableSchema","init_export_table_types","__esmMin","init_sentry_injection_stub","init_database_types","databaseSchema","z","redisKeyTypeSchema","encodedRedisValueSchema","keyScanQuerySchema","redisKeySummarySchema","keyScanResultSchema","keyDetailsQuerySchema","keyParamSchema","redisStringValueSchema","redisHashValueSchema","redisListValueSchema","redisSetValueSchema","redisSortedSetValueSchema","redisStreamValueSchema","redisUnknownValueSchema","redisKeyValueSchema","keyDetailsResultSchema","keyRawQuerySchema","keyRawResultSchema","createStringValueSchema","createHashValueSchema","createListValueSchema","createSetValueSchema","createSortedSetValueSchema","createStreamValueSchema","createKeySchema","keyWriteResultSchema","renameKeyActionSchema","setTtlKeyActionSchema","setStringKeyActionSchema","upsertHashKeyActionSchema","deleteHashKeyActionSchema","pushListKeyActionSchema","setListKeyActionSchema","deleteListKeyActionSchema","addSetKeyActionSchema","removeSetKeyActionSchema","upsertSortedSetKeyActionSchema","removeSortedSetKeyActionSchema","appendStreamKeyActionSchema","deleteStreamKeyActionSchema","keyActionSchema","deleteKeyQuerySchema","deleteKeyResultSchema","init_key_browser_types","__esmMin","init_sentry_injection_stub","value","init_rate_limit_response_type","__esmMin","init_sentry_injection_stub","z","renameColumnSchema","renameColumnParamSchema","renameColumnParamsSchema","init_rename_column_types","__esmMin","init_sentry_injection_stub","init_database_types","init_delete_column_types","deleteColumnParamSchema","databaseSchema","z","renameTableSchema","renameTableParamSchema","renameTableParamsSchema","init_rename_table_types","__esmMin","init_sentry_injection_stub","init_database_types","tableNameSchema","databaseSchema","z","filterSchema","sortDirections","sortSchema","tableDataMetaSchema","tableDataResultSchema","tableDataQuerySchema","init_table_data_types","__esmMin","init_sentry_injection_stub","init_database_types","databaseSchema","val","parsed","z","tableInfoSchema","init_table_info_type","__esmMin","init_sentry_injection_stub","z","tableSchemaResultSchema","init_table_schema_types","__esmMin","init_sentry_injection_stub","z","updateRecordsSchema","init_update_recors_types","__esmMin","init_sentry_injection_stub","types_exports","__export","AI_PROVIDERS","AI_PROVIDER_OPTIONS","DATABASE_CAPABILITIES","DATABASE_TYPES","DataTypes","FOREIGN_KEY_ACTIONS","FORMAT_TYPES","StandardizedDataType","addColumnParamSchema","addColumnParamsSchema","addColumnSchema","addRecordSchema","aiProviderSchema","alterColumnParamSchema","alterColumnParamsSchema","alterColumnSchema","bulkInsertRecordsSchema","chatSchema","columnInfoSchema","connectionInfoSchema","createKeySchema","createTableSchema","currentDatabaseSchema","dataTypesSchema","databaseInfoSchema","databaseListSchema","databaseSchema","databaseTypeParamSchema","databaseTypeSchema","deleteColumnParamSchema","deleteColumnParamsSchema","deleteColumnQuerySchema","deleteColumnSuccessResponseSchema","deleteKeyQuerySchema","deleteKeyResultSchema","deleteRecordSchema","deleteTableQuerySchema","encodedRedisValueSchema","executeQuerySchema","exportTableSchema","fieldDataSchema","filterSchema","foreignKeyActionSchema","foreignKeyDataSchema","getDefaultAiModel","hasDatabaseCapability","keyActionSchema","keyDetailsQuerySchema","keyDetailsResultSchema","keyParamSchema","keyRawQuerySchema","keyRawResultSchema","keyScanQuerySchema","keyScanResultSchema","keyWriteResultSchema","mapMssqlToDataType","mapMysqlToDataType","mapPostgresToDataType","mapSqliteToDataType","redisKeySummarySchema","redisKeyTypeSchema","redisKeyValueSchema","renameColumnParamSchema","renameColumnParamsSchema","renameColumnSchema","renameTableParamSchema","renameTableParamsSchema","renameTableSchema","sortDirections","sortSchema","standardizeDataTypeLabel","standardizeMssqlDataTypeLabel","standardizeMysqlDataTypeLabel","standardizeSqliteDataTypeLabel","standardizedDataTypeSchema","tableDataMetaSchema","tableDataQuerySchema","tableDataResultSchema","tableInfoSchema","tableNameSchema","tableSchemaResultSchema","updateRecordsSchema","init_types","__esmMin","init_sentry_injection_stub","init_add_column_types","init_add_record_types","init_ai_provider_types","init_alter_column_types","init_api_response_types","init_bulk_insert_records_type","init_chat_types","init_cmd_args_types","init_column_type","init_column_info_types","init_create_table_types","init_database_types","init_database_capabilities_types","init_database_list_types","init_database_schema_type","init_delete_column_types","init_delete_record_types","init_delete_table_types","init_execute_query_types","init_export_table_types","init_key_browser_types","init_rate_limit_response_type","init_rename_column_types","init_rename_table_types","init_table_data_types","init_table_info_type","init_table_schema_types","init_update_recors_types","buildWhereClause","filters","startIdx","conditions","values","idx","filter","col","buildSortClause","sorts","order","s","mapColumnTypeToMssql","columnType","isArray","normalized","formatMssqlDefaultValue","defaultValue","trimmed","buildMssqlColumnDefinition","field","options","mappedType","def","dv","init_mssql_query_builder","__esmMin","init_sentry_injection_stub","HTTPException","MSSQL_FK_VIOLATION","MSSQL_FK_DEPENDENCY","MsSqlAdapter","init_mssql_adapter","__esmMin","init_sentry_injection_stub","init_types","init_base_adapter","init_connections","init_parse_database_url","init_mssql_query_builder","BaseAdapter","db","sql","values","request","getMssqlPool","val","idx","name","nativeType","mapMssqlToDataType","universalType","params","tableName","filters","sort","order","limit","cursor","filterWhere","filterValues","nextIdx","buildWhereClause","sortClause","buildSortClause","currentOffset","countSql","rawRows","row","_rows","hasMore","pool","countRequest","countResult","total","dataRequest","rows","e","result","info","urlDefaults","parseDatabaseUrl","table","tableData","fields","foreignKeys","columnDefs","field","mappedType","mapColumnTypeToMssql","colDef","dv","formatMssqlDefaultValue","constraintDefs","primaryKeyFields","f","fkDefs","fk","cascade","tableCheck","rowCount","relatedRecords","fkConstraints","error","newTableName","targetCheck","schemaResult","columns","col","checkResult","checkEnumMap","r","enumValues","standardizeMssqlDataTypeLabel","columnName","columnType","defaultValue","isPrimaryKey","isNullable","isUnique","isIdentity","colCheck","buildMssqlColumnDefinition","constraintName","nullability","newColumnName","newColCheck","data","booleanColumns","identityResult","identityColumns","value","columnNames","paramNames","_col","keyColumns","groups","transaction","keyValues","rowUpdates","setClauses","u","whereClauses","column","primaryKeys","pkColumn","pkValues","pk","paramList","_","totalRelated","deletedTables","visited","deleteRelatedRecursively","targetTable","targetColumn","visitedSet","key","nestedFks","nestedFk","selectRequest","selectParamList","nestedValues","deleteRequest","deleteParamList","deleteResult","constraint","mainRequest","mainParamList","records","i","record","query","cleanedQuery","start","duration","fks","results","relatedResult","constraintsByTable","constraints","cols","c","checkClause","matches","m","offset","buildWhereClause","filters","conditions","values","filter","col","buildSortClause","sorts","order","s","buildCursorWhereClause","cursorData","direction","sortDirection","sortColumns","operator","columnList","placeholders","queryValues","mapColumnTypeToMysql","columnType","isArray","normalized","formatMysqlDefaultValue","defaultValue","trimmed","buildMysqlColumnDefinition","field","options","mappedType","def","dv","init_mysql_query_builder","__esmMin","init_sentry_injection_stub","HTTPException","MYSQL_FK_VIOLATION","MYSQL_FK_DEPENDENCY","MySqlAdapter","init_mysql_adapter","__esmMin","init_sentry_injection_stub","init_types","init_base_adapter","init_connections","init_parse_database_url","init_mysql_query_builder","BaseAdapter","db","sql","values","pool","getMysqlPool","rows","name","nativeType","mapMysqlToDataType","universalType","params","tableName","cursor","limit","direction","sort","order","filters","sortColumns","effectiveSortDirection","s","filterWhere","filterValues","buildWhereClause","cursorWhere","cursorValues","cursorData","res","buildCursorWhereClause","combinedWhere","sortClause","buildSortClause","effectiveSortClause","col","countSql","rawRows","row","hasMore","createCursor","firstRow","lastRow","nextCursor","prevCursor","pkColumns","cursorColumns","pk","countRows","total","dataRows","makeCursor","infoRows","connRows","info","urlDefaults","parseDatabaseUrl","tables","table","tableData","fields","foreignKeys","columnDefs","field","buildMysqlColumnDefinition","constraintDefs","primaryKeyFields","f","fkDefs","fk","cascade","tableRows","rowCount","relatedRecords","connection","error","mysqlError","newTableName","targetRows","e","createTableSql","r","isEnum","standardizeMysqlDataTypeLabel","columnName","columnType","defaultValue","isPrimaryKey","isNullable","isUnique","isIdentity","isArray","colRows","colDef","result","colRow","newColumnName","newColRows","data","booleanColumns","columns","value","i","c","keyColumns","groups","keyValues","rowUpdates","setClauses","u","whereClauses","column","primaryKeys","pkColumn","pkValues","placeholders","fkConstraints","totalRelated","deletedTables","visited","deleteRelatedRecursively","targetTable","targetColumn","visitedSet","key","nestedFks","nestedFk","nestedPh","selectRows","nestedValues","ph","deleteResult","constraint","mainPh","records","colNames","record","query","cleaned","start","duration","dmlResult","fks","results","relatedRows","constraintsByTable","constraints","cols","match","v","buildWhereClause","filters","conditions","values","filter","paramIndex","columnName","buildSortClause","sorts","order","s","buildCursorWhereClause","cursorData","direction","sortDirection","startParamIndex","sortColumns","queryValues","useGreaterThan","columnList","col","placeholders","_","i","operator","resolvedSchemaFor","init_pg_query_builder","__esmMin","init_sentry_injection_stub","tableParam","HTTPException","PgAdapter","init_pg_adapter","__esmMin","init_sentry_injection_stub","init_types","init_base_adapter","init_connections","init_parse_database_url","init_pg_query_builder","BaseAdapter","db","sql","values","getDbPool","name","nativeType","mapPostgresToDataType","universalType","params","tableName","cursor","limit","direction","sort","order","filters","pool","sortColumns","effectiveSortDirection","s","cursorColumns","filterWhere","filterValues","buildWhereClause","cursorWhere","cursorValues","cursorData","res","buildCursorWhereClause","combinedWhere","sortClause","buildSortClause","effectiveSortClause","col","limitParamIndex","countSql","rawRows","row","rows","hasMore","createCursor","data","firstRow","lastRow","nextCursor","prevCursor","pkColumns","pk","countRes","total","dataRes","connectionInfoSchema","result","urlDefaults","parseDatabaseUrl","escapeChar","tables","t","tableData","fields","foreignKeys","columnDefs","field","def","fkDefs","fk","cascade","tableRows","rowCount","error","newTableName","requestedSchema","schemaRows","schemas","r","schemaName","targetRows","e","existsRows","columns","resolvedSchemaFor","constraints","indexes","formatType","data_type","udt_name","character_maximum_length","numeric_precision","numeric_scale","lines","colDefs","constraintMap","c","arr","constraintDefs","cols","first","colNames","idx","parsedEnumValues","standardizeDataTypeLabel","columnName","columnType","defaultValue","isPrimaryKey","isNullable","isUnique","isIdentity","isArray","colRows","client","newColumnName","colExistsQuery","curRows","nextRows","placeholders","_","i","keyColumns","groups","keyValues","rowUpdates","setClauses","u","whereClauses","column","primaryKeys","pkColumn","pkValues","fkConstraints","totalRelated","deletedTables","deleteRelated","targetTable","targetColumn","nested","nfk","nestedVals","ph","records","successCount","record","query","cleaned","start","duration","f","fks","results","constraintsByTable","key","tokenizeCommand","input","out","cur","i","inSingle","inDouble","ch","shapeReply","argv","reply","singleCellFallback","cmd","subcmd","a","zrangeWithScoresShape","compound","shaper","COMMAND_SHAPES","scalarShape","isStringArray","flatArrayShape","isFlatPairArray","statusShape","pairArrayShape","infoShape","xrangeShape","init_redis_command_shaper","__esmMin","init_sentry_injection_stub","v","x","idx","rows","section","line","entry","id","fields","fieldsObj","createHash","randomBytes","HTTPException","z","parseInfoSection","info","out","line","idx","parseKeyspaceInfo","match","extractKey","data","k","extractTtl","t","parsed","stringifyValue","v","coerceObject","value","kind","coerceArray","coerceZsetEntries","arr","entry","obj","score","flatPairsToZsetEntries","reply","i","streamInfoToObject","length","firstEntry","lastEntry","idOf","REDIS_TABLES","TABLE_TO_REDIS_TYPE","SCHEMA_MUTATION_MESSAGE","SORT_UNSUPPORTED_MESSAGE","FILTER_UNSUPPORTED_MESSAGE","PREV_UNSUPPORTED_MESSAGE","SCAN_ROUND_TRIP_CAP","COUNT_CACHE_TTL_MS","COUNT_SCAN_CEILING","MAX_STRING_PREVIEW_BYTES","MAX_STRING_FULL_BYTES","isRedisTable","assertRedisTable","parseDbIndex","encodeKeyBrowserCursor","decodeKeyBrowserCursor","encodeKeyDetailsCursor","decodeKeyDetailsCursor","encodeBinaryValue","escapeRedisGlob","normalizeRedisKeyType","decodeBinaryValue","decodeKeyParam","revisionForDump","conflict","isUnavailableCommandError","assertKeyType","assertTransactionSucceeded","encodeScanCursor","decodeScanCursor","columnInfo","KEY_COL","TTL_COL","TABLE_COLUMNS","SCHEMA_DESCRIPTIONS","RedisAdapter","init_redis_adapter","__esmMin","init_sentry_injection_stub","init_base_adapter","init_connections","init_redis_command_shaper","name","tableName","db","getRedisDefaultDb","env","cursor","utf8","type","dump","error","message","actual","expected","result","failed","overrides","BaseAdapter","_params","rawRows","row","nativeType","_universalType","params","limit","search","exactPattern","dbIndex","client","getRedisClient","scanCursor","decoded","pattern","scanArgs","nextRaw","pageKeys","nextScanCursor","pipeline","key","metadata","index","offset","memory","e","encodedKey","full","direction","typeRaw","ttlMs","memoryRaw","dumpRaw","summary","decodedCursor","readLimit","scanResult","values","next","entries","nextOffset","hasMore","members","boundary","rawEntries","id","fields","lastId","chunk","getIsolatedRedisClient","transaction","field","member","newKey","marker","resultKey","nextDump","total","supportsLogicalDatabases","configReply","keyspaceInfo","keysPerDb","_","serverInfo","clientsInfo","server","clients","maxclients","opts","counts","table","sort","filters","redisType","collectedKeys","rounds","scanComplete","batch","overflow","rows","hasNextPage","nextCursor","keys","ttlPipeline","ttlResults","valuePipeline","valueResults","ttl","raw","cached","results","updates","primaryKey","primaryKeys","pkField","updatesByKey","u","keyStr","existing","updatedCount","nextKeyRaw","nextKey","pk","deletedCount","records","errors","successCount","record","allKeys","c","flat","val","args","query","startTime","argv","tokenizeCommand","cmd","rest","shapeReply","buildWhereClause","filters","conditions","values","filter","col","buildSortClause","sorts","order","s","buildCursorWhereClause","cursorData","direction","sortDirection","sortColumns","operator","columnList","placeholders","queryValues","init_sqlite_query_builder","__esmMin","init_sentry_injection_stub","statSync","HTTPException","SqliteAdapter","init_sqlite_adapter","__esmMin","init_sentry_injection_stub","init_types","init_base_adapter","init_connections","init_sqlite_query_builder","BaseAdapter","_db","sql","values","getSqliteDb","name","nativeType","mapSqliteToDataType","universalType","params","tableName","cursor","limit","direction","sort","order","filters","sortColumns","effectiveSortDirection","s","filterWhere","filterValues","buildWhereClause","cursorWhere","cursorValues","cursorData","res","buildCursorWhereClause","combinedWhere","sortClause","buildSortClause","effectiveSortClause","col","countSql","rawRows","row","rows","hasMore","createCursor","data","firstRow","lastRow","nextCursor","prevCursor","db","sqliteDb","pkColumns","c","a","b","cursorColumns","pk","useRowid","pkTieBreakerCols","tbDir","countRow","total","selectClause","dataRows","_r","rest","e","r","t","tableData","fields","foreignKeys","columnDefs","field","def","fkDefs","fk","cascade","rowCount","error","newTableName","escapeIdent","columns","fks","fkMap","standardizeSqliteDataTypeLabel","columnName","columnType","defaultValue","isNullable","isUnique","colInfo","pkCols","hasCompositePk","newColDefs","isTarget","type","nullable","defVal","isPk","fksByGroup","arr","group","from","f","to","table","on_update","on_delete","colNames","tempName","existingIndexes","existingTriggers","doAlter","newColumnName","v","placeholders","result","keyColumns","groups","doUpdate","keyValues","rowUpdates","setClauses","u","whereClauses","column","primaryKeys","pkColumn","pkValues","doDelete","doForceDelete","fkRefs","totalRelated","ph","records","stmt","doInsert","recs","count","record","successCount","query","cleaned","start","duration","info","filePath","bytes","allTables","references","results","registerAdapters","adapterRegistry","PgAdapter","MySqlAdapter","MsSqlAdapter","MongoAdapter","SqliteAdapter","RedisAdapter","init_register","__esmMin","init_sentry_injection_stub","init_adapter_registry","init_mongo_adapter","init_mssql_adapter","init_mysql_adapter","init_pg_adapter","init_redis_adapter","init_sqlite_adapter","HTTPException","DatabaseError","ZodError","handleError","e","c","operation","operationForRequest","errorType","errorTypeName","status","statusForError","writeOperationalLog","captureServerError","databaseTypeForRequest","issue","isConnectionError","init_error_handler","__esmMin","init_sentry_injection_stub","init_observability","mysqlError","generateSystemPrompt","schema","dbTypeLower","dbTypeLabel","formatSchemaForPrompt","output","table","col","pkIndicator","fkIndicator","nullable","rel","init_system_prompt_generator","__esmMin","init_sentry_injection_stub","convertColumnInfo","col","column","extractRelationships","tables","relationships","table","toTable","toColumn","stringifySampleValue","value","getSampleData","adapter","tableName","db","row","key","error","getTableColumns","getDatabaseSchema","options","dbType","getDbType","includeSampleData","maxTables","getAdapter","tablesList","tablePromises","schemaName","columns","sampleData","getDetailedSchema","init_table_details_schema","__esmMin","init_sentry_injection_stub","init_adapter_registry","init_db_manager","zValidator","Hono","HTTPException","LOOPBACK_HOSTNAMES","resolveProxyUrl","chatRoutes","init_chat_routes","__esmMin","init_sentry_injection_stub","init_constants","init_types","init_system_prompt_generator","init_table_details_schema","url","DEFAULTS","isLoopback","c","proxyUrl","proxyResponse","chatSchema","messages","data","provider","model","db","conversationId","includeSchema","schema","getDetailedSchema","systemPrompt","generateSystemPrompt","payload","errorData","Hono","databasesRoutes","init_databases_routes","__esmMin","init_sentry_injection_stub","init_adapter_registry","init_db_manager","c","dbType","getDbType","databases","getAdapter","current","info","zValidator","Hono","keysRoutes","init_keys_routes","__esmMin","init_sentry_injection_stub","init_types","init_adapter_registry","keyScanQuerySchema","c","query","dbType","adapter","assertKeyValueAdapter","getAdapter","databaseSchema","createKeySchema","db","body","keyParamSchema","keyRawQuerySchema","key","keyDetailsQuerySchema","keyActionSchema","deleteKeyQuerySchema","zValidator","Hono","queryRoutes","init_query_routes","__esmMin","init_sentry_injection_stub","init_types","init_adapter_registry","databaseSchema","executeQuerySchema","c","query","db","dbType","data","getAdapter","zValidator","Hono","recordsRoutes","init_records_routes","__esmMin","init_sentry_injection_stub","init_types","init_adapter_registry","databaseSchema","addRecordSchema","c","db","tableName","data","dbType","dao","getAdapter","insertedCount","updateRecordsSchema","primaryKey","updates","updatedCount","deleteRecordSchema","primaryKeys","deletedCount","fkViolation","relatedRecords","bulkInsertRecordsSchema","records","result","utils","write","getExportFile","cols","rows","format","tableName","jsonContent","worksheet","toSheetData","csvContent","workbook","buffer","toCellValue","init_get_export_file","__esmMin","init_sentry_injection_stub","value","row","col","zValidator","Hono","tablesRoutes","init_tables_routes","__esmMin","init_sentry_injection_stub","init_types","init_adapter_registry","init_get_export_file","databaseSchema","c","db","dbType","tablesList","getAdapter","createTableSchema","body","deleteTableQuerySchema","tableNameSchema","cascade","tableName","result","renameTableSchema","deleteColumnQuerySchema","deleteColumnParamSchema","columnName","dao","deletedCount","addColumnSchema","renameColumnSchema","alterColumnSchema","columns","schema","tableDataQuerySchema","cursor","limit","direction","sort","order","filters","tableData","exportTableSchema","format","cols","rows","fileContent","getExportFile","contentType","Hono","z","preferenceSchema","telemetryRoutes","init_telemetry_routes","__esmMin","init_sentry_injection_stub","init_observability","c","setTelemetryEnabled","captureInstallationActive","getTelemetryConfig","parsed","resetTelemetryId","create_server_exports","__export","createServer","existsSync","path","fileURLToPath","serveStatic","zValidator","Hono","cors","HTTPException","logger","prettyJSON","z","API_PREFIX","getWebDistPath","databaseTypeParamSchema","init_create_server","__esmMin","init_sentry_injection_stub","init_constants","init_adapter_registry","init_register","init_error_handler","init_observability","init_chat_routes","init_databases_routes","init_keys_routes","init_query_routes","init_records_routes","init_tables_routes","init_telemetry_routes","DEFAULTS","__dirname","bundledWebDistPath","localWebDistPath","bundledIndexPath","localIndexPath","type","adapterRegistry","registerAdapters","app","origin","o","url","_","next","c","startedAt","operation","operationForRequest","rawType","dbType","candidate","startServerSpan","captureServerEvent","outcomeForStatus","durationBucket","handleError","databasesRoutes","chatRoutes","telemetryRoutes","result","tablesRoutes","recordsRoutes","queryRoutes","keysRoutes","init_sentry_injection_stub","init_sentry_injection_stub","e","n","init_sentry_injection_stub","init_constants","intro","log","outro","spinner","serve","color","init_sentry_injection_stub","program","args","options","hasOpen","hasNoOpen","init_sentry_injection_stub","readFile","resolve","cancel","isCancel","note","select","spinner","text","parseDotenv","color","getDatabaseUrl","env","varName","envVarName","s","choice","customPath","value","customEnvPath","content","parsed","e","error","dbUrl","init_sentry_injection_stub","access","readFile","dirname","resolve","parseDotenv","findEnvPath","startDir","dir","envPath","parent","loadEnv","env","content","err","init_sentry_injection_stub","open","shouldOpenBrowser","override","openBrowser","url","init_sentry_injection_stub","CONNECTION_URL","sanitizeErrorMessage","message","url","init_sentry_injection_stub","init_meta","intro","outro","color","showHelp","META","init_sentry_injection_stub","init_constants","intro","note","outro","color","showStatus","env","databaseUrl","varName","intro","color","envVarName","DEFAULTS","foundUrl","ENV","loadEnv","outro","note","init_sentry_injection_stub","init_package","intro","outro","color","showVersion","package_default","main","env","port","databaseUrl","varName","open","status","help","version","args","showHelp","showVersion","showStatus","intro","color","ENV","loadEnv","key","value","PORT","DEFAULTS","HOST","VAR_NAME","hasEnvFileValue","hasProcessValue","DATABASE_URL","getDatabaseUrl","configSource","log","initServerObservability","checkDatabaseConnection","getDatabaseConnectionDetails","type","name","destination","connectionSpinner","spinner","error","createServer","app","serve","serverUrl","shouldOpenBrowser","openBrowser","outro","message","sanitizeErrorMessage","index_default"]}
|
|
1
|
+
{"version":3,"sources":["../_sentry-injection-stub","../../shared/src/constants/chat.ts","../../shared/src/constants/column-types-mysql.ts","../../shared/src/constants/column-types-pgsql.ts","../../shared/src/constants/defaults.ts","../../shared/src/constants/links.ts","../../shared/src/constants/meta.ts","../../shared/src/constants/proxy-limits.ts","../../shared/src/constants/index.ts","../../shared/src/types/database.types.ts","../../shared/src/types/add-column.types.ts","../../shared/src/types/add-record.types.ts","../../shared/src/types/ai-provider.types.ts","../../shared/src/types/delete-column.types.ts","../../shared/src/types/alter-column.types.ts","../../shared/src/types/api-response.types.ts","../../shared/src/types/bulk-insert-records.type.ts","../../shared/src/types/chat.types.ts","../../shared/src/types/cmd-args.types.ts","../../shared/src/types/column-info.types.ts","../../shared/src/types/column.type.ts","../../shared/src/types/create-table.types.ts","../../shared/src/types/database-engines.types.ts","../../shared/src/types/database-list.types.ts","../../shared/src/types/database-schema.type.ts","../../shared/src/types/delete-record.types.ts","../../shared/src/types/delete-table.types.ts","../../shared/src/types/execute-query.types.ts","../../shared/src/types/export-table.types.ts","../../shared/src/types/key-browser.types.ts","../../shared/src/types/rate-limit-response.type.ts","../../shared/src/types/rename-column.types.ts","../../shared/src/types/rename-table.types.ts","../../shared/src/types/table-data.types.ts","../../shared/src/types/table-info.type.ts","../../shared/src/types/table-schema.types.ts","../../shared/src/types/update-recors.types.ts","../../shared/src/types/index.ts","../src/utils/parse-database-url.ts","../package.json","../src/observability.ts","../src/db-manager.ts","../src/cmd/check-database.ts","../src/adapters/adapter.registry.ts","../src/adapters/base.adapter.ts","../src/adapters/connections.ts","../src/adapters/clickhouse/clickhouse.query-builder.ts","../src/adapters/clickhouse/clickhouse.adapter.ts","../src/adapters/duckdb/duckdb.query-builder.ts","../src/adapters/duckdb/duckdb.adapter.ts","../src/utils/mongo-database-visibility.ts","../src/adapters/mongo/mongo.pipeline-builder.ts","../src/adapters/mongo/mongo.adapter.ts","../src/adapters/mssql/mssql.query-builder.ts","../src/adapters/mssql/mssql.adapter.ts","../src/adapters/mysql/mysql.query-builder.ts","../src/adapters/mysql/mysql.adapter.ts","../src/adapters/oracle/oracle.query-builder.ts","../src/adapters/oracle/oracle.values.ts","../src/adapters/oracle/oracle.adapter.ts","../src/adapters/pg/pg.query-builder.ts","../src/adapters/pg/pg.adapter.ts","../src/adapters/redis/redis.command-shaper.ts","../src/adapters/redis/redis.adapter.ts","../src/adapters/sqlite/sqlite.query-builder.ts","../src/adapters/sqlite/sqlite.adapter.ts","../src/adapters/register.ts","../src/middlewares/error-handler.ts","../src/utils/system-prompt-generator.ts","../src/utils/table-details-schema.ts","../src/routes/chat.routes.ts","../src/routes/databases.routes.ts","../src/routes/keys.routes.ts","../src/routes/query.routes.ts","../src/routes/records.routes.ts","../src/utils/get-export-file.ts","../src/routes/tables.routes.ts","../src/routes/telemetry.routes.ts","../src/utils/create-server.ts","../src/index.ts","sentry-debug-id-stub:_sentry-debug-id-injection-stub?sentry-module-id=f6ec434a-e864-4be7-a394-33e60195d7a8","../src/index.ts","../src/cmd/args.ts","../src/cmd/get-db-url.ts","../src/cmd/load-env.ts","../src/cmd/open-browser.ts","../src/cmd/sanitize-error.ts","../src/cmd/show-help.ts","../src/cmd/show-status.ts","../src/cmd/show-version.ts"],"sourcesContent":["!function(){try{var e=\"undefined\"!=typeof window?window:\"undefined\"!=typeof global?global:\"undefined\"!=typeof globalThis?globalThis:\"undefined\"!=typeof self?self:{};e.SENTRY_RELEASE={id:\"db-studio@1.16.0\"};}catch(e){}}();","export const CHAT_SUGGESTIONS = [\n\t\"Show me all tables in my database\",\n\t\"What columns are in the users table?\",\n\t\"Write a query to find all active users\",\n\t\"How many orders were placed last month?\",\n\t\"Find top 5 customers by total spend\",\n\t\"Write a JOIN between users and orders\",\n\t\"Users who haven't made any purchase yet\",\n\t\"Generate monthly revenue summary query\",\n\t\"Suggest useful indexes for better performance\",\n\t\"Show schema of the products / inventory table\",\n\t\"Latest 20 orders with customer names\",\n\t\"Help me write a safe UPDATE query\",\n];\n\n// const MODEL_LIST = [\n// \t{\n// \t\tid: \"gpt-4o\",\n// \t\tname: \"GPT-4o\",\n// \t\tchef: \"OpenAI\",\n// \t\tchefSlug: \"openai\",\n// \t},\n// \t{\n// \t\tid: \"gpt-4o-mini\",\n// \t\tname: \"GPT-4o Mini\",\n// \t\tchef: \"OpenAI\",\n// \t\tchefSlug: \"openai\",\n// \t},\n// \t{\n// \t\tid: \"claude-opus-4-20250514\",\n// \t\tname: \"Claude 4 Opus\",\n// \t\tchef: \"Anthropic\",\n// \t\tchefSlug: \"anthropic\",\n// \t},\n// \t{\n// \t\tid: \"claude-sonnet-4-20250514\",\n// \t\tname: \"Claude 4 Sonnet\",\n// \t\tchef: \"Anthropic\",\n// \t\tchefSlug: \"anthropic\",\n// \t},\n// \t{\n// \t\tid: \"gemini-2.0-flash-exp\",\n// \t\tname: \"Gemini 2.0 Flash\",\n// \t\tchef: \"Google\",\n// \t\tchefSlug: \"google\",\n// \t},\n// ];\n","export const MYSQL_COLUMN_TYPES = [\n\t// Numeric\n\t{ value: \"tinyint\", label: \"tinyint\" },\n\t{ value: \"smallint\", label: \"smallint\" },\n\t{ value: \"mediumint\", label: \"mediumint\" },\n\t{ value: \"int\", label: \"int\" },\n\t{ value: \"bigint\", label: \"bigint\" },\n\t{ value: \"decimal\", label: \"decimal\" },\n\t{ value: \"float\", label: \"float\" },\n\t{ value: \"double\", label: \"double\" },\n\t{ value: \"bit\", label: \"bit\" },\n\t// Boolean\n\t{ value: \"boolean\", label: \"boolean\" },\n\t// Text\n\t{ value: \"char\", label: \"char\" },\n\t{ value: \"varchar\", label: \"varchar\" },\n\t{ value: \"tinytext\", label: \"tinytext\" },\n\t{ value: \"text\", label: \"text\" },\n\t{ value: \"mediumtext\", label: \"mediumtext\" },\n\t{ value: \"longtext\", label: \"longtext\" },\n\t// Binary\n\t{ value: \"binary\", label: \"binary\" },\n\t{ value: \"varbinary\", label: \"varbinary\" },\n\t{ value: \"tinyblob\", label: \"tinyblob\" },\n\t{ value: \"blob\", label: \"blob\" },\n\t{ value: \"mediumblob\", label: \"mediumblob\" },\n\t{ value: \"longblob\", label: \"longblob\" },\n\t// JSON\n\t{ value: \"json\", label: \"json\" },\n\t// Date / Time\n\t{ value: \"date\", label: \"date\" },\n\t{ value: \"time\", label: \"time\" },\n\t{ value: \"datetime\", label: \"datetime\" },\n\t{ value: \"timestamp\", label: \"timestamp\" },\n\t{ value: \"year\", label: \"year\" },\n\t// Complex\n\t{ value: \"enum\", label: \"enum\" },\n\t{ value: \"set\", label: \"set\" },\n] as const;\n\nexport type MysqlColumnType = (typeof MYSQL_COLUMN_TYPES)[number][\"value\"];\n","export const PGSQL_COLUMN_TYPES = [\n\t// Numeric\n\t{ value: \"integer\", label: \"integer\" },\n\t{ value: \"bigint\", label: \"bigint\" },\n\t{ value: \"smallint\", label: \"smallint\" },\n\t{ value: \"numeric\", label: \"numeric\" },\n\t{ value: \"real\", label: \"real\" },\n\t{ value: \"double precision\", label: \"double precision\" },\n\t{ value: \"money\", label: \"money\" },\n\t{ value: \"serial\", label: \"serial\" },\n\t{ value: \"bigserial\", label: \"bigserial\" },\n\t// Boolean\n\t{ value: \"boolean\", label: \"boolean\" },\n\t// Text\n\t{ value: \"text\", label: \"text\" },\n\t{ value: \"varchar\", label: \"varchar\" },\n\t{ value: \"char\", label: \"char\" },\n\t// JSON\n\t{ value: \"json\", label: \"json\" },\n\t{ value: \"jsonb\", label: \"jsonb\" },\n\t{ value: \"xml\", label: \"xml\" },\n\t// UUID\n\t{ value: \"uuid\", label: \"uuid\" },\n\t// Date / Time\n\t{ value: \"date\", label: \"date\" },\n\t{ value: \"time\", label: \"time\" },\n\t{ value: \"timestamp\", label: \"timestamp\" },\n\t{ value: \"timestamptz\", label: \"timestamptz\" },\n\t{ value: \"interval\", label: \"interval\" },\n\t// Binary\n\t{ value: \"bytea\", label: \"bytea\" },\n\t// Network\n\t{ value: \"inet\", label: \"inet\" },\n\t{ value: \"cidr\", label: \"cidr\" },\n\t{ value: \"macaddr\", label: \"macaddr\" },\n\t{ value: \"macaddr8\", label: \"macaddr8\" },\n\t// Geometric\n\t{ value: \"point\", label: \"point\" },\n\t{ value: \"line\", label: \"line\" },\n\t{ value: \"polygon\", label: \"polygon\" },\n] as const;\n\nexport type PgsqlColumnType = (typeof PGSQL_COLUMN_TYPES)[number][\"value\"];\n","const env = (\n\tglobalThis as typeof globalThis & {\n\t\tprocess?: {\n\t\t\tenv?: {\n\t\t\t\tNODE_ENV?: string;\n\t\t\t\tDB_STUDIO_PROXY_URL?: string;\n\t\t\t};\n\t\t};\n\t}\n).process?.env;\n\nconst nodeEnv = env?.NODE_ENV;\n\nexport const DEFAULTS = {\n\tPORT: 3333,\n\tENV: \".env\",\n\tVAR_NAME: \"DATABASE_URL\",\n\tBASE_URL: \"https://api.db-studio.localhost\",\n\t/**\n\t * URL namespace for all HTTP API routes. The API and the SPA are served\n\t * from the same origin in self-hosted mode, so the API is mounted under\n\t * this prefix to keep it from colliding with client-side (SPA) routes such\n\t * as `/table/:name` on a page refresh. See db-studio#214.\n\t */\n\tAPI_PREFIX: \"/api\",\n\tIS_DEV: nodeEnv === \"development\",\n\tPROXY_URL:\n\t\tenv?.DB_STUDIO_PROXY_URL ??\n\t\t(nodeEnv === \"development\"\n\t\t\t? \"https://proxy.db-studio.localhost\"\n\t\t\t: \"https://db-studio-proxy.husamql3.workers.dev\"),\n};\n","export const HEADER_LINKS = [\n\t{ label: \"Home\", href: \"/\" },\n\t{ label: \"Roadmap\", href: \"/roadmap\" },\n\t{ label: \"Docs\", href: \"/docs/$\" },\n\t{ label: \"Changelog\", href: \"/changelog\" },\n];\n","export const META = {\n\t//* author\n\tAUTHOR: \"Hüsam 🥑 <husam@ql3.dev>\",\n\tAUTHOR_NAME: \"Hüsam\",\n\tAUTHOR_AVATAR: \"/avocado.png\",\n\tAUTHOR_USERNAME: \"husamql3\",\n\tAUTHOR_GITHUB_LINK: \"https://github.com/husamql3\",\n\t//* site\n\tSITE_DESCRIPTION: \"The modern pgAdmin alternative that works with every database.\",\n\tSITE_KEYWORDS: [\n\t\t\"pgadmin alternative\",\n\t\t\"database client\",\n\t\t\"database gui\",\n\t\t\"database browser\",\n\t\t\"sql editor\",\n\t\t\"postgresql client\",\n\t\t\"mysql client\",\n\t\t\"table editor\",\n\t\t\"ai sql\",\n\t\t\"er diagram\",\n\t],\n\tSITE_TITLE: \"db-studio\",\n\tSITE_NAME: \"dbstudio.sh\",\n\tSITE_URL: \"https://dbstudio.sh\",\n\tSITE_X_LINK: \"https://x.com/dbstudio_sh\",\n\tSITE_GITHUB_LINK: \"https://github.com/husamql3/db-studio\",\n\tSITE_GITHUB_NEW_ISSUE_LINK: \"https://github.com/husamql3/db-studio/issues/new/choose\",\n\tSITE_DOCS_LINK: \"https://dbstudio.sh/docs\",\n\tSITE_CHANGELOG_LINK: \"https://dbstudio.sh/changelog\",\n\tSITE_ROADMAP_LINK: \"https://dbstudio.sh/roadmap\",\n\tSITE_IMAGE: \"https://dbstudio.sh/og-image.png\",\n\tSITE_IMAGE_WIDTH: \"1200\",\n\tSITE_IMAGE_HEIGHT: \"630\",\n\tSITE_IMAGE_ALT: \"dbstudio.sh – Modern database management studio\",\n\tSITE_COLOR: \"#1447e6\",\n};\n","export const ONE_DAY = 24 * 60 * 60 * 1000;\nexport const LIMIT = 3;\n/**\n * Ceiling for requests that carry a personal API key (BYOK). Those requests do\n * not spend our hosted Gemini quota, so they get a far higher allowance — but\n * not an unlimited one, otherwise an arbitrary `x-byok-*` header would be enough\n * to bypass the limiter entirely.\n */\nexport const BYOK_LIMIT = 120;\n","export * from \"./chat.js\";\nexport * from \"./column-types-mysql.js\";\nexport * from \"./column-types-pgsql.js\";\nexport * from \"./defaults.js\";\nexport * from \"./links.js\";\nexport * from \"./meta.js\";\nexport * from \"./proxy-limits.js\";\n","import { z } from \"zod\";\n\nexport const databaseSchema = z.object({\n\tdb: z.string(\"Database name is required\"),\n});\n\nexport type DatabaseSchemaType = z.infer<typeof databaseSchema>;\n\nexport const DATABASE_TYPES = [\n\t\"pg\",\n\t\"mysql\",\n\t\"mssql\",\n\t\"mongodb\",\n\t\"sqlite\",\n\t\"redis\",\n\t\"duckdb\",\n\t\"oracle\",\n\t\"clickhouse\",\n] as const;\n\nexport const databaseTypeSchema = z.enum(DATABASE_TYPES, {\n\tmessage: \"Invalid database type\",\n});\nexport type DatabaseTypeSchema = z.infer<typeof databaseTypeSchema>;\n\nexport const currentDatabaseSchema = databaseSchema.extend({\n\tdbType: databaseTypeSchema,\n});\nexport type CurrentDatabaseSchemaType = z.infer<typeof currentDatabaseSchema>;\n\nexport const databaseTypeParamSchema = z.object({\n\tdbType: databaseTypeSchema,\n});\n\nexport const tableNameSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n});\n\nexport type TableNameSchemaType = z.infer<typeof tableNameSchema>;\n","import { z } from \"zod\";\nimport { databaseSchema, tableNameSchema } from \"./database.types\";\n\nexport const addColumnSchema = z.object({\n\tcolumnName: z.string(\"Column name is required\"),\n\tcolumnType: z.string(\"Column type is required\"),\n\tdefaultValue: z.string().optional(),\n\tisPrimaryKey: z.boolean().default(false),\n\tisNullable: z.boolean().default(false),\n\tisUnique: z.boolean().default(false),\n\tisIdentity: z.boolean().default(false),\n\tisArray: z.boolean().default(false),\n});\n\nexport type AddColumnSchemaType = z.infer<typeof addColumnSchema>;\n\nexport const addColumnParamSchema = tableNameSchema;\n\nexport type AddColumnParamSchemaType = z.infer<typeof addColumnParamSchema>;\n\nexport const addColumnParamsSchema = z.object({\n\tdb: databaseSchema.shape.db,\n\ttableName: tableNameSchema.shape.tableName,\n\tcolumnName: addColumnSchema.shape.columnName,\n\tcolumnType: addColumnSchema.shape.columnType,\n\tdefaultValue: addColumnSchema.shape.defaultValue,\n\tisPrimaryKey: addColumnSchema.shape.isPrimaryKey,\n\tisNullable: addColumnSchema.shape.isNullable,\n\tisUnique: addColumnSchema.shape.isUnique,\n\tisIdentity: addColumnSchema.shape.isIdentity,\n\tisArray: addColumnSchema.shape.isArray,\n});\n\nexport type AddColumnParamsSchemaType = z.infer<typeof addColumnParamsSchema>;\n","import { z } from \"zod\";\n\nexport const addRecordSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n\tdata: z.record(z.string(\"Column name is required\"), z.any()),\n});\n\nexport type AddRecordSchemaType = z.infer<typeof addRecordSchema>;\n","import { z } from \"zod\";\n\nexport const AI_PROVIDERS = [\"gemini\", \"openai\", \"anthropic\", \"grok\", \"openrouter\"] as const;\nexport const aiProviderSchema = z.enum(AI_PROVIDERS);\nexport type AiProvider = z.infer<typeof aiProviderSchema>;\n\nexport const AI_PROVIDER_OPTIONS: ReadonlyArray<{\n\tid: AiProvider;\n\tlabel: string;\n\tmodels: ReadonlyArray<{ id: string; label: string }>;\n}> = [\n\t{\n\t\tid: \"gemini\",\n\t\tlabel: \"Google Gemini\",\n\t\tmodels: [\n\t\t\t{ id: \"gemini-3-flash-preview\", label: \"Gemini 3 Flash\" },\n\t\t\t{ id: \"gemini-2.5-pro\", label: \"Gemini 2.5 Pro\" },\n\t\t],\n\t},\n\t{\n\t\tid: \"openai\",\n\t\tlabel: \"OpenAI\",\n\t\tmodels: [\n\t\t\t{ id: \"gpt-5.2\", label: \"GPT-5.2\" },\n\t\t\t{ id: \"gpt-5-mini\", label: \"GPT-5 mini\" },\n\t\t],\n\t},\n\t{\n\t\tid: \"anthropic\",\n\t\tlabel: \"Anthropic\",\n\t\tmodels: [\n\t\t\t{ id: \"claude-sonnet-4-6\", label: \"Claude Sonnet 4.6\" },\n\t\t\t{ id: \"claude-haiku-4-5\", label: \"Claude Haiku 4.5\" },\n\t\t],\n\t},\n\t{\n\t\tid: \"grok\",\n\t\tlabel: \"xAI Grok\",\n\t\tmodels: [\n\t\t\t{ id: \"grok-4.6\", label: \"Grok 4.6\" },\n\t\t\t{ id: \"grok-4.5\", label: \"Grok 4.5\" },\n\t\t],\n\t},\n\t{\n\t\tid: \"openrouter\",\n\t\tlabel: \"OpenRouter\",\n\t\tmodels: [\n\t\t\t{ id: \"openai/gpt-5.2\", label: \"GPT-5.2 via OpenRouter\" },\n\t\t\t{ id: \"anthropic/claude-sonnet-4.6\", label: \"Claude Sonnet 4.6 via OpenRouter\" },\n\t\t],\n\t},\n];\n\nexport const getDefaultAiModel = (provider: AiProvider): string =>\n\tAI_PROVIDER_OPTIONS.find((option) => option.id === provider)?.models[0]?.id ??\n\t\"gemini-3-flash-preview\";\n","import { z } from \"zod\";\nimport { databaseSchema } from \"./database.types\";\n\nexport const deleteColumnQuerySchema = databaseSchema.extend({\n\tcascade: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform((val) => val === \"true\"),\n});\n\nexport type DeleteColumnQuerySchemaType = z.infer<typeof deleteColumnQuerySchema>;\n\nexport const deleteColumnParamSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n\tcolumnName: z.string(\"Column name is required\"),\n});\n\nexport const deleteColumnParamsSchema = z.object({\n\tdb: databaseSchema.shape.db,\n\ttableName: deleteColumnParamSchema.shape.tableName,\n\tcolumnName: deleteColumnParamSchema.shape.columnName,\n\tcascade: z.boolean().optional(),\n});\n\nexport type DeleteColumnParamsSchemaType = z.infer<typeof deleteColumnParamsSchema>;\n\nexport const deleteColumnSuccessResponseSchema = z.object({\n\tmessage: z.string(\"Message is required\"),\n\ttableName: z.string(\"Table name is required\"),\n\tcolumnName: z.string(\"Column name is required\"),\n\tdeletedCount: z.number(\"Deleted count is required\").default(0),\n});\n\nexport type DeleteColumnResponseType = z.infer<typeof deleteColumnSuccessResponseSchema>;\n","import { z } from \"zod\";\nimport { databaseSchema } from \"./database.types\";\nimport { deleteColumnParamSchema } from \"./delete-column.types\";\n\nexport const alterColumnSchema = z.object({\n\tcolumnType: z.string(\"Column type is required\"),\n\tisNullable: z.boolean(),\n\tdefaultValue: z.string().nullable().optional(),\n});\n\nexport type AlterColumnSchemaType = z.infer<typeof alterColumnSchema>;\n\nexport const alterColumnParamSchema = deleteColumnParamSchema;\n\nexport type AlterColumnParamSchemaType = z.infer<typeof alterColumnParamSchema>;\n\nexport const alterColumnParamsSchema = z.object({\n\tdb: databaseSchema.shape.db,\n\ttableName: deleteColumnParamSchema.shape.tableName,\n\tcolumnName: deleteColumnParamSchema.shape.columnName,\n\tcolumnType: alterColumnSchema.shape.columnType,\n\tisNullable: alterColumnSchema.shape.isNullable,\n\tdefaultValue: alterColumnSchema.shape.defaultValue,\n});\n\nexport type AlterColumnParamsSchemaType = z.infer<typeof alterColumnParamsSchema>;\n","/**\n * Standard API success response wrapper type\n * Used by both server and client\n */\nexport type BaseResponse<T> = {\n\tdata: T;\n\tmessage?: string;\n};\n\n/**\n * Standard API error response type\n */\nexport type ApiError = {\n\terror: string;\n\tdetails?: string;\n};\n","import { z } from \"zod\";\nimport type { DatabaseSchemaType } from \"./database.types\";\n\nexport type BulkInsertRecordsParams = {\n\ttableName: string;\n\trecords: Record<string, unknown>[];\n\tdb: DatabaseSchemaType[\"db\"];\n};\n\nexport type BulkInsertResult = {\n\tsuccess: boolean;\n\tmessage: string;\n\tsuccessCount: number;\n\tfailureCount: number;\n\terrors?: Array<{ recordIndex: number; error: string }>;\n};\n\nexport const bulkInsertRecordsSchema = z.object({\n\ttableName: z.string().min(1, \"Table name is required\"),\n\trecords: z.array(z.record(z.string(), z.any())).min(1, \"At least one record is required\"),\n});\n","import { z } from \"zod\";\nimport { aiProviderSchema, getDefaultAiModel } from \"./ai-provider.types.js\";\nimport { databaseSchema } from \"./database.types.js\";\n\n// Legacy UI message part schema. Current TanStack AI clients serialize messages\n// to the AG-UI wire format (`content` / `toolCalls`) before sending them.\nconst messagePart = z\n\t.object({\n\t\ttype: z.string(),\n\t\tcontent: z.string().optional(),\n\t})\n\t.passthrough();\n\n// `fetchServerSentEvents` wraps extra body under `data`. Accept both the current\n// AG-UI wire messages and legacy UI messages so older clients remain compatible.\nconst chatBodySchema = z.object({\n\tprovider: aiProviderSchema.optional().default(\"gemini\"),\n\t// Left optional here: a fixed default would pair, say, `provider: \"openai\"`\n\t// with a Gemini model and the proxy would reject the combination with a 400.\n\t// The default is resolved from the parsed provider in the transform below.\n\tmodel: z.string().min(1).optional(),\n\tmessages: z.array(\n\t\tz\n\t\t\t.object({\n\t\t\t\tid: z.string(),\n\t\t\t\trole: z.enum([\"user\", \"assistant\", \"system\", \"tool\", \"reasoning\"]),\n\t\t\t\tcontent: z.union([z.string(), z.null(), z.array(z.unknown())]).optional(),\n\t\t\t\tparts: z.array(messagePart).optional(),\n\t\t\t})\n\t\t\t.passthrough(),\n\t),\n\tdata: z.object({\n\t\tconversationId: z.string().optional(),\n\t\tdb: databaseSchema.shape.db,\n\t\tincludeSchema: z.boolean().optional().default(true),\n\t}),\n});\n\nexport const chatSchema = chatBodySchema.transform((body) => ({\n\t...body,\n\tmodel: body.model ?? getDefaultAiModel(body.provider),\n}));\n","export type Args = {\n\tenv?: string;\n\tport?: string;\n\tdatabaseUrl?: string;\n\tvarName?: string;\n\topen?: boolean;\n\tstatus?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n};\n","import { z } from \"zod\";\n\nconst dataTypes = [\"text\", \"boolean\", \"number\", \"enum\", \"json\", \"date\", \"array\"] as const;\n\nexport const dataTypesSchema = z.enum(dataTypes);\nexport type DataTypes = z.infer<typeof dataTypesSchema>;\n\nexport const DataTypes = {\n\ttext: \"text\",\n\tboolean: \"boolean\",\n\tnumber: \"number\",\n\tenum: \"enum\",\n\tjson: \"json\",\n\tdate: \"date\",\n\tarray: \"array\",\n} as const satisfies Record<DataTypes, string>;\n\nconst standardizedDataTypes = [\n\t// PostgreSQL numeric types\n\t\"int\",\n\t\"bigint\",\n\t\"smallint\",\n\t\"numeric\",\n\t\"float\",\n\t\"double\",\n\t\"money\",\n\t// MySQL numeric types\n\t\"tinyint\",\n\t\"mediumint\",\n\t\"bit\",\n\t// Boolean\n\t\"boolean\",\n\t// Text types (shared)\n\t\"text\",\n\t\"varchar\",\n\t\"char\",\n\t// MySQL text types\n\t\"tinytext\",\n\t\"mediumtext\",\n\t\"longtext\",\n\t// JSON types\n\t\"json\",\n\t\"jsonb\",\n\t\"xml\",\n\t// UUID\n\t\"uuid\",\n\t// Date/Time types (shared)\n\t\"date\",\n\t\"time\",\n\t\"timestamp\",\n\t// PostgreSQL date/time\n\t\"timestamptz\",\n\t\"interval\",\n\t// MySQL date/time\n\t\"datetime\",\n\t\"year\",\n\t// PostgreSQL binary/network/geometric types\n\t\"bytea\",\n\t\"inet\",\n\t\"cidr\",\n\t\"macaddr\",\n\t\"macaddr8\",\n\t\"point\",\n\t\"line\",\n\t\"polygon\",\n\t// MySQL binary types\n\t\"binary\",\n\t\"varbinary\",\n\t\"blob\",\n\t\"tinyblob\",\n\t\"mediumblob\",\n\t\"longblob\",\n\t// Complex types (shared)\n\t\"array\",\n\t\"enum\",\n\t// MySQL set type\n\t\"set\",\n] as const;\n\nexport const standardizedDataTypeSchema = z.enum(standardizedDataTypes);\n\nexport const columnInfoSchema = z.object({\n\tcolumnName: z.string(),\n\tdataType: dataTypesSchema,\n\tdataTypeLabel: standardizedDataTypeSchema,\n\tisNullable: z.boolean(),\n\tcolumnDefault: z.string().nullable(),\n\tisPrimaryKey: z.boolean(),\n\tisForeignKey: z.boolean(),\n\treferencedTable: z.string().nullable(),\n\treferencedColumn: z.string().nullable(),\n\tenumValues: z.array(z.string()).nullable(),\n});\n\nexport type ColumnInfoSchemaType = z.infer<typeof columnInfoSchema>;\n","import { DataTypes } from \"./column-info.types.js\";\n\n/**\n * Maps PostgreSQL data types to generic DataType enum\n */\nexport function mapPostgresToDataType(pgType: string): DataTypes {\n\tconst normalized = pgType?.toLowerCase().trim() || \"\";\n\n\t// Handle array types and date/time types\n\tif (\n\t\tnormalized.includes(\"[]\") ||\n\t\tnormalized === \"date\" ||\n\t\tnormalized === \"time\" ||\n\t\tnormalized === \"time without time zone\" ||\n\t\tnormalized.startsWith(\"time(\") ||\n\t\tnormalized === \"timestamp\" ||\n\t\tnormalized === \"timestamp without time zone\" ||\n\t\tnormalized.startsWith(\"timestamp(\") ||\n\t\tnormalized === \"timestamp with time zone\" ||\n\t\tnormalized === \"timestamptz\" ||\n\t\tnormalized.startsWith(\"timestamp with time zone(\")\n\t) {\n\t\treturn DataTypes.date;\n\t}\n\n\t// Numeric types\n\tif (\n\t\tnormalized === \"integer\" ||\n\t\tnormalized === \"int\" ||\n\t\tnormalized === \"int4\" ||\n\t\tnormalized === \"bigint\" ||\n\t\tnormalized === \"int8\" ||\n\t\tnormalized === \"smallint\" ||\n\t\tnormalized === \"int2\" ||\n\t\tnormalized === \"decimal\" ||\n\t\tnormalized.startsWith(\"decimal(\") ||\n\t\tnormalized === \"numeric\" ||\n\t\tnormalized.startsWith(\"numeric(\") ||\n\t\tnormalized === \"real\" ||\n\t\tnormalized === \"float4\" ||\n\t\tnormalized === \"double precision\" ||\n\t\tnormalized === \"float8\" ||\n\t\tnormalized === \"float\" ||\n\t\tnormalized === \"serial\" ||\n\t\tnormalized === \"serial4\" ||\n\t\tnormalized === \"bigserial\" ||\n\t\tnormalized === \"serial8\" ||\n\t\tnormalized === \"money\"\n\t) {\n\t\treturn DataTypes.number;\n\t}\n\n\t// Boolean\n\tif (normalized === \"boolean\" || normalized === \"bool\") {\n\t\treturn DataTypes.boolean;\n\t}\n\n\t// JSON types\n\tif (normalized === \"json\" || normalized === \"jsonb\") {\n\t\treturn DataTypes.json;\n\t}\n\n\t// Enum types and long text types\n\tif (\n\t\tnormalized.startsWith(\"user-defined\") ||\n\t\tnormalized === \"enum\" ||\n\t\tnormalized === \"text\" ||\n\t\tnormalized === \"xml\"\n\t) {\n\t\treturn DataTypes.text;\n\t}\n\n\t// Short string types (varchar, char, uuid, etc.)\n\tif (\n\t\tnormalized === \"character varying\" ||\n\t\tnormalized.startsWith(\"varchar\") ||\n\t\tnormalized.startsWith(\"character varying(\") ||\n\t\tnormalized === \"character\" ||\n\t\tnormalized.startsWith(\"char\") ||\n\t\tnormalized.startsWith(\"character(\") ||\n\t\tnormalized === \"bpchar\" ||\n\t\tnormalized === \"uuid\" ||\n\t\tnormalized === \"interval\" ||\n\t\tnormalized.startsWith(\"interval\") ||\n\t\tnormalized === \"bytea\" ||\n\t\tnormalized === \"point\" ||\n\t\tnormalized === \"line\" ||\n\t\tnormalized === \"polygon\" ||\n\t\tnormalized === \"inet\" ||\n\t\tnormalized === \"cidr\" ||\n\t\tnormalized === \"macaddr\" ||\n\t\tnormalized === \"macaddr8\"\n\t) {\n\t\treturn DataTypes.text;\n\t}\n\n\t// Default to short for unrecognized types\n\treturn DataTypes.text;\n}\n\n/**\n * Standardized data type labels\n */\nexport const StandardizedDataType = {\n\t// PostgreSQL numeric types\n\tint: \"int\",\n\tbigint: \"bigint\",\n\tsmallint: \"smallint\",\n\tnumeric: \"numeric\",\n\tfloat: \"float\",\n\tdouble: \"double\",\n\tmoney: \"money\",\n\t// MySQL numeric types\n\ttinyint: \"tinyint\",\n\tmediumint: \"mediumint\",\n\tbit: \"bit\",\n\t// Boolean\n\tboolean: \"boolean\",\n\t// Text types (shared)\n\ttext: \"text\",\n\tvarchar: \"varchar\",\n\tchar: \"char\",\n\t// MySQL text types\n\ttinytext: \"tinytext\",\n\tmediumtext: \"mediumtext\",\n\tlongtext: \"longtext\",\n\t// JSON types\n\tjson: \"json\",\n\tjsonb: \"jsonb\",\n\txml: \"xml\",\n\t// UUID\n\tuuid: \"uuid\",\n\t// Date/Time types (shared)\n\tdate: \"date\",\n\ttime: \"time\",\n\ttimestamp: \"timestamp\",\n\t// PostgreSQL date/time\n\ttimestamptz: \"timestamptz\",\n\tinterval: \"interval\",\n\t// MySQL date/time\n\tdatetime: \"datetime\",\n\tyear: \"year\",\n\t// PostgreSQL binary/network/geometric types\n\tbytea: \"bytea\",\n\tinet: \"inet\",\n\tcidr: \"cidr\",\n\tmacaddr: \"macaddr\",\n\tmacaddr8: \"macaddr8\",\n\tpoint: \"point\",\n\tline: \"line\",\n\tpolygon: \"polygon\",\n\t// MySQL binary types\n\tbinary: \"binary\",\n\tvarbinary: \"varbinary\",\n\tblob: \"blob\",\n\ttinyblob: \"tinyblob\",\n\tmediumblob: \"mediumblob\",\n\tlongblob: \"longblob\",\n\t// Complex types (shared)\n\tarray: \"array\",\n\tenum: \"enum\",\n\t// MySQL set type\n\tset: \"set\",\n} as const;\n\nexport type StandardizedDataType =\n\t(typeof StandardizedDataType)[keyof typeof StandardizedDataType];\n\n/**\n * Maps PostgreSQL data types to standardized display labels\n */\nexport function standardizeDataTypeLabel(\n\tpgType: string | null | undefined,\n): StandardizedDataType {\n\tif (!pgType) {\n\t\treturn StandardizedDataType.text; // Default fallback\n\t}\n\tconst normalized = pgType.toLowerCase().trim();\n\n\t// Numeric types\n\tif (\n\t\tnormalized === \"integer\" ||\n\t\tnormalized === \"int\" ||\n\t\tnormalized === \"int4\" ||\n\t\tnormalized === \"serial\" ||\n\t\tnormalized === \"serial4\"\n\t) {\n\t\treturn StandardizedDataType.int;\n\t}\n\n\tif (\n\t\tnormalized === \"bigint\" ||\n\t\tnormalized === \"int8\" ||\n\t\tnormalized === \"bigserial\" ||\n\t\tnormalized === \"serial8\"\n\t) {\n\t\treturn StandardizedDataType.bigint;\n\t}\n\n\tif (normalized === \"smallint\" || normalized === \"int2\") {\n\t\treturn StandardizedDataType.smallint;\n\t}\n\n\tif (\n\t\tnormalized === \"decimal\" ||\n\t\tnormalized.startsWith(\"decimal(\") ||\n\t\tnormalized === \"numeric\" ||\n\t\tnormalized.startsWith(\"numeric(\")\n\t) {\n\t\treturn StandardizedDataType.numeric;\n\t}\n\n\tif (normalized === \"real\" || normalized === \"float4\") {\n\t\treturn StandardizedDataType.float;\n\t}\n\n\tif (normalized === \"double precision\" || normalized === \"float8\" || normalized === \"float\") {\n\t\treturn StandardizedDataType.double;\n\t}\n\n\tif (normalized === \"money\") {\n\t\treturn StandardizedDataType.money;\n\t}\n\n\t// Boolean\n\tif (normalized === \"boolean\" || normalized === \"bool\") {\n\t\treturn StandardizedDataType.boolean;\n\t}\n\n\t// Text types\n\tif (normalized === \"text\") {\n\t\treturn StandardizedDataType.text;\n\t}\n\n\tif (\n\t\tnormalized === \"character varying\" ||\n\t\tnormalized.startsWith(\"varchar\") ||\n\t\tnormalized.startsWith(\"character varying(\")\n\t) {\n\t\treturn StandardizedDataType.varchar;\n\t}\n\n\tif (\n\t\tnormalized === \"character\" ||\n\t\tnormalized.startsWith(\"char\") ||\n\t\tnormalized.startsWith(\"character(\") ||\n\t\tnormalized === \"bpchar\"\n\t) {\n\t\treturn StandardizedDataType.char;\n\t}\n\n\t// JSON types\n\tif (normalized === \"json\") {\n\t\treturn StandardizedDataType.json;\n\t}\n\n\tif (normalized === \"jsonb\") {\n\t\treturn StandardizedDataType.jsonb;\n\t}\n\n\tif (normalized === \"xml\") {\n\t\treturn StandardizedDataType.xml;\n\t}\n\n\t// UUID\n\tif (normalized === \"uuid\") {\n\t\treturn StandardizedDataType.uuid;\n\t}\n\n\t// Date/Time types\n\tif (normalized === \"date\") {\n\t\treturn StandardizedDataType.date;\n\t}\n\n\tif (\n\t\tnormalized === \"time\" ||\n\t\tnormalized === \"time without time zone\" ||\n\t\tnormalized.startsWith(\"time(\")\n\t) {\n\t\treturn StandardizedDataType.time;\n\t}\n\n\tif (\n\t\tnormalized === \"timestamp\" ||\n\t\tnormalized === \"timestamp without time zone\" ||\n\t\tnormalized.startsWith(\"timestamp(\")\n\t) {\n\t\treturn StandardizedDataType.timestamp;\n\t}\n\n\tif (\n\t\tnormalized === \"timestamp with time zone\" ||\n\t\tnormalized === \"timestamptz\" ||\n\t\tnormalized.startsWith(\"timestamp with time zone(\")\n\t) {\n\t\treturn StandardizedDataType.timestamptz;\n\t}\n\n\tif (normalized === \"interval\" || normalized.startsWith(\"interval\")) {\n\t\treturn StandardizedDataType.interval;\n\t}\n\n\t// Binary\n\tif (normalized === \"bytea\") {\n\t\treturn StandardizedDataType.bytea;\n\t}\n\n\t// Network types\n\tif (normalized === \"inet\") {\n\t\treturn StandardizedDataType.inet;\n\t}\n\n\tif (normalized === \"cidr\") {\n\t\treturn StandardizedDataType.cidr;\n\t}\n\n\tif (normalized === \"macaddr\") {\n\t\treturn StandardizedDataType.macaddr;\n\t}\n\n\tif (normalized === \"macaddr8\") {\n\t\treturn StandardizedDataType.macaddr8;\n\t}\n\n\t// Geometric types\n\tif (normalized === \"point\") {\n\t\treturn StandardizedDataType.point;\n\t}\n\n\tif (normalized === \"line\") {\n\t\treturn StandardizedDataType.line;\n\t}\n\n\tif (normalized === \"polygon\") {\n\t\treturn StandardizedDataType.polygon;\n\t}\n\n\t// Array types\n\t// todo: handle array types\n\tif (normalized.startsWith(\"array\") || normalized.includes(\"[]\")) {\n\t\treturn StandardizedDataType.text;\n\t}\n\n\t// User-defined types (enums)\n\tif (normalized.startsWith(\"user-defined\") || normalized === \"enum\") {\n\t\treturn StandardizedDataType.enum;\n\t}\n\n\t// Default: return the original type\n\treturn StandardizedDataType.text;\n}\n\n/**\n * Maps MySQL data types to generic DataType enum (used for cell rendering)\n * @param mysqlDataType - The DATA_TYPE field from information_schema.COLUMNS\n * @param columnType - The COLUMN_TYPE field (e.g., \"tinyint(1)\", \"enum('a','b')\") for finer mapping\n */\nexport function mapMysqlToDataType(mysqlDataType: string, columnType?: string): DataTypes {\n\tconst normalized = mysqlDataType?.toLowerCase().trim() || \"\";\n\tconst fullType = columnType?.toLowerCase().trim() || \"\";\n\n\t// tinyint(1) is MySQL's boolean convention\n\tif (normalized === \"tinyint\" && fullType === \"tinyint(1)\") {\n\t\treturn DataTypes.boolean;\n\t}\n\n\t// Numeric types\n\tif (\n\t\tnormalized === \"tinyint\" ||\n\t\tnormalized === \"smallint\" ||\n\t\tnormalized === \"mediumint\" ||\n\t\tnormalized === \"int\" ||\n\t\tnormalized === \"integer\" ||\n\t\tnormalized === \"bigint\" ||\n\t\tnormalized === \"decimal\" ||\n\t\tnormalized === \"numeric\" ||\n\t\tnormalized === \"float\" ||\n\t\tnormalized === \"double\" ||\n\t\tnormalized === \"real\" ||\n\t\tnormalized === \"bit\"\n\t) {\n\t\treturn DataTypes.number;\n\t}\n\n\t// Boolean (explicit)\n\tif (normalized === \"boolean\" || normalized === \"bool\") {\n\t\treturn DataTypes.boolean;\n\t}\n\n\t// Date/time types\n\tif (\n\t\tnormalized === \"date\" ||\n\t\tnormalized === \"datetime\" ||\n\t\tnormalized === \"timestamp\" ||\n\t\tnormalized === \"time\" ||\n\t\tnormalized === \"year\"\n\t) {\n\t\treturn DataTypes.date;\n\t}\n\n\t// JSON\n\tif (normalized === \"json\") {\n\t\treturn DataTypes.json;\n\t}\n\n\t// Enum and set (set behaves like enum for display)\n\tif (normalized === \"enum\" || normalized === \"set\") {\n\t\treturn DataTypes.enum;\n\t}\n\n\t// All text and binary types default to text\n\treturn DataTypes.text;\n}\n\n/**\n * Maps MySQL data types to standardized display labels\n * @param mysqlDataType - The DATA_TYPE field from information_schema.COLUMNS\n * @param columnType - The COLUMN_TYPE field (e.g., \"tinyint(1)\") for finer mapping\n */\nexport function standardizeMysqlDataTypeLabel(\n\tmysqlDataType: string,\n\tcolumnType?: string,\n): StandardizedDataType {\n\tif (!mysqlDataType) {\n\t\treturn StandardizedDataType.text;\n\t}\n\tconst normalized = mysqlDataType.toLowerCase().trim();\n\tconst fullType = columnType?.toLowerCase().trim() || \"\";\n\n\t// tinyint(1) is MySQL's boolean convention\n\tif (normalized === \"tinyint\" && fullType === \"tinyint(1)\")\n\t\treturn StandardizedDataType.boolean;\n\n\t// Numeric types\n\tif (normalized === \"tinyint\") return StandardizedDataType.tinyint;\n\tif (normalized === \"smallint\") return StandardizedDataType.smallint;\n\tif (normalized === \"mediumint\") return StandardizedDataType.mediumint;\n\tif (normalized === \"int\" || normalized === \"integer\") return StandardizedDataType.int;\n\tif (normalized === \"bigint\") return StandardizedDataType.bigint;\n\tif (normalized === \"decimal\" || normalized === \"numeric\")\n\t\treturn StandardizedDataType.numeric;\n\tif (normalized === \"float\" || normalized === \"real\") return StandardizedDataType.float;\n\tif (normalized === \"double\") return StandardizedDataType.double;\n\tif (normalized === \"bit\") return StandardizedDataType.bit;\n\n\t// Boolean\n\tif (normalized === \"boolean\" || normalized === \"bool\") return StandardizedDataType.boolean;\n\n\t// Text types\n\tif (normalized === \"char\") return StandardizedDataType.char;\n\tif (normalized === \"varchar\") return StandardizedDataType.varchar;\n\tif (normalized === \"tinytext\") return StandardizedDataType.tinytext;\n\tif (normalized === \"text\") return StandardizedDataType.text;\n\tif (normalized === \"mediumtext\") return StandardizedDataType.mediumtext;\n\tif (normalized === \"longtext\") return StandardizedDataType.longtext;\n\n\t// Binary types\n\tif (normalized === \"binary\") return StandardizedDataType.binary;\n\tif (normalized === \"varbinary\") return StandardizedDataType.varbinary;\n\tif (normalized === \"tinyblob\") return StandardizedDataType.tinyblob;\n\tif (normalized === \"blob\") return StandardizedDataType.blob;\n\tif (normalized === \"mediumblob\") return StandardizedDataType.mediumblob;\n\tif (normalized === \"longblob\") return StandardizedDataType.longblob;\n\n\t// JSON\n\tif (normalized === \"json\") return StandardizedDataType.json;\n\n\t// Date/time types\n\tif (normalized === \"date\") return StandardizedDataType.date;\n\tif (normalized === \"time\") return StandardizedDataType.time;\n\tif (normalized === \"datetime\") return StandardizedDataType.datetime;\n\tif (normalized === \"timestamp\") return StandardizedDataType.timestamp;\n\tif (normalized === \"year\") return StandardizedDataType.year;\n\n\t// Complex types\n\tif (normalized === \"enum\") return StandardizedDataType.enum;\n\tif (normalized === \"set\") return StandardizedDataType.set;\n\n\t// Default\n\treturn StandardizedDataType.text;\n}\n\n/**\n * Maps SQL Server data types to generic DataType enum (used for cell rendering)\n * @param mssqlDataType - The data type from sys.columns or information_schema.columns\n */\nexport function mapMssqlToDataType(mssqlDataType: string): DataTypes {\n\tconst normalized = mssqlDataType?.toLowerCase().trim() || \"\";\n\n\t// Numeric types\n\tif (\n\t\tnormalized === \"tinyint\" ||\n\t\tnormalized === \"smallint\" ||\n\t\tnormalized === \"int\" ||\n\t\tnormalized === \"bigint\" ||\n\t\tnormalized === \"decimal\" ||\n\t\tnormalized === \"numeric\" ||\n\t\tnormalized === \"float\" ||\n\t\tnormalized === \"real\" ||\n\t\tnormalized === \"money\" ||\n\t\tnormalized === \"smallmoney\"\n\t) {\n\t\treturn DataTypes.number;\n\t}\n\n\t// Boolean (bit with length 1)\n\tif (normalized === \"bit\") {\n\t\treturn DataTypes.boolean;\n\t}\n\n\t// Date/time types\n\tif (\n\t\tnormalized === \"date\" ||\n\t\tnormalized === \"datetime\" ||\n\t\tnormalized === \"datetime2\" ||\n\t\tnormalized === \"smalldatetime\" ||\n\t\tnormalized === \"time\" ||\n\t\tnormalized === \"datetimeoffset\"\n\t) {\n\t\treturn DataTypes.date;\n\t}\n\n\t// JSON (SQL Server 2016+)\n\tif (normalized === \"json\") {\n\t\treturn DataTypes.json;\n\t}\n\n\t// All text and binary types default to text\n\treturn DataTypes.text;\n}\n\n/**\n * Maps SQL Server data types to standardized display labels\n * @param mssqlDataType - The data type from sys.columns or information_schema.columns\n */\nexport function standardizeMssqlDataTypeLabel(mssqlDataType: string): StandardizedDataType {\n\tif (!mssqlDataType) {\n\t\treturn StandardizedDataType.text;\n\t}\n\tconst normalized = mssqlDataType.toLowerCase().trim();\n\n\t// Numeric types\n\tif (normalized === \"tinyint\") return StandardizedDataType.tinyint;\n\tif (normalized === \"smallint\") return StandardizedDataType.smallint;\n\tif (normalized === \"int\") return StandardizedDataType.int;\n\tif (normalized === \"bigint\") return StandardizedDataType.bigint;\n\tif (normalized === \"decimal\" || normalized === \"numeric\")\n\t\treturn StandardizedDataType.numeric;\n\tif (normalized === \"float\") return StandardizedDataType.float;\n\tif (normalized === \"real\") return StandardizedDataType.float;\n\tif (normalized === \"money\" || normalized === \"smallmoney\") return StandardizedDataType.money;\n\n\t// Boolean\n\tif (normalized === \"bit\") return StandardizedDataType.boolean;\n\n\t// Text types\n\tif (normalized === \"char\") return StandardizedDataType.char;\n\tif (normalized === \"varchar\") return StandardizedDataType.varchar;\n\tif (normalized === \"text\") return StandardizedDataType.text;\n\tif (normalized === \"nchar\") return StandardizedDataType.char;\n\tif (normalized === \"nvarchar\") return StandardizedDataType.varchar;\n\tif (normalized === \"ntext\") return StandardizedDataType.text;\n\n\t// Binary types\n\tif (normalized === \"binary\") return StandardizedDataType.binary;\n\tif (normalized === \"varbinary\") return StandardizedDataType.varbinary;\n\tif (normalized === \"image\") return StandardizedDataType.blob;\n\n\t// UUID\n\tif (normalized === \"uniqueidentifier\") return StandardizedDataType.uuid;\n\n\t// Date/time types\n\tif (normalized === \"date\") return StandardizedDataType.date;\n\tif (normalized === \"time\") return StandardizedDataType.time;\n\tif (normalized === \"datetime\") return StandardizedDataType.datetime;\n\tif (normalized === \"datetime2\") return StandardizedDataType.datetime;\n\tif (normalized === \"smalldatetime\") return StandardizedDataType.datetime;\n\tif (normalized === \"datetimeoffset\") return StandardizedDataType.timestamptz;\n\n\t// JSON and XML\n\tif (normalized === \"json\") return StandardizedDataType.json;\n\tif (normalized === \"xml\") return StandardizedDataType.xml;\n\n\t// Default\n\treturn StandardizedDataType.text;\n}\n\n/**\n * Maps SQLite type affinity strings to generic DataTypes (used for cell rendering).\n * SQLite has flexible typing — column types are user-declared strings, so we use affinity rules.\n */\nexport function mapSqliteToDataType(sqliteType: string): DataTypes {\n\tconst normalized = sqliteType?.toLowerCase().trim() || \"\";\n\n\tif (normalized === \"boolean\" || normalized === \"bool\") return DataTypes.boolean;\n\tif (normalized === \"json\") return DataTypes.json;\n\n\tif (\n\t\tnormalized === \"date\" ||\n\t\tnormalized === \"datetime\" ||\n\t\tnormalized === \"timestamp\" ||\n\t\tnormalized === \"time\"\n\t) {\n\t\treturn DataTypes.date;\n\t}\n\n\t// SQLite integer affinity: any type name containing \"INT\"\n\tif (\n\t\tnormalized.includes(\"int\") ||\n\t\tnormalized === \"real\" ||\n\t\tnormalized.includes(\"floa\") ||\n\t\tnormalized.includes(\"doub\") ||\n\t\tnormalized === \"numeric\" ||\n\t\tnormalized.startsWith(\"numeric(\") ||\n\t\tnormalized === \"decimal\" ||\n\t\tnormalized.startsWith(\"decimal(\")\n\t) {\n\t\treturn DataTypes.number;\n\t}\n\n\treturn DataTypes.text;\n}\n\n/**\n * Maps SQLite type strings to the standardized display labels used in ColumnInfoSchemaType.\n */\nexport function standardizeSqliteDataTypeLabel(sqliteType: string): StandardizedDataType {\n\tconst normalized = sqliteType?.toLowerCase().trim() || \"\";\n\n\tif (normalized === \"integer\" || normalized === \"int\") return StandardizedDataType.int;\n\tif (normalized === \"bigint\" || normalized.startsWith(\"bigint(\"))\n\t\treturn StandardizedDataType.bigint;\n\tif (normalized === \"smallint\" || normalized.startsWith(\"smallint(\"))\n\t\treturn StandardizedDataType.smallint;\n\tif (normalized === \"tinyint\" || normalized.startsWith(\"tinyint(\"))\n\t\treturn StandardizedDataType.tinyint;\n\tif (normalized === \"mediumint\" || normalized.startsWith(\"mediumint(\"))\n\t\treturn StandardizedDataType.mediumint;\n\tif (normalized.includes(\"int\")) return StandardizedDataType.int;\n\n\tif (normalized === \"real\" || normalized === \"float\" || normalized.startsWith(\"float(\"))\n\t\treturn StandardizedDataType.float;\n\tif (\n\t\tnormalized === \"double\" ||\n\t\tnormalized === \"double precision\" ||\n\t\tnormalized.startsWith(\"double(\")\n\t)\n\t\treturn StandardizedDataType.double;\n\n\tif (\n\t\tnormalized === \"numeric\" ||\n\t\tnormalized.startsWith(\"numeric(\") ||\n\t\tnormalized === \"decimal\" ||\n\t\tnormalized.startsWith(\"decimal(\")\n\t) {\n\t\treturn StandardizedDataType.numeric;\n\t}\n\n\tif (normalized === \"boolean\" || normalized === \"bool\") return StandardizedDataType.boolean;\n\n\tif (normalized === \"text\" || normalized === \"clob\") return StandardizedDataType.text;\n\tif (normalized === \"varchar\" || normalized.startsWith(\"varchar(\"))\n\t\treturn StandardizedDataType.varchar;\n\tif (normalized === \"char\" || normalized.startsWith(\"char(\"))\n\t\treturn StandardizedDataType.char;\n\n\tif (normalized === \"json\") return StandardizedDataType.json;\n\n\tif (normalized === \"date\") return StandardizedDataType.date;\n\tif (normalized === \"time\") return StandardizedDataType.time;\n\tif (normalized === \"datetime\") return StandardizedDataType.datetime;\n\tif (normalized === \"timestamp\") return StandardizedDataType.timestamp;\n\n\tif (normalized === \"blob\") return StandardizedDataType.blob;\n\n\treturn StandardizedDataType.text;\n}\n\n/**\n * Maps DuckDB column types (as reported by `duckdb_columns().data_type`) to generic DataTypes.\n * LIST, ARRAY, STRUCT, MAP and UNION values arrive as JSON, so they render as json cells.\n */\nexport function mapDuckdbToDataType(duckdbType: string): DataTypes {\n\tconst normalized = duckdbType?.toLowerCase().trim() || \"\";\n\n\tif (\n\t\tnormalized.endsWith(\"]\") ||\n\t\tnormalized.startsWith(\"struct\") ||\n\t\tnormalized.startsWith(\"map\") ||\n\t\tnormalized.startsWith(\"union\") ||\n\t\tnormalized === \"json\"\n\t) {\n\t\treturn DataTypes.json;\n\t}\n\tif (normalized === \"boolean\" || normalized === \"bool\") return DataTypes.boolean;\n\tif (normalized.startsWith(\"enum\")) return DataTypes.enum;\n\tif (normalized === \"interval\") return DataTypes.text;\n\tif (normalized === \"date\" || normalized.startsWith(\"time\") || normalized === \"datetime\") {\n\t\treturn DataTypes.date;\n\t}\n\tif (\n\t\tnormalized.includes(\"int\") ||\n\t\tnormalized === \"float\" ||\n\t\tnormalized === \"real\" ||\n\t\tnormalized === \"double\" ||\n\t\tnormalized.startsWith(\"decimal\") ||\n\t\tnormalized.startsWith(\"numeric\") ||\n\t\tnormalized === \"bignum\"\n\t) {\n\t\treturn DataTypes.number;\n\t}\n\n\treturn DataTypes.text;\n}\n\n/**\n * Maps DuckDB column types to the standardized display labels used in ColumnInfoSchemaType.\n */\nexport function standardizeDuckdbDataTypeLabel(duckdbType: string): StandardizedDataType {\n\tconst normalized = duckdbType?.toLowerCase().trim() || \"\";\n\n\tif (normalized.endsWith(\"]\")) return StandardizedDataType.array;\n\tif (\n\t\tnormalized.startsWith(\"struct\") ||\n\t\tnormalized.startsWith(\"map\") ||\n\t\tnormalized.startsWith(\"union\") ||\n\t\tnormalized === \"json\"\n\t) {\n\t\treturn StandardizedDataType.json;\n\t}\n\tif (normalized.startsWith(\"enum\")) return StandardizedDataType.enum;\n\tif (normalized === \"interval\") return StandardizedDataType.interval;\n\n\tif (normalized === \"tinyint\" || normalized === \"utinyint\")\n\t\treturn StandardizedDataType.tinyint;\n\tif (normalized === \"smallint\" || normalized === \"usmallint\")\n\t\treturn StandardizedDataType.smallint;\n\tif (normalized === \"integer\" || normalized === \"int\") return StandardizedDataType.int;\n\tif (normalized.includes(\"int\") || normalized === \"bignum\")\n\t\treturn StandardizedDataType.bigint;\n\tif (normalized.startsWith(\"decimal\") || normalized.startsWith(\"numeric\"))\n\t\treturn StandardizedDataType.numeric;\n\tif (normalized === \"float\" || normalized === \"real\") return StandardizedDataType.float;\n\tif (normalized === \"double\") return StandardizedDataType.double;\n\n\tif (normalized === \"boolean\" || normalized === \"bool\") return StandardizedDataType.boolean;\n\tif (normalized === \"varchar\" || normalized.startsWith(\"varchar(\"))\n\t\treturn StandardizedDataType.varchar;\n\tif (normalized === \"uuid\") return StandardizedDataType.uuid;\n\n\tif (normalized === \"date\") return StandardizedDataType.date;\n\tif (normalized === \"timestamp with time zone\" || normalized === \"timestamptz\")\n\t\treturn StandardizedDataType.timestamptz;\n\tif (normalized.startsWith(\"timestamp\") || normalized === \"datetime\")\n\t\treturn StandardizedDataType.timestamp;\n\tif (normalized.startsWith(\"time\")) return StandardizedDataType.time;\n\n\tif (normalized === \"blob\" || normalized === \"bytea\") return StandardizedDataType.blob;\n\tif (normalized === \"bit\" || normalized === \"bitstring\") return StandardizedDataType.bit;\n\n\treturn StandardizedDataType.text;\n}\n\n/**\n * Maps Oracle column types (as formatted from `USER_TAB_COLUMNS`, e.g. `NUMBER(10)`,\n * `TIMESTAMP(6) WITH TIME ZONE`) to generic DataTypes. Oracle DATE carries a time of day.\n */\nexport function mapOracleToDataType(oracleType: string): DataTypes {\n\tconst normalized = oracleType?.toLowerCase().trim() || \"\";\n\n\tif (normalized === \"boolean\") return DataTypes.boolean;\n\tif (normalized === \"json\") return DataTypes.json;\n\tif (normalized === \"date\" || normalized.startsWith(\"timestamp\")) return DataTypes.date;\n\tif (\n\t\tnormalized.startsWith(\"number\") ||\n\t\tnormalized.startsWith(\"float\") ||\n\t\tnormalized === \"integer\" ||\n\t\tnormalized === \"binary_float\" ||\n\t\tnormalized === \"binary_double\"\n\t) {\n\t\treturn DataTypes.number;\n\t}\n\n\treturn DataTypes.text;\n}\n\n/**\n * Maps Oracle column types to the standardized display labels used in ColumnInfoSchemaType.\n */\nexport function standardizeOracleDataTypeLabel(oracleType: string): StandardizedDataType {\n\tconst normalized = oracleType?.toLowerCase().trim() || \"\";\n\n\tif (normalized === \"boolean\") return StandardizedDataType.boolean;\n\tif (normalized === \"json\") return StandardizedDataType.json;\n\tif (normalized === \"xmltype\") return StandardizedDataType.xml;\n\n\tif (normalized === \"integer\") return StandardizedDataType.int;\n\tconst integer = normalized.match(/^number\\((\\d+)(?:,0)?\\)$/);\n\tif (integer) {\n\t\tconst precision = Number(integer[1]);\n\t\tif (precision <= 4) return StandardizedDataType.smallint;\n\t\tif (precision <= 10) return StandardizedDataType.int;\n\t\tif (precision <= 19) return StandardizedDataType.bigint;\n\t}\n\tif (normalized.startsWith(\"number\")) return StandardizedDataType.numeric;\n\tif (normalized === \"binary_float\") return StandardizedDataType.float;\n\tif (normalized === \"binary_double\" || normalized.startsWith(\"float\"))\n\t\treturn StandardizedDataType.double;\n\n\tif (normalized.startsWith(\"varchar\") || normalized.startsWith(\"nvarchar\"))\n\t\treturn StandardizedDataType.varchar;\n\tif (normalized.startsWith(\"char\") || normalized.startsWith(\"nchar\"))\n\t\treturn StandardizedDataType.char;\n\n\tif (normalized.startsWith(\"timestamp\") && normalized.endsWith(\"time zone\"))\n\t\treturn StandardizedDataType.timestamptz;\n\tif (normalized === \"date\" || normalized.startsWith(\"timestamp\"))\n\t\treturn StandardizedDataType.timestamp;\n\tif (normalized.startsWith(\"interval\")) return StandardizedDataType.interval;\n\n\tif (normalized === \"blob\" || normalized === \"long raw\") return StandardizedDataType.blob;\n\tif (normalized.startsWith(\"raw\")) return StandardizedDataType.varbinary;\n\n\treturn StandardizedDataType.text;\n}\n\n/** Strips the `Nullable(...)` and `LowCardinality(...)` wrappers, which do not change how a value renders. */\nexport function unwrapClickhouseType(clickhouseType: string): string {\n\tlet type = clickhouseType.trim();\n\tfor (;;) {\n\t\tconst match = type.match(/^(?:Nullable|LowCardinality)\\((.*)\\)$/);\n\t\tif (!match?.[1]) return type;\n\t\ttype = match[1].trim();\n\t}\n}\n\n/**\n * Maps ClickHouse column types (as reported by `system.columns.type`) to generic DataTypes.\n */\nexport function mapClickhouseToDataType(clickhouseType: string): DataTypes {\n\tconst type = unwrapClickhouseType(clickhouseType);\n\n\tif (type.startsWith(\"Array(\")) return DataTypes.array;\n\tif (type.startsWith(\"Enum8(\") || type.startsWith(\"Enum16(\")) return DataTypes.enum;\n\tif (type === \"Bool\") return DataTypes.boolean;\n\tif (/^(Date|Date32|DateTime|DateTime64|Time|Time64)\\b/.test(type)) return DataTypes.date;\n\tif (/^(U?Int\\d+|Float\\d+|BFloat16|Decimal\\d*)\\b/.test(type)) return DataTypes.number;\n\tif (/^(JSON|Object|Map|Tuple|Variant|Dynamic|Nested)\\b/.test(type)) return DataTypes.json;\n\n\treturn DataTypes.text;\n}\n\n/**\n * Maps ClickHouse column types to the standardized display labels used in ColumnInfoSchemaType.\n */\nexport function standardizeClickhouseDataTypeLabel(\n\tclickhouseType: string,\n): StandardizedDataType {\n\tconst type = unwrapClickhouseType(clickhouseType);\n\n\tif (type.startsWith(\"Array(\")) return StandardizedDataType.array;\n\tif (type.startsWith(\"Enum8(\") || type.startsWith(\"Enum16(\"))\n\t\treturn StandardizedDataType.enum;\n\tif (type === \"Bool\") return StandardizedDataType.boolean;\n\n\tif (/^U?Int8$/.test(type)) return StandardizedDataType.tinyint;\n\tif (/^U?Int16$/.test(type)) return StandardizedDataType.smallint;\n\tif (/^U?Int32$/.test(type)) return StandardizedDataType.int;\n\tif (/^U?Int(64|128|256)$/.test(type)) return StandardizedDataType.bigint;\n\tif (type === \"Float32\" || type === \"BFloat16\") return StandardizedDataType.float;\n\tif (type === \"Float64\") return StandardizedDataType.double;\n\tif (type.startsWith(\"Decimal\")) return StandardizedDataType.numeric;\n\n\tif (type.startsWith(\"FixedString(\")) return StandardizedDataType.char;\n\tif (type === \"UUID\") return StandardizedDataType.uuid;\n\tif (type === \"IPv4\" || type === \"IPv6\") return StandardizedDataType.inet;\n\n\tif (type === \"Date\" || type === \"Date32\") return StandardizedDataType.date;\n\tif (type.startsWith(\"DateTime64\")) return StandardizedDataType.timestamp;\n\tif (type.startsWith(\"DateTime\")) return StandardizedDataType.datetime;\n\tif (type.startsWith(\"Time\")) return StandardizedDataType.time;\n\n\tif (/^(JSON|Object|Map|Tuple|Variant|Dynamic|Nested)\\b/.test(type))\n\t\treturn StandardizedDataType.json;\n\n\treturn StandardizedDataType.text;\n}\n","import { z } from \"zod\";\n\nexport const FOREIGN_KEY_ACTIONS = [\n\t\"CASCADE\",\n\t\"SET NULL\",\n\t\"SET DEFAULT\",\n\t\"RESTRICT\",\n\t\"NO ACTION\",\n] as const;\nexport const foreignKeyActionSchema = z.enum(FOREIGN_KEY_ACTIONS);\n\nexport const fieldDataSchema = z.object({\n\tcolumnName: z.string(\"Column name is required\"),\n\tcolumnType: z.string(\"Column type is required\"),\n\tdefaultValue: z.string().optional(),\n\tisPrimaryKey: z.boolean().default(false),\n\tisNullable: z.boolean().default(false),\n\tisUnique: z.boolean().default(false),\n\tisIdentity: z.boolean().default(false),\n\tisArray: z.boolean().default(false),\n});\nexport type FieldDataType = z.infer<typeof fieldDataSchema>;\n\nexport const foreignKeyDataSchema = z.object({\n\tcolumnName: z.string(\"Column name is required\"),\n\treferencedTable: z.string(\"Referenced table is required\"),\n\treferencedColumn: z.string(\"Referenced column is required\"),\n\tonUpdate: foreignKeyActionSchema.default(\"NO ACTION\"),\n\tonDelete: foreignKeyActionSchema.default(\"NO ACTION\"),\n});\nexport type ForeignKeyDataType = z.infer<typeof foreignKeyDataSchema>;\n\nexport const createTableSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n\tfields: z.array(fieldDataSchema).min(1, \"At least one field is required\"),\n\tforeignKeys: z.array(foreignKeyDataSchema).optional(),\n});\n\nexport type CreateTableSchemaType = z.infer<typeof createTableSchema>;\n","import { DATABASE_TYPES, type DatabaseTypeSchema } from \"./database.types.js\";\n\nexport type DataModel = \"relational\" | \"document\" | \"key-value\";\n\ninterface DatabaseEngineBase {\n\tlabel: string;\n\t/** URL schemes; the first is canonical. */\n\tprotocols: readonly string[];\n\t/** `null` for file-based engines. */\n\tdefaultPort: number | null;\n\tdataModel: DataModel;\n\teditorLanguage: \"pgsql\" | \"json\" | \"plaintext\";\n\tliveMode: boolean;\n\tschemaSelector: boolean;\n}\n\ntype RowMutationCapability =\n\t| { rowMutation: true; rowMutationReason?: never }\n\t| { rowMutation: false; rowMutationReason: string };\n\nexport type DatabaseEngine = DatabaseEngineBase & RowMutationCapability;\n\nexport const DATABASE_ENGINES = {\n\tpg: {\n\t\tlabel: \"PostgreSQL\",\n\t\tprotocols: [\"postgres\", \"postgresql\", \"cockroachdb\"],\n\t\tdefaultPort: 5432,\n\t\tdataModel: \"relational\",\n\t\teditorLanguage: \"pgsql\",\n\t\tliveMode: true,\n\t\tschemaSelector: true,\n\t\trowMutation: true,\n\t},\n\tmysql: {\n\t\tlabel: \"MySQL\",\n\t\tprotocols: [\"mysql\", \"mysql2\", \"mariadb\", \"tidb\"],\n\t\tdefaultPort: 3306,\n\t\tdataModel: \"relational\",\n\t\teditorLanguage: \"pgsql\",\n\t\tliveMode: true,\n\t\tschemaSelector: false,\n\t\trowMutation: true,\n\t},\n\tmssql: {\n\t\tlabel: \"SQL Server\",\n\t\tprotocols: [\"mssql\", \"sqlserver\"],\n\t\tdefaultPort: 1433,\n\t\tdataModel: \"relational\",\n\t\teditorLanguage: \"pgsql\",\n\t\tliveMode: true,\n\t\tschemaSelector: false,\n\t\trowMutation: true,\n\t},\n\tmongodb: {\n\t\tlabel: \"MongoDB\",\n\t\tprotocols: [\"mongodb\", \"mongodb+srv\"],\n\t\tdefaultPort: 27017,\n\t\tdataModel: \"document\",\n\t\teditorLanguage: \"json\",\n\t\tliveMode: false,\n\t\tschemaSelector: false,\n\t\trowMutation: true,\n\t},\n\tsqlite: {\n\t\tlabel: \"SQLite / libSQL\",\n\t\tprotocols: [\"sqlite\", \"libsql\"],\n\t\tdefaultPort: null,\n\t\tdataModel: \"relational\",\n\t\teditorLanguage: \"pgsql\",\n\t\tliveMode: true,\n\t\tschemaSelector: false,\n\t\trowMutation: true,\n\t},\n\tredis: {\n\t\tlabel: \"Redis\",\n\t\tprotocols: [\"redis\", \"rediss\"],\n\t\tdefaultPort: 6379,\n\t\tdataModel: \"key-value\",\n\t\teditorLanguage: \"plaintext\",\n\t\tliveMode: false,\n\t\tschemaSelector: false,\n\t\trowMutation: true,\n\t},\n\tduckdb: {\n\t\tlabel: \"DuckDB\",\n\t\tprotocols: [\"duckdb\"],\n\t\tdefaultPort: null,\n\t\tdataModel: \"relational\",\n\t\teditorLanguage: \"pgsql\",\n\t\tliveMode: true,\n\t\tschemaSelector: false,\n\t\trowMutation: true,\n\t},\n\toracle: {\n\t\tlabel: \"Oracle\",\n\t\tprotocols: [\"oracle\"],\n\t\tdefaultPort: 1521,\n\t\tdataModel: \"relational\",\n\t\teditorLanguage: \"pgsql\",\n\t\tliveMode: true,\n\t\tschemaSelector: false,\n\t\trowMutation: true,\n\t},\n\tclickhouse: {\n\t\tlabel: \"ClickHouse\",\n\t\tprotocols: [\"clickhouse\", \"clickhouses\"],\n\t\tdefaultPort: 8123,\n\t\tdataModel: \"relational\",\n\t\teditorLanguage: \"pgsql\",\n\t\tliveMode: false,\n\t\tschemaSelector: false,\n\t\trowMutation: false,\n\t\trowMutationReason:\n\t\t\t\"Use a SQL query to update or delete ClickHouse rows; sorting keys are not unique.\",\n\t},\n} satisfies Record<DatabaseTypeSchema, DatabaseEngine>;\n\n/** Maps a URL scheme without the trailing colon (e.g. `\"postgresql\"`) to its db type. */\nexport const dbTypeFromProtocol = (protocol: string): DatabaseTypeSchema | undefined =>\n\tDATABASE_TYPES.find((type) => DATABASE_ENGINES[type].protocols.includes(protocol));\n","import { z } from \"zod\";\nimport { databaseTypeSchema } from \"./database.types.js\";\n\nexport const databaseInfoSchema = z.object({\n\tname: z.string(\"Name is required\"),\n\tsize: z.string(\"Size is required\"),\n\towner: z.string(\"Owner is required\"),\n\tencoding: z.string(\"Encoding is required\"),\n});\n\nexport type DatabaseInfoSchemaType = z.infer<typeof databaseInfoSchema>;\n\nexport const databaseListSchema = z.object({\n\tdatabases: z.array(databaseInfoSchema),\n\tdbType: databaseTypeSchema,\n});\n\nexport type DatabaseListSchemaType = z.infer<typeof databaseListSchema>;\n\nexport const connectionInfoSchema = z.object({\n\tversion: z.string(\"Version is required\"),\n\tdatabase: z.string(\"Database is required\"),\n\tuser: z.string(\"User is required\"),\n\thost: z.string(\"Host is required\").nullable(),\n\tport: z.number(\"Port is required\").nullable(),\n\tactive_connections: z.coerce.number(\"Active connections is required\"),\n\tmax_connections: z.coerce.number(\"Max connections is required\"),\n});\n\nexport type ConnectionInfoSchemaType = z.infer<typeof connectionInfoSchema>;\n","import type { DatabaseTypeSchema } from \"./database.types.js\";\n\nexport type DatabaseSchema = {\n\tdbType: DatabaseTypeSchema;\n\ttables: Table[];\n\trelationships: Relationship[];\n};\n\nexport type Table = {\n\tname: string;\n\tdescription?: string;\n\tcolumns: Column[];\n\tsampleData?: Record<string, string>[];\n};\n\nexport type Column = {\n\tname: string;\n\ttype: string;\n\tnullable: boolean;\n\tisPrimaryKey?: boolean;\n\tforeignKey?: string;\n\tdescription?: string;\n\tenumValues?: string[];\n};\n\nexport type Relationship = {\n\tfromTable: string;\n\tfromColumn: string;\n\ttoTable: string;\n\ttoColumn: string;\n};\n","import { z } from \"zod\";\nimport type { DatabaseSchemaType } from \"./database.types\";\n\nexport const deleteRecordSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n\tprimaryKeys: z\n\t\t.array(\n\t\t\tz.object({\n\t\t\t\tcolumnName: z.string(\"Column name is required\"),\n\t\t\t\tvalue: z.any(),\n\t\t\t}),\n\t\t)\n\t\t.min(1, \"At least one primary key is required\"),\n});\n\nexport type DeleteRecordSchemaType = z.infer<typeof deleteRecordSchema>;\n\nexport type DeleteRecordParams = DeleteRecordSchemaType & {\n\tdb: DatabaseSchemaType[\"db\"];\n};\n\nexport type DeleteRecordResult = {\n\tdeletedCount: number;\n\tfkViolation: boolean;\n\trelatedRecords: RelatedRecord[];\n};\n\nexport type ForeignKeyConstraint = {\n\tconstraintName: string;\n\treferencingTable: string;\n\treferencingColumn: string;\n\treferencedTable: string;\n\treferencedColumn: string;\n};\n\nexport type ForeignKeyConstraintRow = {\n\tconstraint_name: string;\n\treferencing_table: string;\n\treferencing_column: string;\n\treferenced_table: string;\n\treferenced_column: string;\n};\n\nexport type RelatedRecord = {\n\ttableName: string;\n\tcolumnName: string;\n\tconstraintName: string;\n\trecords: Array<Record<string, unknown>>;\n};\n","import { z } from \"zod\";\nimport { databaseSchema } from \"./database.types\";\nimport type { RelatedRecord } from \"./delete-record.types\";\n\nexport const deleteTableQuerySchema = databaseSchema.extend({\n\tcascade: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform((val) => val === \"true\"),\n});\n\nexport type DeleteTableQuerySchemaType = z.infer<typeof deleteTableQuerySchema>;\n\nexport type DeleteTableParams = {\n\ttableName: string;\n\tdb: string;\n\tcascade?: boolean;\n};\n\nexport type DeleteTableResult = {\n\tdeletedCount: number;\n\tfkViolation: boolean;\n\trelatedRecords: RelatedRecord[];\n};\n","import { z } from \"zod\";\n\nexport const executeQuerySchema = z.object({\n\tquery: z.string(\"Query is required\"),\n});\n\nexport type ExecuteQueryParams = z.infer<typeof executeQuerySchema>;\n\nexport type ExecuteQueryResult = {\n\tcolumns: string[];\n\trows: Record<string, unknown>[];\n\trowCount: number;\n\tduration: number;\n\tmessage?: string;\n\terror?: string;\n};\n","import { z } from \"zod\";\nimport { databaseSchema } from \"./database.types.js\";\n\nexport const FORMAT_TYPES = [\"csv\", \"xlsx\", \"json\"] as const;\nexport type FormatType = (typeof FORMAT_TYPES)[number];\n\nexport const exportTableSchema = databaseSchema.extend({\n\tformat: z.enum(FORMAT_TYPES, {\n\t\tmessage: \"Invalid format. Supported formats: csv, xlsx, json\",\n\t}),\n});\nexport type ExportTableSchemaType = z.infer<typeof exportTableSchema>;\n\nexport type CellValue = string | number | boolean | Date | null | undefined;\n","import { z } from \"zod\";\n\nexport const redisKeyTypeSchema = z.enum([\n\t\"string\",\n\t\"hash\",\n\t\"list\",\n\t\"set\",\n\t\"zset\",\n\t\"stream\",\n\t\"unknown\",\n]);\nexport type RedisKeyTypeSchemaType = z.infer<typeof redisKeyTypeSchema>;\n\nexport const encodedRedisValueSchema = z.object({\n\tbase64: z\n\t\t.string()\n\t\t.max(16 * 1024 * 1024)\n\t\t.refine(\n\t\t\t(value) => /^(?:[A-Za-z0-9_-]{4})*(?:[A-Za-z0-9_-]{2,3})?$/.test(value),\n\t\t\t\"Invalid unpadded base64url value\",\n\t\t),\n\tutf8: z.string().optional(),\n});\nexport type EncodedRedisValueSchemaType = z.infer<typeof encodedRedisValueSchema>;\n\nexport const keyScanQuerySchema = z.object({\n\tdb: z.string(),\n\tcursor: z\n\t\t.string()\n\t\t.max(2048)\n\t\t.regex(/^[A-Za-z0-9_-]+$/)\n\t\t.optional(),\n\tlimit: z.coerce.number().int().min(1).max(200).default(50),\n\tsearch: z.string().max(512).optional(),\n\texactPattern: z.stringbool().default(false),\n\ttype: redisKeyTypeSchema.exclude([\"unknown\"]).optional(),\n});\nexport type KeyScanQuerySchemaType = z.infer<typeof keyScanQuerySchema>;\n\nexport const redisKeySummarySchema = z.object({\n\tkey: encodedRedisValueSchema,\n\ttype: redisKeyTypeSchema,\n\tttlMs: z.number().int(),\n\tmemoryBytes: z.number().int().nonnegative().nullable(),\n});\nexport type RedisKeySummarySchemaType = z.infer<typeof redisKeySummarySchema>;\n\nexport const keyScanResultSchema = z.object({\n\tkeys: z.array(redisKeySummarySchema),\n\tnextCursor: z.string().nullable(),\n\thasMore: z.boolean(),\n});\nexport type KeyScanResultSchemaType = z.infer<typeof keyScanResultSchema>;\n\nexport const keyDetailsQuerySchema = z.object({\n\tdb: z.string(),\n\tcursor: z\n\t\t.string()\n\t\t.max(2048)\n\t\t.regex(/^[A-Za-z0-9_-]+$/)\n\t\t.optional(),\n\tlimit: z.coerce.number().int().min(1).max(500).default(100),\n\tfull: z.stringbool().default(false),\n\tdirection: z.enum([\"forward\", \"backward\"]).default(\"forward\"),\n});\nexport type KeyDetailsQuerySchemaType = z.infer<typeof keyDetailsQuerySchema>;\n\nexport const keyParamSchema = z.object({\n\tkey: z\n\t\t.string()\n\t\t.min(1)\n\t\t.max(16 * 1024)\n\t\t.regex(/^[A-Za-z0-9_-]+$/), // \"-\" is the URL sentinel for Redis' valid empty binary key.\n});\n\nconst redisStringValueSchema = z.object({\n\tkind: z.literal(\"string\"),\n\tvalue: encodedRedisValueSchema,\n\ttruncated: z.boolean(),\n});\n\nconst redisHashValueSchema = z.object({\n\tkind: z.literal(\"hash\"),\n\tentries: z.array(\n\t\tz.object({ field: encodedRedisValueSchema, value: encodedRedisValueSchema }),\n\t),\n});\n\nconst redisListValueSchema = z.object({\n\tkind: z.literal(\"list\"),\n\tentries: z.array(z.object({ index: z.number().int(), value: encodedRedisValueSchema })),\n});\n\nconst redisSetValueSchema = z.object({\n\tkind: z.literal(\"set\"),\n\tmembers: z.array(encodedRedisValueSchema),\n});\n\nconst redisSortedSetValueSchema = z.object({\n\tkind: z.literal(\"zset\"),\n\tentries: z.array(\n\t\tz.object({\n\t\t\tmember: encodedRedisValueSchema,\n\t\t\tscore: z.union([z.number(), z.literal(\"inf\"), z.literal(\"-inf\")]),\n\t\t}),\n\t),\n});\n\nconst redisStreamValueSchema = z.object({\n\tkind: z.literal(\"stream\"),\n\tentries: z.array(\n\t\tz.object({\n\t\t\tid: z.string(),\n\t\t\tfields: z.array(\n\t\t\t\tz.object({ field: encodedRedisValueSchema, value: encodedRedisValueSchema }),\n\t\t\t),\n\t\t}),\n\t),\n});\n\nconst redisUnknownValueSchema = z.object({ kind: z.literal(\"unknown\") });\n\nexport const redisKeyValueSchema = z.discriminatedUnion(\"kind\", [\n\tredisStringValueSchema,\n\tredisHashValueSchema,\n\tredisListValueSchema,\n\tredisSetValueSchema,\n\tredisSortedSetValueSchema,\n\tredisStreamValueSchema,\n\tredisUnknownValueSchema,\n]);\nexport type RedisKeyValueSchemaType = z.infer<typeof redisKeyValueSchema>;\n\nexport const keyDetailsResultSchema = redisKeySummarySchema.extend({\n\tlength: z.number().int().nonnegative().nullable(),\n\trevision: z.string(),\n\tvalue: redisKeyValueSchema,\n\tnextCursor: z.string().nullable(),\n\thasMore: z.boolean(),\n});\nexport type KeyDetailsResultSchemaType = z.infer<typeof keyDetailsResultSchema>;\n\nexport const keyRawQuerySchema = z.object({\n\tdb: z.string(),\n\toffset: z.coerce.number().int().nonnegative().default(0),\n\tlimit: z.coerce\n\t\t.number()\n\t\t.int()\n\t\t.min(1)\n\t\t.max(1024 * 1024)\n\t\t.default(1024 * 1024),\n\texpectedRevision: z.string().optional(),\n});\nexport type KeyRawQuerySchemaType = z.infer<typeof keyRawQuerySchema>;\n\nexport const keyRawResultSchema = z.object({\n\tchunk: encodedRedisValueSchema,\n\tlength: z.number().int().nonnegative(),\n\tnextOffset: z.number().int().nonnegative().nullable(),\n\thasMore: z.boolean(),\n});\nexport type KeyRawResultSchemaType = z.infer<typeof keyRawResultSchema>;\n\nconst createStringValueSchema = z.object({\n\tkind: z.literal(\"string\"),\n\tvalue: encodedRedisValueSchema,\n});\n\nconst createHashValueSchema = z.object({\n\tkind: z.literal(\"hash\"),\n\tentries: z\n\t\t.array(z.object({ field: encodedRedisValueSchema, value: encodedRedisValueSchema }))\n\t\t.min(1),\n});\n\nconst createListValueSchema = z.object({\n\tkind: z.literal(\"list\"),\n\tentries: z.array(encodedRedisValueSchema).min(1),\n});\n\nconst createSetValueSchema = z.object({\n\tkind: z.literal(\"set\"),\n\tmembers: z.array(encodedRedisValueSchema).min(1),\n});\n\nconst createSortedSetValueSchema = z.object({\n\tkind: z.literal(\"zset\"),\n\tentries: z.array(z.object({ member: encodedRedisValueSchema, score: z.number() })).min(1),\n});\n\nconst createStreamValueSchema = z.object({\n\tkind: z.literal(\"stream\"),\n\tid: z.string().default(\"*\"),\n\tfields: z\n\t\t.array(z.object({ field: encodedRedisValueSchema, value: encodedRedisValueSchema }))\n\t\t.min(1),\n});\n\nexport const createKeySchema = z.object({\n\tkey: encodedRedisValueSchema,\n\ttype: redisKeyTypeSchema.exclude([\"unknown\"]),\n\tvalue: z.discriminatedUnion(\"kind\", [\n\t\tcreateStringValueSchema,\n\t\tcreateHashValueSchema,\n\t\tcreateListValueSchema,\n\t\tcreateSetValueSchema,\n\t\tcreateSortedSetValueSchema,\n\t\tcreateStreamValueSchema,\n\t]),\n\tttlMs: z.number().int().positive().nullable().default(null),\n});\nexport type CreateKeySchemaType = z.infer<typeof createKeySchema>;\n\nexport const keyWriteResultSchema = z.object({\n\tkey: encodedRedisValueSchema,\n\trevision: z.string().nullable(),\n\tdeleted: z.boolean(),\n});\nexport type KeyWriteResultSchemaType = z.infer<typeof keyWriteResultSchema>;\n\nconst renameKeyActionSchema = z.object({\n\taction: z.literal(\"rename\"),\n\tnewKey: encodedRedisValueSchema,\n});\n\nconst setTtlKeyActionSchema = z.object({\n\taction: z.literal(\"setTtl\"),\n\tttlMs: z.number().int().positive().nullable(),\n});\n\nconst setStringKeyActionSchema = z.object({\n\taction: z.literal(\"setString\"),\n\tvalue: encodedRedisValueSchema,\n});\n\nconst upsertHashKeyActionSchema = z.object({\n\taction: z.literal(\"upsertHash\"),\n\tfield: encodedRedisValueSchema,\n\tvalue: encodedRedisValueSchema,\n});\n\nconst deleteHashKeyActionSchema = z.object({\n\taction: z.literal(\"deleteHash\"),\n\tfield: encodedRedisValueSchema,\n});\n\nconst pushListKeyActionSchema = z.object({\n\taction: z.literal(\"pushList\"),\n\tside: z.enum([\"left\", \"right\"]),\n\tvalue: encodedRedisValueSchema,\n});\n\nconst setListKeyActionSchema = z.object({\n\taction: z.literal(\"setList\"),\n\tindex: z.number().int(),\n\tvalue: encodedRedisValueSchema,\n});\n\nconst deleteListKeyActionSchema = z.object({\n\taction: z.literal(\"deleteList\"),\n\tindex: z.number().int(),\n});\n\nconst addSetKeyActionSchema = z.object({\n\taction: z.literal(\"addSet\"),\n\tmember: encodedRedisValueSchema,\n});\n\nconst removeSetKeyActionSchema = z.object({\n\taction: z.literal(\"removeSet\"),\n\tmember: encodedRedisValueSchema,\n});\n\nconst upsertSortedSetKeyActionSchema = z.object({\n\taction: z.literal(\"upsertZset\"),\n\tmember: encodedRedisValueSchema,\n\tscore: z.number(),\n});\n\nconst removeSortedSetKeyActionSchema = z.object({\n\taction: z.literal(\"removeZset\"),\n\tmember: encodedRedisValueSchema,\n});\n\nconst appendStreamKeyActionSchema = z.object({\n\taction: z.literal(\"appendStream\"),\n\tid: z.string().default(\"*\"),\n\tfields: z\n\t\t.array(z.object({ field: encodedRedisValueSchema, value: encodedRedisValueSchema }))\n\t\t.min(1),\n});\n\nconst deleteStreamKeyActionSchema = z.object({\n\taction: z.literal(\"deleteStream\"),\n\tid: z.string(),\n});\n\nexport const keyActionSchema = z.object({\n\texpectedRevision: z.string(),\n\tforce: z.boolean().default(false),\n\toperation: z.discriminatedUnion(\"action\", [\n\t\trenameKeyActionSchema,\n\t\tsetTtlKeyActionSchema,\n\t\tsetStringKeyActionSchema,\n\t\tupsertHashKeyActionSchema,\n\t\tdeleteHashKeyActionSchema,\n\t\tpushListKeyActionSchema,\n\t\tsetListKeyActionSchema,\n\t\tdeleteListKeyActionSchema,\n\t\taddSetKeyActionSchema,\n\t\tremoveSetKeyActionSchema,\n\t\tupsertSortedSetKeyActionSchema,\n\t\tremoveSortedSetKeyActionSchema,\n\t\tappendStreamKeyActionSchema,\n\t\tdeleteStreamKeyActionSchema,\n\t]),\n});\nexport type KeyActionSchemaType = z.infer<typeof keyActionSchema>;\n\nexport const deleteKeyQuerySchema = z.object({\n\tdb: z.string(),\n\texpectedRevision: z.string(),\n\tforce: z.stringbool().default(false),\n});\nexport type DeleteKeyQuerySchemaType = z.infer<typeof deleteKeyQuerySchema>;\n\nexport const deleteKeyResultSchema = z.object({ deleted: z.boolean() });\nexport type DeleteKeyResultSchemaType = z.infer<typeof deleteKeyResultSchema>;\n","export type RateLimitResponse = {\n\tlimit: number;\n\tused: number;\n\tremaining: number;\n};\n","import { z } from \"zod\";\nimport { databaseSchema } from \"./database.types\";\nimport { deleteColumnParamSchema } from \"./delete-column.types\";\n\nexport const renameColumnSchema = z.object({\n\tnewColumnName: z.string(\"New column name is required\"),\n});\n\nexport type RenameColumnSchemaType = z.infer<typeof renameColumnSchema>;\n\nexport const renameColumnParamSchema = deleteColumnParamSchema;\n\nexport type RenameColumnParamSchemaType = z.infer<typeof renameColumnParamSchema>;\n\nexport const renameColumnParamsSchema = z.object({\n\tdb: databaseSchema.shape.db,\n\ttableName: deleteColumnParamSchema.shape.tableName,\n\tcolumnName: deleteColumnParamSchema.shape.columnName,\n\tnewColumnName: renameColumnSchema.shape.newColumnName,\n});\n\nexport type RenameColumnParamsSchemaType = z.infer<typeof renameColumnParamsSchema>;\n","import { z } from \"zod\";\nimport { databaseSchema, tableNameSchema } from \"./database.types\";\n\nexport const renameTableSchema = z.object({\n\t// Trimmed server-side so whitespace-only names are rejected even if a\n\t// client skips the frontend trim (matches the sidebar dialog behavior).\n\tnewTableName: z\n\t\t.string(\"New table name is required\")\n\t\t.trim()\n\t\t.min(1, \"New table name is required\"),\n\tschemaName: z.string().trim().min(1).optional(),\n});\n\nexport type RenameTableSchemaType = z.infer<typeof renameTableSchema>;\n\nexport const renameTableParamSchema = tableNameSchema;\n\nexport type RenameTableParamSchemaType = z.infer<typeof renameTableParamSchema>;\n\nexport const renameTableParamsSchema = z.object({\n\tdb: databaseSchema.shape.db,\n\ttableName: tableNameSchema.shape.tableName,\n\tnewTableName: renameTableSchema.shape.newTableName,\n\tschemaName: renameTableSchema.shape.schemaName,\n});\n\nexport type RenameTableParamsSchemaType = z.infer<typeof renameTableParamsSchema>;\n","import { z } from \"zod\";\nimport { databaseSchema } from \"./database.types.js\";\n\nexport const filterSchema = z.object({\n\tcolumnName: z.string(),\n\toperator: z.string(),\n\tvalue: z.string(),\n});\n\nexport type FilterType = z.infer<typeof filterSchema>;\n\nexport const sortDirections = [\"asc\", \"desc\"] as const;\nexport type SortDirection = (typeof sortDirections)[number];\n\nexport const sortSchema = z.object({\n\tcolumnName: z.string(),\n\tdirection: z.enum(sortDirections),\n});\n\nexport type SortType = z.infer<typeof sortSchema>;\n\nexport const tableDataMetaSchema = z.object({\n\tlimit: z.number(),\n\ttotal: z.number(),\n\thasNextPage: z.boolean(),\n\thasPreviousPage: z.boolean(),\n\tnextCursor: z.string().nullable(),\n\tprevCursor: z.string().nullable(),\n});\n\nexport const tableDataResultSchema = z.object({\n\tdata: z.array(z.record(z.string(), z.unknown())),\n\tmeta: tableDataMetaSchema,\n});\n\nexport type TableDataResultSchemaType = z.infer<typeof tableDataResultSchema>;\n\nexport const tableDataQuerySchema = z.object({\n\tdb: databaseSchema.shape.db,\n\tcursor: z.string().optional(), // Base64 encoded cursor for pagination\n\tlimit: z.string().optional().default(\"50\").transform(Number),\n\tdirection: z.enum(sortDirections).optional().default(sortDirections[0]), // Pagination direction\n\tsort: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform((val) => {\n\t\t\tif (!val) return \"\";\n\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(val);\n\t\t\t\tif (Array.isArray(parsed)) {\n\t\t\t\t\treturn parsed;\n\t\t\t\t}\n\t\t\t\treturn val;\n\t\t\t} catch {\n\t\t\t\treturn val;\n\t\t\t}\n\t\t}),\n\torder: z.enum(sortDirections).optional(),\n\tfilters: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform((val) => {\n\t\t\tif (!val) return [];\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(val);\n\t\t\t} catch {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t}),\n});\n\nexport type TableDataQuerySchemaType = z.infer<typeof tableDataQuerySchema>;\n\nexport interface CursorData {\n\tvalues: Record<string, unknown>;\n\tsortColumns: string[];\n}\n","import { z } from \"zod\";\n\nexport const tableInfoSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n\tschemaName: z.string().optional(),\n\trowCount: z.coerce.number(\"Row count is required\"),\n});\n\nexport type TableInfoSchemaType = z.infer<typeof tableInfoSchema>;\n","import { z } from \"zod\";\n\nexport const tableSchemaResultSchema = z.object({\n\tschema: z.string(),\n});\n\nexport type TableSchemaResult = z.infer<typeof tableSchemaResultSchema>;\n","import { z } from \"zod\";\n\nexport const updateRecordsSchema = z.object({\n\ttableName: z.string(\"Table name is required\"),\n\tprimaryKey: z.string(\"Primary key is required\").default(\"id\"),\n\t/**\n\t * Every component of a composite primary key. When present it takes precedence\n\t * over `primaryKey`, so a row is matched on all of its key columns instead of\n\t * only the first one.\n\t */\n\tprimaryKeys: z.array(z.string().min(1)).min(1).optional(),\n\tupdates: z\n\t\t.array(\n\t\t\tz.object(\n\t\t\t\t{\n\t\t\t\t\trowData: z.record(z.string(\"Column name is required\"), z.any()),\n\t\t\t\t\tcolumnName: z.string(\"Column name is required\"),\n\t\t\t\t\tvalue: z.any(),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tmessage: \"Each update must have a row data, column name, and value.\",\n\t\t\t\t},\n\t\t\t),\n\t\t)\n\t\t.min(1, \"At least one update is required\"),\n});\n\nexport type UpdateRecordsSchemaType = z.infer<typeof updateRecordsSchema>;\n","export * from \"./add-column.types.js\";\nexport * from \"./add-record.types.js\"; // done\nexport * from \"./ai-provider.types.js\";\nexport * from \"./alter-column.types.js\";\nexport * from \"./api-response.types.js\";\nexport * from \"./bulk-insert-records.type.js\";\nexport * from \"./chat.types.js\"; // done\nexport * from \"./cmd-args.types.js\"; // done\nexport * from \"./column.type.js\";\nexport * from \"./column-info.types.js\";\nexport * from \"./create-table.types.js\"; // done\nexport * from \"./database.types.js\"; // done\nexport * from \"./database-engines.types.js\";\nexport * from \"./database-list.types.js\"; // done\nexport * from \"./database-schema.type.js\"; // done\nexport * from \"./delete-column.types.js\"; // done\nexport * from \"./delete-record.types.js\"; // done\nexport * from \"./delete-table.types.js\"; // done\nexport * from \"./execute-query.types.js\"; // done\nexport * from \"./export-table.types.js\";\nexport * from \"./key-browser.types.js\";\nexport * from \"./rate-limit-response.type.js\";\nexport * from \"./rename-column.types.js\";\nexport * from \"./rename-table.types.js\";\nexport * from \"./table-data.types.js\"; // done\nexport * from \"./table-info.type.js\"; // done\nexport * from \"./table-schema.types.js\"; // done\nexport * from \"./update-recors.types.js\"; // done\n","import { DATABASE_ENGINES, dbTypeFromProtocol } from \"@db-studio/shared/types\";\n\n/** Wire-compatible aliases the drivers don't understand, with the alias engine's own default port. */\nexport const DRIVER_ALIASES: Record<string, { driverScheme: string; defaultPort: number }> = {\n\tcockroachdb: { driverScheme: \"postgresql\", defaultPort: 26257 },\n\tmariadb: { driverScheme: \"mysql\", defaultPort: 3306 },\n\ttidb: { driverScheme: \"mysql\", defaultPort: 4000 },\n};\n\nexport const defaultPortFor = (url: URL): number => {\n\tconst scheme = url.protocol.replace(\":\", \"\");\n\tconst dbType = dbTypeFromProtocol(scheme);\n\treturn (\n\t\tDRIVER_ALIASES[scheme]?.defaultPort ??\n\t\t(dbType && DATABASE_ENGINES[dbType].defaultPort) ??\n\t\t5432\n\t);\n};\n\n/**\n * Rewrite a wire-compatible alias (e.g. `cockroachdb://`) to the scheme its driver\n * understands, pinning the alias's default port so the driver does not substitute its own.\n */\nexport const toDriverUrl = (databaseUrl: string): string => {\n\tconst url = new URL(databaseUrl);\n\tconst alias = DRIVER_ALIASES[url.protocol.replace(\":\", \"\")];\n\tif (!alias) return databaseUrl;\n\turl.port ||= String(alias.defaultPort);\n\turl.protocol = alias.driverScheme;\n\treturn url.toString();\n};\n\n/**\n * Parse DATABASE_URL to extract host and port\n */\nexport function parseDatabaseUrl(databaseUrl = process.env.DATABASE_URL): {\n\thost: string;\n\tport: number;\n} {\n\tif (!databaseUrl) {\n\t\treturn { host: \"localhost\", port: 5432 };\n\t}\n\n\ttry {\n\t\tconst url = new URL(databaseUrl);\n\t\treturn {\n\t\t\thost: url.hostname || \"localhost\",\n\t\t\tport: Number.parseInt(url.port, 10) || defaultPortFor(url),\n\t\t};\n\t} catch (error) {\n\t\tconsole.error(\"Failed to parse DATABASE_URL:\", error);\n\t\treturn { host: \"localhost\", port: 5432 };\n\t}\n}\n","{\n \"name\": \"db-studio\",\n \"type\": \"module\",\n \"version\": \"1.16.0\",\n \"description\": \"Modern database client for PostgreSQL with spreadsheet-like grid, AI-powered SQL assistance, ER diagrams, fast data browsing and editing. CLI tool, upcoming desktop & web versions.\",\n \"keywords\": [\n \"database client\",\n \"database gui\",\n \"database browser\",\n \"sql client\",\n \"sql editor\",\n \"query tool\",\n \"table editor\",\n \"data editor\",\n \"postgres\",\n \"postgresql\",\n \"postgresql client\",\n \"postgresql gui\",\n \"pgadmin alternative\",\n \"mysql\",\n \"mysql client\",\n \"ai sql\",\n \"er diagram\",\n \"database management\",\n \"database studio\"\n ],\n \"author\": \"Hüsam 🥑 <husam@ql3.dev>\",\n \"homepage\": \"https://dbstudio.sh\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/husamql3/db-studio.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/husamql3/db-studio/issues\"\n },\n \"license\": \"Apache-2.0\",\n \"bin\": {\n \"db-studio\": \"./dist/index.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"dev\": \"portless run\",\n \"dev:app\": \"NODE_ENV=development tsx watch src/index.ts\",\n \"build\": \"tsup --minify\",\n \"prepack\": \"cd ../web && bun run build && cd ../server && bun run build\",\n \"start\": \"sh -c 'APP_PORT=${PORT:-3333}; portless proxy start >/dev/null && portless alias db-studio \\\"$APP_PORT\\\" --force >/dev/null && HOST=127.0.0.1 PORT=\\\"$APP_PORT\\\" DB_STUDIO_SERVER_URL=https://db-studio.localhost node dist/index.js'\",\n \"format\": \"biome check --write --unsafe\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"e2e\": \"tsx e2e/contract.ts\"\n },\n \"portless\": {\n \"name\": \"api.db-studio\",\n \"script\": \"dev:app\"\n },\n \"dependencies\": {\n \"@clack/prompts\": \"^1.0.1\",\n \"@clickhouse/client\": \"^1.24.0\",\n \"@duckdb/node-api\": \"^1.5.6-r.1\",\n \"@hono/node-server\": \"^2.0.0\",\n \"@hono/zod-validator\": \"^0.9.0\",\n \"@libsql/client\": \"^0.18.0\",\n \"@sentry/node\": \"^10.73.0\",\n \"commander\": \"^15.0.0\",\n \"dotenv\": \"^18.0.0\",\n \"hono\": \"^4.10.4\",\n \"ioredis\": \"^6.0.0\",\n \"mongodb\": \"^7.1.1\",\n \"mssql\": \"^12.2.0\",\n \"mysql2\": \"^3.18.2\",\n \"open\": \"^11.0.0\",\n \"oracledb\": \"^7.0.1\",\n \"pg\": \"^8.13.1\",\n \"picocolors\": \"^1.1.1\",\n \"posthog-node\": \"^5.20.0\",\n \"xlsx\": \"^0.18.5\",\n \"zod\": \"^4.2.1\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.2.6\",\n \"@db-studio/shared\": \"workspace:*\",\n \"@sentry/esbuild-plugin\": \"^5.4.0\",\n \"@types/mssql\": \"^12.3.0\",\n \"@types/node\": \"^26.0.0\",\n \"@types/oracledb\": \"^7.0.3\",\n \"@types/pg\": \"^8.16.0\",\n \"@vitest/coverage-v8\": \"^5.0.0\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.7.1\",\n \"typescript\": \"^7.0.2\",\n \"vitest\": \"^5.0.0\"\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir, platform } from \"node:os\";\nimport path from \"node:path\";\nimport { DATABASE_TYPES, type DatabaseTypeSchema } from \"@db-studio/shared/types\";\nimport * as Sentry from \"@sentry/node\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { PostHog } from \"posthog-node\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\ntype DurationBucket = \"under_100ms\" | \"100ms_1s\" | \"1s_5s\" | \"over_5s\";\ntype Outcome = \"success\" | \"client_error\" | \"server_error\";\n\ntype TelemetryState = {\n\tinstallationId: string;\n\tenabled: boolean;\n\tlastActiveAt?: string;\n};\n\ntype ServerEvent =\n\t| { event: \"installation_active\"; properties: { runtime: string; os: string } }\n\t| {\n\t\t\tevent: \"server_operation\";\n\t\t\tproperties: {\n\t\t\t\toperation: string;\n\t\t\t\tmethod: string;\n\t\t\t\toutcome: Outcome;\n\t\t\t\tduration_bucket: DurationBucket;\n\t\t\t\tdb_type?: DatabaseTypeSchema;\n\t\t\t};\n\t };\n\nconst isTestOrDevelopment = () =>\n\tprocess.env.NODE_ENV === \"test\" || process.env.NODE_ENV === \"development\";\n\nconst telemetryStatePath = () => {\n\tconst base =\n\t\tprocess.env.DB_STUDIO_DATA_DIR ??\n\t\tprocess.env.XDG_STATE_HOME ??\n\t\t(process.platform === \"win32\"\n\t\t\t? process.env.LOCALAPPDATA\n\t\t\t: path.join(homedir(), \".local\", \"state\"));\n\treturn path.join(base || path.join(homedir(), \".db-studio\"), \"db-studio\", \"telemetry.json\");\n};\n\nconst writeState = (value: TelemetryState): void => {\n\ttry {\n\t\tconst file = telemetryStatePath();\n\t\tmkdirSync(path.dirname(file), { recursive: true });\n\t\twriteFileSync(file, JSON.stringify(value), { encoding: \"utf8\", mode: 0o600 });\n\t} catch {\n\t\t// Telemetry persistence is best-effort and cannot affect the product.\n\t}\n};\n\nconst createState = (): TelemetryState => ({ installationId: randomUUID(), enabled: true });\n\nconst readState = (): TelemetryState => {\n\tconst file = telemetryStatePath();\n\ttry {\n\t\tif (existsSync(file)) {\n\t\t\tconst value = JSON.parse(readFileSync(file, \"utf8\")) as Partial<TelemetryState>;\n\t\t\tif (typeof value.installationId === \"string\" && typeof value.enabled === \"boolean\") {\n\t\t\t\treturn {\n\t\t\t\t\tinstallationId: value.installationId,\n\t\t\t\t\tenabled: value.enabled,\n\t\t\t\t\tlastActiveAt:\n\t\t\t\t\t\ttypeof value.lastActiveAt === \"string\" ? value.lastActiveAt : undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// A damaged local telemetry file must never prevent DB Studio from starting.\n\t}\n\tconst value = createState();\n\twriteState(value);\n\treturn value;\n};\n\nlet state: TelemetryState | undefined;\nlet posthog: PostHog | undefined;\nconst OFFICIAL_SENTRY_DSN =\n\t\"https://a1e890d1105f1f27fcb1dbead71c30dd@o4509725125181440.ingest.de.sentry.io/4512040493383760\";\nconst OFFICIAL_POSTHOG_KEY = \"phc_nxaQk54MWAehmL72J4gjVbrQCpbSTedMyHn3PvFxAhkd\";\nconst currentState = (): TelemetryState => (state ??= readState());\n\nexport const isTelemetryEnabled = (): boolean =>\n\t!isTestOrDevelopment() && process.env.DB_STUDIO_TELEMETRY !== \"0\" && currentState().enabled;\n\nexport const getTelemetryConfig = () => ({\n\tenabled: isTelemetryEnabled(),\n\tinstallationId: currentState().installationId,\n\tappVersion: packageJson.version,\n});\n\nexport const setTelemetryEnabled = (enabled: boolean): void => {\n\tstate = { ...currentState(), enabled };\n\twriteState(state);\n\tif (enabled) {\n\t\tvoid posthog?.enable();\n\t\tinitServerObservability();\n\t} else {\n\t\tvoid posthog?.disable();\n\t\tvoid Sentry.close(500);\n\t}\n};\n\nexport const resetTelemetryId = (): string => {\n\tstate = { ...currentState(), installationId: randomUUID(), lastActiveAt: undefined };\n\twriteState(state);\n\treturn state.installationId;\n};\n\nexport const durationBucket = (durationMs: number): DurationBucket => {\n\tif (durationMs < 100) return \"under_100ms\";\n\tif (durationMs < 1_000) return \"100ms_1s\";\n\tif (durationMs < 5_000) return \"1s_5s\";\n\treturn \"over_5s\";\n};\n\nexport const outcomeForStatus = (status: number): Outcome => {\n\tif (status >= 500) return \"server_error\";\n\tif (status >= 400) return \"client_error\";\n\treturn \"success\";\n};\n\nconst DB_TYPE_PATH = new RegExp(`^/api/(${DATABASE_TYPES.join(\"|\")})(?=/|$)`);\n\nexport const operationForRequest = (method: string, pathname: string): string => {\n\tconst pathWithoutType = pathname.replace(DB_TYPE_PATH, \"/api\");\n\tconst rules: Array<[RegExp, string]> = [\n\t\t[/^\\/api\\/databases(?:\\/|$)/, \"databases\"],\n\t\t[/^\\/api\\/tables(?:\\/|$)/, \"tables\"],\n\t\t[/^\\/api\\/records(?:\\/|$)/, \"records\"],\n\t\t[/^\\/api\\/query(?:\\/|$)/, \"query\"],\n\t\t[/^\\/api\\/keys(?:\\/|$)/, \"keys\"],\n\t\t[/^\\/api\\/chat(?:\\/|$)/, \"chat\"],\n\t];\n\tconst resource = rules.find(([pattern]) => pattern.test(pathWithoutType))?.[1] ?? \"other\";\n\treturn `${method.toLowerCase()}_${resource}`;\n};\n\nexport const databaseTypeForRequest = (pathname: string): DatabaseTypeSchema | undefined =>\n\tpathname.match(DB_TYPE_PATH)?.[1] as DatabaseTypeSchema | undefined;\n\nexport const initServerObservability = (): void => {\n\tif (!isTelemetryEnabled()) return;\n\tconst sentryDsn = process.env.DB_STUDIO_SENTRY_DSN ?? OFFICIAL_SENTRY_DSN;\n\tif (\n\t\tsentryDsn &&\n\t\t(!Sentry.isInitialized() || Sentry.getClient()?.getOptions().enabled === false)\n\t) {\n\t\tSentry.init({\n\t\t\tdsn: sentryDsn,\n\t\t\tenvironment: process.env.NODE_ENV ?? \"production\",\n\t\t\trelease: `db-studio@${packageJson.version}`,\n\t\t\ttracesSampleRate: 0.1,\n\t\t\tsendDefaultPii: false,\n\t\t\tdefaultIntegrations: false,\n\t\t\tbeforeSend(event) {\n\t\t\t\tdelete event.request;\n\t\t\t\tdelete event.user;\n\t\t\t\tdelete event.breadcrumbs;\n\t\t\t\treturn event;\n\t\t\t},\n\t\t\tbeforeSendSpan(span) {\n\t\t\t\treturn {\n\t\t\t\t\t...span,\n\t\t\t\t\tdata: Object.fromEntries(\n\t\t\t\t\t\tObject.entries(span.data ?? {}).filter(([key]) => key.startsWith(\"db_studio.\")),\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t},\n\t\t});\n\t}\n\n\tconst posthogKey = process.env.DB_STUDIO_POSTHOG_KEY ?? OFFICIAL_POSTHOG_KEY;\n\tif (posthogKey && !posthog) {\n\t\tposthog = new PostHog(posthogKey, {\n\t\t\thost: process.env.DB_STUDIO_POSTHOG_HOST ?? \"https://eu.i.posthog.com\",\n\t\t\tflushAt: 20,\n\t\t\tflushInterval: 10_000,\n\t\t\trequestTimeout: 2_000,\n\t\t});\n\t}\n};\n\nexport const captureServerEvent = (event: ServerEvent): void => {\n\tif (!isTelemetryEnabled() || !posthog) return;\n\tposthog.capture({\n\t\tdistinctId: currentState().installationId,\n\t\tevent: event.event,\n\t\tproperties: {\n\t\t\t...event.properties,\n\t\t\tsource: \"server\",\n\t\t\tapp_version: packageJson.version,\n\t\t\t$geoip_disable: false,\n\t\t},\n\t});\n};\n\nexport const captureInstallationActive = (): void => {\n\tif (!isTelemetryEnabled()) return;\n\tconst current = currentState();\n\tconst lastActive = current.lastActiveAt ? Date.parse(current.lastActiveAt) : 0;\n\tif (Date.now() - lastActive < 86_400_000) return;\n\tstate = { ...current, lastActiveAt: new Date().toISOString() };\n\twriteState(state);\n\tcaptureServerEvent({\n\t\tevent: \"installation_active\",\n\t\tproperties: { runtime: `node-${process.versions.node.split(\".\")[0]}`, os: platform() },\n\t});\n};\n\nconst safeErrorType = (error: unknown): string => {\n\tconst name =\n\t\terror instanceof HTTPException\n\t\t\t? \"HTTPException\"\n\t\t\t: error instanceof Error\n\t\t\t\t? error.name\n\t\t\t\t: \"Error\";\n\treturn /^[A-Za-z][A-Za-z0-9]{0,49}$/.test(name) ? name : \"Error\";\n};\n\nconst safeErrorCode = (error: unknown): string | undefined => {\n\tif (!(error instanceof Error)) return undefined;\n\tconst { code, errno } = error as Error & { code?: unknown; errno?: unknown };\n\tif (typeof code === \"string\" && /^[A-Z0-9_]{2,32}$/.test(code)) return code;\n\tif (typeof errno === \"number\" && Number.isSafeInteger(errno)) return String(errno);\n\treturn undefined;\n};\n\nconst sanitizedError = (error: unknown, errorType: string): Error => {\n\tconst sanitized = new Error(\"Server operation failed\");\n\tsanitized.name = errorType;\n\tif (error instanceof Error && error.stack) {\n\t\tconst frames = error.stack\n\t\t\t.split(\"\\n\")\n\t\t\t.slice(1)\n\t\t\t.filter((line) => /^\\s*at\\s/.test(line));\n\t\tsanitized.stack = [`${errorType}: Server operation failed`, ...frames].join(\"\\n\");\n\t}\n\treturn sanitized;\n};\n\nexport const captureServerError = (\n\terror: unknown,\n\t{\n\t\toperation,\n\t\tstatus,\n\t\tdbType,\n\t}: { operation: string; status: number; dbType?: DatabaseTypeSchema },\n): void => {\n\tif (!isTelemetryEnabled() || status < 500) return;\n\tconst diagnosticError = error instanceof HTTPException && error.cause ? error.cause : error;\n\tconst errorType = safeErrorType(diagnosticError);\n\tconst errorCode = safeErrorCode(diagnosticError);\n\tSentry.captureException(sanitizedError(diagnosticError, errorType), {\n\t\ttags: {\n\t\t\toperation,\n\t\t\tsource: \"server\",\n\t\t\trelease: packageJson.version,\n\t\t\tstatus: String(status),\n\t\t\t...(dbType ? { db_type: dbType } : {}),\n\t\t\terror_type: errorType,\n\t\t\t...(errorCode ? { error_code: errorCode } : {}),\n\t\t},\n\t\tfingerprint: [operation, String(status), errorType, errorCode ?? \"unknown\"],\n\t});\n};\n\nexport const startServerSpan = <T>(\n\toperation: string,\n\tdbType: DatabaseTypeSchema | undefined,\n\tcallback: () => T,\n): T =>\n\tSentry.startSpan(\n\t\t{\n\t\t\tname: operation,\n\t\t\top: \"http.server\",\n\t\t\tattributes: {\n\t\t\t\t\"db_studio.operation\": operation,\n\t\t\t\t...(dbType ? { \"db_studio.db_type\": dbType } : {}),\n\t\t\t},\n\t\t},\n\t\tcallback,\n\t);\n\nexport const writeOperationalLog = (\n\tlevel: \"info\" | \"error\",\n\tevent: string,\n\tfields: Record<string, string | number | undefined>,\n): void => {\n\tconst safeFields = Object.fromEntries(\n\t\tObject.entries(fields).filter(([, value]) => value !== undefined),\n\t);\n\tprocess.stderr.write(\n\t\t`${JSON.stringify({ timestamp: new Date().toISOString(), level, event, ...safeFields })}\\n`,\n\t);\n};\n","import { resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport {\n\ttype ClickHouseClient,\n\tClickHouseLogLevel,\n\tcreateClient as createClickhouseClient,\n} from \"@clickhouse/client\";\nimport {\n\tDATABASE_ENGINES,\n\ttype DatabaseTypeSchema,\n\tdbTypeFromProtocol,\n} from \"@db-studio/shared/types\";\nimport { type DuckDBConnection, DuckDBInstance } from \"@duckdb/node-api\";\nimport {\n\tcreateClient as createLibsqlClient,\n\ttype Client as LibsqlClient,\n} from \"@libsql/client\";\nimport { Redis, type RedisOptions } from \"ioredis\";\nimport { MongoClient, ObjectId } from \"mongodb\";\nimport type { ConnectionPool as MssqlPool } from \"mssql\";\nimport mssql from \"mssql\";\nimport type { Pool as MysqlPool } from \"mysql2/promise\";\nimport { createPool as createMysqlPool } from \"mysql2/promise\";\nimport oracledb from \"oracledb\";\nimport { Pool, type PoolConfig } from \"pg\";\nimport { toDriverUrl } from \"@/utils/parse-database-url.js\";\n\n/**\n * DatabaseManager - Manages multiple database connection pools for PostgreSQL, MySQL, SQL Server, Oracle, MongoDB, SQLite / libSQL, DuckDB and Redis\n */\nclass DatabaseManager {\n\tprivate pgPools: Map<string, Pool> = new Map();\n\tprivate mysqlPools: Map<string, MysqlPool> = new Map();\n\tprivate mssqlPools: Map<string, MssqlPool> = new Map();\n\tprivate mongoClient: MongoClient | null = null;\n\tprivate sqliteClient: Promise<LibsqlClient> | null = null;\n\tprivate duckdb: Promise<{ instance: DuckDBInstance; connection: DuckDBConnection }> | null =\n\t\tnull;\n\tprivate duckdbQueue: Promise<unknown> = Promise.resolve();\n\tprivate oraclePool: Promise<oracledb.Pool> | null = null;\n\tprivate redisClients: Map<number, Redis> = new Map();\n\tprivate redisClusterChecked = false;\n\tprivate clickhouseClients: Map<string, ClickHouseClient> = new Map();\n\tprivate baseConfig: {\n\t\turl: string;\n\t\thost: string;\n\t\tport: number;\n\t\tuser: string;\n\t\tpassword: string;\n\t\tdbType: DatabaseTypeSchema;\n\t} | null = null;\n\tprivate initError: Error | null = null;\n\n\tconstructor() {\n\t\ttry {\n\t\t\tthis.initializeBaseConfig();\n\t\t} catch (e) {\n\t\t\tthis.initError = e instanceof Error ? e : new Error(String(e));\n\t\t\tconsole.error(`❌ Database configuration error: ${this.initError.message}`);\n\t\t}\n\t}\n\n\t/**\n\t * Detect database type from URL protocol\n\t */\n\tprivate detectDbType(url: URL): DatabaseTypeSchema {\n\t\tconst protocol = url.protocol.replace(\":\", \"\");\n\t\tconst dbType = dbTypeFromProtocol(protocol);\n\t\tif (dbType) return dbType;\n\t\tconst supported = Object.values(DATABASE_ENGINES)\n\t\t\t.map(({ label, protocols }) => `${label} (${protocols.join(\", \")})`)\n\t\t\t.join(\", \");\n\t\tthrow new Error(`Unsupported database type: ${protocol}. Supported types: ${supported}.`);\n\t}\n\n\t/**\n\t * Parse DATABASE_URL and extract connection details\n\t */\n\tprivate initializeBaseConfig() {\n\t\tconst databaseUrl = process.env.DATABASE_URL;\n\t\tif (!databaseUrl) {\n\t\t\tthrow new Error(\"DATABASE_URL is not set. Please provide a database connection string.\");\n\t\t}\n\n\t\t// File-based engines (sqlite://, duckdb://) carry a file path that doesn't parse well as a standard URL\n\t\tconst fileDbType = dbTypeFromProtocol(databaseUrl.split(\"://\")[0]);\n\t\tif (fileDbType && DATABASE_ENGINES[fileDbType].defaultPort === null) {\n\t\t\tthis.baseConfig = {\n\t\t\t\turl: databaseUrl,\n\t\t\t\thost: \"localhost\",\n\t\t\t\tport: 0,\n\t\t\t\tuser: \"\",\n\t\t\t\tpassword: \"\",\n\t\t\t\tdbType: fileDbType,\n\t\t\t};\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst driverUrl = toDriverUrl(databaseUrl);\n\t\t\tconst url = new URL(driverUrl);\n\t\t\tconst detectedType = this.detectDbType(url);\n\t\t\tthis.baseConfig = {\n\t\t\t\turl: driverUrl,\n\t\t\t\thost: url.hostname,\n\t\t\t\tport:\n\t\t\t\t\tNumber.parseInt(url.port, 10) || (DATABASE_ENGINES[detectedType].defaultPort ?? 0),\n\t\t\t\tuser: url.username,\n\t\t\t\tpassword: url.password,\n\t\t\t\tdbType: detectedType,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthrow new Error(error instanceof Error ? error.message : String(error));\n\t\t}\n\t}\n\n\t/**\n\t * Get the detected database type\n\t */\n\tgetDbType(): DatabaseTypeSchema {\n\t\tif (this.initError) throw this.initError;\n\t\tif (!this.baseConfig) {\n\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t}\n\t\treturn this.baseConfig.dbType;\n\t}\n\n\t/**\n\t * Build a connection string for the specified database\n\t */\n\tbuildConnectionString(database?: string): string {\n\t\tif (this.initError) throw this.initError;\n\t\tif (!this.baseConfig) {\n\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t}\n\n\t\t// File-based databases: the URL is already the full connection string\n\t\tif (DATABASE_ENGINES[this.baseConfig.dbType].defaultPort === null) {\n\t\t\treturn this.baseConfig.url;\n\t\t}\n\n\t\tif (!database) {\n\t\t\tconst url = new URL(this.baseConfig.url);\n\t\t\tdatabase = url.pathname.slice(1);\n\t\t}\n\n\t\ttry {\n\t\t\tconst url = new URL(this.baseConfig.url);\n\t\t\turl.pathname = `/${database}`;\n\t\t\treturn url.toString();\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to build connection string for database \"${database}\": ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Get or create the libSQL client for a local SQLite file or a remote libSQL / Turso database\n\t */\n\tgetSqliteClient(): Promise<LibsqlClient> {\n\t\tif (!this.baseConfig || this.baseConfig.dbType !== \"sqlite\") {\n\t\t\tthrow new Error(\"DATABASE_URL is not a sqlite:// or libsql:// connection\");\n\t\t}\n\t\tconst { url } = this.baseConfig;\n\t\tthis.sqliteClient ??= this.openSqliteClient(url).catch((error: unknown) => {\n\t\t\tthis.sqliteClient = null;\n\t\t\tthrow error;\n\t\t});\n\t\treturn this.sqliteClient;\n\t}\n\n\tprivate async openSqliteClient(url: string): Promise<LibsqlClient> {\n\t\t// sqlite:///abs/path.db (or a relative sqlite://./path.db) becomes a file: URL and\n\t\t// sqlite://:memory: stays in memory; libsql:// URLs keep their authToken and tls query params.\n\t\tconst sqlitePath = url.startsWith(\"sqlite://\") ? url.slice(\"sqlite://\".length) : null;\n\t\tconst libsqlUrl =\n\t\t\tsqlitePath === null\n\t\t\t\t? url\n\t\t\t\t: sqlitePath === \":memory:\"\n\t\t\t\t\t? sqlitePath\n\t\t\t\t\t: pathToFileURL(resolve(sqlitePath)).href;\n\t\tconst client = createLibsqlClient({ url: libsqlUrl, intMode: \"bigint\" });\n\t\tif (client.protocol === \"file\") {\n\t\t\tawait client.execute(\"PRAGMA journal_mode = WAL\");\n\t\t\tawait client.execute(\"PRAGMA foreign_keys = ON\");\n\t\t}\n\t\treturn client;\n\t}\n\n\t/**\n\t * Close the libSQL client\n\t */\n\tasync closeSqliteClient(): Promise<void> {\n\t\tconst client = this.sqliteClient;\n\t\tthis.sqliteClient = null;\n\t\tif (client) (await client.catch(() => null))?.close();\n\t}\n\n\t/**\n\t * Run `fn` with the DuckDB connection, opening the file on first use. DuckDB holds one\n\t * connection per file, so calls are serialized: a transaction opened inside `fn` cannot\n\t * interleave with statements from a concurrent request.\n\t */\n\twithDuckdbConnection<T>(fn: (connection: DuckDBConnection) => Promise<T>): Promise<T> {\n\t\tconst run = this.duckdbQueue.then(async () => fn((await this.openDuckdb()).connection));\n\t\tthis.duckdbQueue = run.catch(() => {});\n\t\treturn run;\n\t}\n\n\tprivate openDuckdb() {\n\t\tif (!this.baseConfig || this.baseConfig.dbType !== \"duckdb\") {\n\t\t\tthrow new Error(\"DATABASE_URL is not a duckdb:// connection\");\n\t\t}\n\t\tif (!this.duckdb) {\n\t\t\tconst filePath = this.baseConfig.url.replace(/^duckdb:\\/\\//, \"\");\n\t\t\tthis.duckdb = (async () => {\n\t\t\t\ttry {\n\t\t\t\t\t// Checkpoint on every commit. DuckDB (1.4 and 1.5) cannot replay an ALTER TABLE on a\n\t\t\t\t\t// table with a nextval() default from the WAL, so a process that exits before the\n\t\t\t\t\t// next checkpoint leaves a file that no longer opens.\n\t\t\t\t\tconst instance = await DuckDBInstance.create(filePath, {\n\t\t\t\t\t\tcheckpoint_threshold: \"0b\",\n\t\t\t\t\t});\n\t\t\t\t\treturn { instance, connection: await instance.connect() };\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthis.duckdb = null;\n\t\t\t\t\tconst message = e instanceof Error ? e.message : String(e);\n\t\t\t\t\tif (message.includes(\"Could not set lock on file\")) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`The DuckDB file \"${filePath}\" is locked by another process. Close the other program using it and try again. (${message})`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t})();\n\t\t}\n\t\treturn this.duckdb;\n\t}\n\n\tasync closeDuckdb(): Promise<void> {\n\t\tconst open = this.duckdb;\n\t\tthis.duckdb = null;\n\t\tconst handle = await open?.catch(() => null);\n\t\thandle?.connection.closeSync();\n\t\thandle?.instance.closeSync();\n\t}\n\n\t/**\n\t * Get or create the Oracle pool for the service in the URL (`oracle://user:pass@host:1521/SERVICE`).\n\t * One pool per process: an Oracle service is a single database, so `db` never selects another pool.\n\t */\n\tgetOraclePool(): Promise<oracledb.Pool> {\n\t\tif (!this.baseConfig || this.baseConfig.dbType !== \"oracle\") {\n\t\t\tthrow new Error(\"DATABASE_URL is not an oracle:// connection\");\n\t\t}\n\t\tconst { url, host, port, user, password } = this.baseConfig;\n\t\tconst service = decodeURIComponent(new URL(url).pathname.slice(1));\n\t\tthis.oraclePool ??= oracledb\n\t\t\t.createPool({\n\t\t\t\tuser: decodeURIComponent(user),\n\t\t\t\tpassword: decodeURIComponent(password),\n\t\t\t\tconnectString: `${host}:${port}/${service}`,\n\t\t\t\tpoolMin: 0,\n\t\t\t\tpoolMax: 10,\n\t\t\t\tconnectTimeout: 5,\n\t\t\t\t// LTZ values are projected in the session zone; pin it so pooled connections agree.\n\t\t\t\tsessionCallback: (connection, _tag, done) => {\n\t\t\t\t\tconnection\n\t\t\t\t\t\t.execute(\"ALTER SESSION SET TIME_ZONE = '+00:00'\")\n\t\t\t\t\t\t.then(() =>\n\t\t\t\t\t\t\tconnection.execute(\n\t\t\t\t\t\t\t\t`ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD\"T\"HH24:MI:SS' NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD\"T\"HH24:MI:SS.FF9' NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD\"T\"HH24:MI:SS.FF9TZH:TZM' NLS_NUMERIC_CHARACTERS = '.,'`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.then(() => done(), done);\n\t\t\t\t},\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tthis.oraclePool = null;\n\t\t\t\tthrow error;\n\t\t\t});\n\t\treturn this.oraclePool;\n\t}\n\n\tasync closeOraclePool(): Promise<void> {\n\t\tconst pool = this.oraclePool;\n\t\tthis.oraclePool = null;\n\t\tawait (await pool?.catch(() => null))?.close(0);\n\t}\n\n\t/**\n\t * Get or create a PostgreSQL connection pool for the specified database\n\t */\n\tgetPgPool(database?: string): Pool {\n\t\tconst connectionString = this.buildConnectionString(database);\n\n\t\tif (!this.pgPools.has(connectionString)) {\n\t\t\tconst poolConfig: PoolConfig = {\n\t\t\t\tconnectionString,\n\t\t\t\tmax: 10,\n\t\t\t\tidleTimeoutMillis: 30000,\n\t\t\t\tconnectionTimeoutMillis: 2000,\n\t\t\t};\n\n\t\t\tconst pool = new Pool(poolConfig);\n\n\t\t\t// The tables list spans every user schema, but the SQL the adapters\n\t\t\t// build refers to tables by bare name, so a table outside \"public\" is\n\t\t\t// listed yet every query against it fails with \"relation does not\n\t\t\t// exist\". Widen search_path on each new connection.\n\t\t\t//\n\t\t\t// pg emits \"connect\" synchronously and hands the client straight to\n\t\t\t// the caller, so this must enqueue in one shot: awaiting a lookup\n\t\t\t// first would let the caller's query jump ahead of the SET. \"public\"\n\t\t\t// stays first so it keeps winning a name collision, as before. A\n\t\t\t// single set_config() rather than a DO block, because CockroachDB\n\t\t\t// does not run PL/pgSQL.\n\t\t\tpool.on(\"connect\", (client) => {\n\t\t\t\tclient\n\t\t\t\t\t.query(\n\t\t\t\t\t\t`SELECT set_config(\n\t\t\t\t\t\t\t'search_path',\n\t\t\t\t\t\t\tCOALESCE(\n\t\t\t\t\t\t\t\t'public, ' || string_agg(quote_ident(nspname), ', ' ORDER BY nspname),\n\t\t\t\t\t\t\t\tcurrent_setting('search_path')\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tfalse\n\t\t\t\t\t\t)\n\t\t\t\t\t\tFROM pg_namespace\n\t\t\t\t\t\tWHERE nspname NOT IN ('pg_catalog', 'information_schema', 'public', 'crdb_internal', 'pg_extension')\n\t\t\t\t\t\t\tAND nspname NOT LIKE 'pg_toast%'\n\t\t\t\t\t\t\tAND nspname NOT LIKE 'pg_temp%';`,\n\t\t\t\t\t)\n\t\t\t\t\t.catch((err: Error) => {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\t`Failed to widen search_path for \"${connectionString}\":`,\n\t\t\t\t\t\t\terr.message,\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t});\n\n\t\t\tpool.on(\"error\", (err) => {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`Unexpected error on PostgreSQL pool for \"${connectionString}\":`,\n\t\t\t\t\terr.message,\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tthis.pgPools.set(connectionString, pool);\n\t\t}\n\n\t\treturn this.pgPools.get(connectionString) ?? new Pool({ connectionString });\n\t}\n\n\t/**\n\t * Get or create a MySQL connection pool for the specified database\n\t */\n\tgetMysqlPool(database?: string): MysqlPool {\n\t\tif (!this.baseConfig) {\n\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t}\n\n\t\tconst connectionString = this.buildConnectionString(database);\n\n\t\tif (!this.mysqlPools.has(connectionString)) {\n\t\t\tconst url = new URL(connectionString);\n\t\t\tconst dbName = url.pathname.slice(1);\n\n\t\t\tconst pool = createMysqlPool({\n\t\t\t\thost: this.baseConfig.host,\n\t\t\t\tport: this.baseConfig.port,\n\t\t\t\tuser: this.baseConfig.user,\n\t\t\t\tpassword: this.baseConfig.password,\n\t\t\t\tdatabase: dbName || undefined,\n\t\t\t\twaitForConnections: true,\n\t\t\t\tconnectionLimit: 10,\n\t\t\t\tidleTimeout: 30000,\n\t\t\t\tconnectTimeout: 2000,\n\t\t\t\t// Enable multiple statements for raw query support\n\t\t\t\tmultipleStatements: false,\n\t\t\t});\n\n\t\t\tthis.mysqlPools.set(connectionString, pool);\n\t\t}\n\n\t\treturn this.mysqlPools.get(connectionString) as MysqlPool;\n\t}\n\n\t/**\n\t * Get or create a SQL Server connection pool for the specified database\n\t */\n\tasync getMssqlPool(database?: string): Promise<MssqlPool> {\n\t\tif (!this.baseConfig) {\n\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t}\n\n\t\tconst connectionString = this.buildConnectionString(database);\n\n\t\tif (!this.mssqlPools.has(connectionString)) {\n\t\t\tconst url = new URL(connectionString);\n\t\t\tconst dbName = url.pathname.slice(1);\n\n\t\t\tconst config: mssql.config = {\n\t\t\t\tserver: this.baseConfig.host,\n\t\t\t\tport: this.baseConfig.port,\n\t\t\t\tuser: this.baseConfig.user,\n\t\t\t\tpassword: this.baseConfig.password,\n\t\t\t\tdatabase: dbName || undefined,\n\t\t\t\toptions: {\n\t\t\t\t\tencrypt: false, // Use true for Azure\n\t\t\t\t\ttrustServerCertificate: true,\n\t\t\t\t\tenableArithAbort: true,\n\t\t\t\t\tconnectTimeout: 2000,\n\t\t\t\t},\n\t\t\t\tpool: {\n\t\t\t\t\tmax: 10,\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tidleTimeoutMillis: 30000,\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst pool = await new mssql.ConnectionPool(config).connect();\n\n\t\t\tpool.on(\"error\", (err) => {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`Unexpected error on SQL Server pool for \"${connectionString}\":`,\n\t\t\t\t\terr.message,\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tthis.mssqlPools.set(connectionString, pool);\n\t\t}\n\n\t\treturn this.mssqlPools.get(connectionString) as MssqlPool;\n\t}\n\n\t/**\n\t * Get or create a ClickHouse HTTP client for the specified database.\n\t * `clickhouse://` maps to http, `clickhouses://` to https (default port 8443).\n\t */\n\tgetClickhouseClient(database?: string): ClickHouseClient {\n\t\tconst url = new URL(this.buildConnectionString(database));\n\t\tconst dbName = decodeURIComponent(url.pathname.slice(1)) || \"default\";\n\n\t\tconst existing = this.clickhouseClients.get(dbName);\n\t\tif (existing) return existing;\n\n\t\tconst tls = url.protocol === \"clickhouses:\";\n\t\tconst client = createClickhouseClient({\n\t\t\turl: `${tls ? \"https\" : \"http\"}://${url.hostname}:${url.port || (tls ? 8443 : 8123)}`,\n\t\t\tusername: decodeURIComponent(url.username) || \"default\",\n\t\t\tpassword: decodeURIComponent(url.password),\n\t\t\tdatabase: dbName,\n\t\t\trequest_timeout: 30_000,\n\t\t\tclickhouse_settings: {\n\t\t\t\toutput_format_json_quote_64bit_integers: 1,\n\t\t\t\toutput_format_json_quote_decimals: 1,\n\t\t\t\twait_end_of_query: 1,\n\t\t\t},\n\t\t\t// Failures surface through the adapter's error mapping; the client's own log would duplicate them.\n\t\t\tlog: { level: ClickHouseLogLevel.OFF },\n\t\t});\n\t\tthis.clickhouseClients.set(dbName, client);\n\t\treturn client;\n\t}\n\n\t/**\n\t * Get the appropriate pool based on database type (legacy/PG-only helper)\n\t */\n\tgetPool(database?: string): Pool {\n\t\treturn this.getPgPool(database);\n\t}\n\n\t/**\n\t * Close a specific PostgreSQL pool by connection string\n\t */\n\tasync closePgPool(connectionString: string): Promise<void> {\n\t\tconst pool = this.pgPools.get(connectionString);\n\t\tif (pool) {\n\t\t\tawait pool.end();\n\t\t\tthis.pgPools.delete(connectionString);\n\t\t\tconsole.log(`Closed PostgreSQL connection pool for: ${connectionString}`);\n\t\t}\n\t}\n\n\t/**\n\t * Close a specific MySQL pool by connection string\n\t */\n\tasync closeMysqlPool(connectionString: string): Promise<void> {\n\t\tconst pool = this.mysqlPools.get(connectionString);\n\t\tif (pool) {\n\t\t\tawait pool.end();\n\t\t\tthis.mysqlPools.delete(connectionString);\n\t\t\tconsole.log(`Closed MySQL connection pool for: ${connectionString}`);\n\t\t}\n\t}\n\n\t/**\n\t * Close a specific SQL Server pool by connection string\n\t */\n\tasync closeMssqlPool(connectionString: string): Promise<void> {\n\t\tconst pool = this.mssqlPools.get(connectionString);\n\t\tif (pool) {\n\t\t\tawait pool.close();\n\t\t\tthis.mssqlPools.delete(connectionString);\n\t\t\tconsole.log(`Closed SQL Server connection pool for: ${connectionString}`);\n\t\t}\n\t}\n\n\t/**\n\t * Close a specific database pool by connection string (both types)\n\t */\n\tasync closePool(connectionString: string): Promise<void> {\n\t\tif (this.baseConfig?.dbType === \"sqlite\" && connectionString === this.baseConfig.url) {\n\t\t\tawait this.closeSqliteClient();\n\t\t\treturn;\n\t\t}\n\t\tif (this.baseConfig?.dbType === \"duckdb\" && connectionString === this.baseConfig.url) {\n\t\t\tawait this.closeDuckdb();\n\t\t\treturn;\n\t\t}\n\t\tif (this.baseConfig?.dbType === \"oracle\") {\n\t\t\tawait this.closeOraclePool();\n\t\t\treturn;\n\t\t}\n\t\tawait this.closePgPool(connectionString);\n\t\tawait this.closeMysqlPool(connectionString);\n\t\tawait this.closeMssqlPool(connectionString);\n\t}\n\n\t/**\n\t * Close a specific database pool by database name\n\t */\n\tasync closePoolByDatabase(database: string): Promise<void> {\n\t\tif (this.baseConfig?.dbType === \"sqlite\") {\n\t\t\tawait this.closeSqliteClient();\n\t\t\treturn;\n\t\t}\n\t\tif (this.baseConfig?.dbType === \"duckdb\") {\n\t\t\tawait this.closeDuckdb();\n\t\t\treturn;\n\t\t}\n\t\tif (this.baseConfig?.dbType === \"oracle\") {\n\t\t\tawait this.closeOraclePool();\n\t\t\treturn;\n\t\t}\n\t\tconst connectionString = this.buildConnectionString(database);\n\t\tawait this.closePool(connectionString);\n\t}\n\n\t/**\n\t * Get or create a MongoDB client\n\t */\n\tasync getMongoClient(): Promise<MongoClient> {\n\t\tif (!this.mongoClient) {\n\t\t\tif (!this.baseConfig) {\n\t\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t\t}\n\t\t\tconst nextClient = new MongoClient(this.baseConfig.url);\n\t\t\ttry {\n\t\t\t\tawait nextClient.connect();\n\t\t\t\tthis.mongoClient = nextClient;\n\t\t\t} catch (error) {\n\t\t\t\ttry {\n\t\t\t\t\tawait nextClient.close();\n\t\t\t\t} catch {\n\t\t\t\t\t// ignore close errors\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\treturn this.mongoClient;\n\t}\n\n\t/**\n\t * Get the MongoDB database name from the connection URL\n\t */\n\tgetMongoDbName(): string {\n\t\tif (!this.baseConfig) {\n\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t}\n\t\tconst raw = new URL(this.baseConfig.url).pathname.replace(/^\\/+|\\/+$/g, \"\");\n\t\ttry {\n\t\t\treturn decodeURIComponent(raw) || \"admin\";\n\t\t} catch {\n\t\t\t// Malformed percent-encoding — fall back to the literal path segment.\n\t\t\treturn raw || \"admin\";\n\t\t}\n\t}\n\n\t/**\n\t * Get a MongoDB database instance\n\t */\n\tasync getMongoDb(dbName?: string) {\n\t\tconst mongoClient = await this.getMongoClient();\n\t\treturn mongoClient.db(dbName ?? this.getMongoDbName());\n\t}\n\n\t/**\n\t * Get or create a Redis client for the specified logical DB index (0-15 by default)\n\t */\n\tasync getRedisClient(dbIndex?: number): Promise<Redis> {\n\t\tif (!this.baseConfig) {\n\t\t\tthrow new Error(\"Base configuration not initialized\");\n\t\t}\n\t\tif (this.baseConfig.dbType !== \"redis\") {\n\t\t\tthrow new Error(\"DATABASE_URL is not a redis:// connection\");\n\t\t}\n\n\t\tconst index = dbIndex ?? this.getRedisDefaultDb();\n\n\t\tconst existing = this.redisClients.get(index);\n\t\tif (existing) return existing;\n\n\t\tconst url = new URL(this.baseConfig.url);\n\t\tconst options: RedisOptions = {\n\t\t\thost: this.baseConfig.host,\n\t\t\tport: this.baseConfig.port,\n\t\t\tdb: index,\n\t\t\tlazyConnect: true,\n\t\t\tmaxRetriesPerRequest: 1,\n\t\t\tenableReadyCheck: true,\n\t\t\tconnectTimeout: 2000,\n\t\t};\n\t\tif (this.baseConfig.user) options.username = decodeURIComponent(this.baseConfig.user);\n\t\tif (this.baseConfig.password)\n\t\t\toptions.password = decodeURIComponent(this.baseConfig.password);\n\t\tif (url.protocol === \"rediss:\") options.tls = {};\n\n\t\tconst client = new Redis(options);\n\t\ttry {\n\t\t\tawait client.connect();\n\t\t\tif (!this.redisClusterChecked) {\n\t\t\t\tconst info = await client.info(\"server\");\n\t\t\t\tif (/^redis_mode:(cluster|sentinel)\\b/m.test(info)) {\n\t\t\t\t\tawait client.quit().catch(() => {});\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Redis cluster and Sentinel modes are not supported. Use a standalone redis:// connection.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst version = info.match(/^redis_version:([^\\r\\n]+)/m)?.[1];\n\t\t\t\tconst [major = 0, minor = 0] = version?.split(\".\").map(Number) ?? [];\n\t\t\t\tif (major < 6 || (major === 6 && minor < 2)) {\n\t\t\t\t\tawait client.quit().catch(() => {});\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Redis 6.2 or newer is required. Connected server reports ${version ?? \"an unknown version\"}.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis.redisClusterChecked = true;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait client.quit().catch(() => {});\n\t\t\tthrow error;\n\t\t}\n\n\t\tthis.redisClients.set(index, client);\n\t\treturn client;\n\t}\n\n\tasync getIsolatedRedisClient(dbIndex?: number): Promise<Redis> {\n\t\tconst client = (await this.getRedisClient(dbIndex)).duplicate();\n\t\tawait client.connect();\n\t\treturn client;\n\t}\n\n\t/**\n\t * Get the default Redis logical DB from the URL (e.g. redis://host/3 → 3)\n\t */\n\tgetRedisDefaultDb(): number {\n\t\tif (!this.baseConfig) return 0;\n\t\ttry {\n\t\t\tconst url = new URL(this.baseConfig.url);\n\t\t\tconst path = url.pathname.replace(/^\\//, \"\");\n\t\t\tif (!path) return 0;\n\t\t\tconst parsed = Number.parseInt(path, 10);\n\t\t\treturn Number.isFinite(parsed) ? parsed : 0;\n\t\t} catch {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\t/**\n\t * Close all database pools\n\t */\n\tasync closeAll(): Promise<void> {\n\t\tconst pgClosePromises = Array.from(this.pgPools.entries()).map(\n\t\t\tasync ([connectionString, pool]) => {\n\t\t\t\tawait pool.end();\n\t\t\t\tconsole.log(`Closed PostgreSQL pool for: ${connectionString}`);\n\t\t\t},\n\t\t);\n\t\tconst mysqlClosePromises = Array.from(this.mysqlPools.entries()).map(\n\t\t\tasync ([connectionString, pool]) => {\n\t\t\t\tawait pool.end();\n\t\t\t\tconsole.log(`Closed MySQL pool for: ${connectionString}`);\n\t\t\t},\n\t\t);\n\t\tconst mssqlClosePromises = Array.from(this.mssqlPools.entries()).map(\n\t\t\tasync ([connectionString, pool]) => {\n\t\t\t\tawait pool.close();\n\t\t\t\tconsole.log(`Closed SQL Server pool for: ${connectionString}`);\n\t\t\t},\n\t\t);\n\t\tawait Promise.all([...pgClosePromises, ...mysqlClosePromises, ...mssqlClosePromises]);\n\t\tthis.pgPools.clear();\n\t\tthis.mysqlPools.clear();\n\t\tthis.mssqlPools.clear();\n\t\tif (this.mongoClient) {\n\t\t\tawait this.mongoClient.close();\n\t\t\tthis.mongoClient = null;\n\t\t}\n\t\tawait this.closeSqliteClient();\n\t\tawait this.closeDuckdb();\n\t\tawait this.closeOraclePool();\n\t\tconst redisClosePromises = Array.from(this.redisClients.entries()).map(\n\t\t\tasync ([index, client]) => {\n\t\t\t\tawait client.quit().catch(() => {});\n\t\t\t\tconsole.log(`Closed Redis client for db=${index}`);\n\t\t\t},\n\t\t);\n\t\tawait Promise.all(redisClosePromises);\n\t\tthis.redisClients.clear();\n\t\tthis.redisClusterChecked = false;\n\t\tawait Promise.all(\n\t\t\tArray.from(this.clickhouseClients.values()).map((client) => client.close()),\n\t\t);\n\t\tthis.clickhouseClients.clear();\n\t}\n\n\t/**\n\t * Get all active pool connection strings\n\t */\n\tgetActivePools(): string[] {\n\t\treturn [\n\t\t\t...Array.from(this.pgPools.keys()),\n\t\t\t...Array.from(this.mysqlPools.keys()),\n\t\t\t...Array.from(this.mssqlPools.keys()),\n\t\t];\n\t}\n}\n\n// Singleton instance\nconst databaseManager = new DatabaseManager();\n\n/**\n * Get a PostgreSQL pool for the specified database\n */\nexport const getDbPool = (database?: string): Pool => {\n\treturn databaseManager.getPgPool(database);\n};\n\n/**\n * Get a MySQL pool for the specified database\n */\nexport const getMysqlPool = (database?: string): MysqlPool => {\n\treturn databaseManager.getMysqlPool(database);\n};\n\n/**\n * Get a SQL Server pool for the specified database\n */\nexport const getMssqlPool = async (database?: string): Promise<MssqlPool> => {\n\treturn databaseManager.getMssqlPool(database);\n};\n\n/**\n * Get a ClickHouse client for the specified database\n */\nexport const getClickhouseClient = (database?: string): ClickHouseClient => {\n\treturn databaseManager.getClickhouseClient(database);\n};\n\n/**\n * Get the detected database type from DATABASE_URL\n */\nexport const getDbType = (): DatabaseTypeSchema => {\n\treturn databaseManager.getDbType();\n};\n\n/**\n * Build a connection string for the specified database\n */\nconst _buildDbConnectionString = (database?: string): string => {\n\treturn databaseManager.buildConnectionString(database);\n};\n\n/**\n * Close a specific database pool by database name\n */\nconst _closeDbPool = async (database: string): Promise<void> => {\n\treturn databaseManager.closePoolByDatabase(database);\n};\n\n/**\n * Close a specific database pool by connection string\n */\nconst _closeDbPoolByConnectionString = async (connectionString: string): Promise<void> => {\n\treturn databaseManager.closePool(connectionString);\n};\n\n/**\n * Close all database pools\n */\nconst _closeAllDbPools = async (): Promise<void> => {\n\treturn databaseManager.closeAll();\n};\n\n/**\n * Get list of active pool connection strings\n */\nconst _getActivePools = (): string[] => {\n\treturn databaseManager.getActivePools();\n};\n\n/**\n * Get the libSQL client for the configured SQLite file or libSQL / Turso database\n */\nexport const getSqliteClient = (): Promise<LibsqlClient> => {\n\treturn databaseManager.getSqliteClient();\n};\n\n/**\n * Run `fn` with the DuckDB connection (single file, opened once, calls serialized)\n */\nexport const withDuckdbConnection = <T>(\n\tfn: (connection: DuckDBConnection) => Promise<T>,\n): Promise<T> => {\n\treturn databaseManager.withDuckdbConnection(fn);\n};\n\n/**\n * Get or create the Oracle pool for the configured service\n */\nexport const getOraclePool = (): Promise<oracledb.Pool> => {\n\treturn databaseManager.getOraclePool();\n};\n\n/**\n * Get or create the MongoDB client\n */\nexport const getMongoClient = (): Promise<MongoClient> => {\n\treturn databaseManager.getMongoClient();\n};\n\n/**\n * Get the MongoDB database name from the connection URL\n */\nexport const getMongoDbName = (): string => {\n\treturn databaseManager.getMongoDbName();\n};\n\n/**\n * Get a MongoDB database instance\n */\nexport const getMongoDb = (dbName?: string) => {\n\treturn databaseManager.getMongoDb(dbName);\n};\n\n/**\n * Get or create a Redis client for the specified logical DB index\n */\nexport const getRedisClient = (dbIndex?: number): Promise<Redis> => {\n\treturn databaseManager.getRedisClient(dbIndex);\n};\n\nexport const getIsolatedRedisClient = (dbIndex?: number): Promise<Redis> => {\n\treturn databaseManager.getIsolatedRedisClient(dbIndex);\n};\n\n/**\n * Get the default Redis logical DB index from the connection URL\n */\nexport const getRedisDefaultDb = (): number => {\n\treturn databaseManager.getRedisDefaultDb();\n};\n\nexport const isValidObjectId = (value: unknown): value is string => {\n\treturn typeof value === \"string\" && ObjectId.isValid(value);\n};\n\nexport const coerceObjectId = (value: unknown): unknown => {\n\tif (typeof value === \"string\" && ObjectId.isValid(value)) {\n\t\treturn new ObjectId(value);\n\t}\n\treturn value;\n};\n","import { DATABASE_ENGINES, type DatabaseTypeSchema } from \"@db-studio/shared/types\";\nimport {\n\tgetClickhouseClient,\n\tgetDbPool,\n\tgetDbType,\n\tgetMongoClient,\n\tgetMongoDbName,\n\tgetMssqlPool,\n\tgetMysqlPool,\n\tgetOraclePool,\n\tgetRedisClient,\n\tgetSqliteClient,\n\twithDuckdbConnection,\n} from \"@/db-manager.js\";\nimport { parseDatabaseUrl } from \"@/utils/parse-database-url.js\";\n\nconst STARTUP_TIMEOUT_MS = 2_000;\n\nconst withStartupTimeout = async <T>(operation: Promise<T>): Promise<T> => {\n\tlet timeout: ReturnType<typeof setTimeout> | undefined;\n\ttry {\n\t\treturn await Promise.race([\n\t\t\toperation,\n\t\t\tnew Promise<never>((_, reject) => {\n\t\t\t\ttimeout = setTimeout(\n\t\t\t\t\t() => reject(new Error(\"Database startup check timed out\")),\n\t\t\t\t\tSTARTUP_TIMEOUT_MS,\n\t\t\t\t);\n\t\t\t}),\n\t\t]);\n\t} finally {\n\t\tif (timeout) clearTimeout(timeout);\n\t}\n};\n\nexport type DatabaseConnectionDetails = {\n\ttype: DatabaseTypeSchema;\n\tname: string;\n\tdestination: string;\n};\n\nexport const getDatabaseConnectionDetails = (\n\tdatabaseUrl: string,\n): DatabaseConnectionDetails => {\n\tconst type = getDbType();\n\tconst { label: name, defaultPort } = DATABASE_ENGINES[type];\n\tif (databaseUrl.startsWith(\"sqlite://\")) return { type, name, destination: \"local file\" };\n\n\tif (defaultPort === null) return { type, name, destination: new URL(databaseUrl).host };\n\n\tconst { host, port } = parseDatabaseUrl(databaseUrl);\n\treturn { type, name, destination: `${host}:${port}` };\n};\n\nexport const checkDatabaseConnection = async (type: DatabaseTypeSchema): Promise<void> => {\n\tswitch (type) {\n\t\tcase \"pg\":\n\t\t\tawait withStartupTimeout(getDbPool().query(\"SELECT 1\"));\n\t\t\treturn;\n\t\tcase \"mysql\":\n\t\t\tawait getMysqlPool().query(\"SELECT 1\");\n\t\t\treturn;\n\t\tcase \"mssql\":\n\t\t\tawait (await getMssqlPool()).request().query(\"SELECT 1\");\n\t\t\treturn;\n\t\tcase \"mongodb\": {\n\t\t\tconst client = await getMongoClient();\n\t\t\tawait client.db(getMongoDbName()).command({ ping: 1 });\n\t\t\treturn;\n\t\t}\n\t\tcase \"sqlite\":\n\t\t\tawait withStartupTimeout(getSqliteClient().then((client) => client.execute(\"SELECT 1\")));\n\t\t\treturn;\n\t\tcase \"redis\":\n\t\t\tawait (await getRedisClient()).ping();\n\t\t\treturn;\n\t\tcase \"duckdb\":\n\t\t\tawait withDuckdbConnection((connection) => connection.run(\"SELECT 1\"));\n\t\t\treturn;\n\t\tcase \"oracle\": {\n\t\t\tconst connection = await (await getOraclePool()).getConnection();\n\t\t\tawait connection.execute(\"SELECT 1 FROM dual\").finally(() => connection.close());\n\t\t\treturn;\n\t\t}\n\n\t\tcase \"clickhouse\":\n\t\t\tawait withStartupTimeout(getClickhouseClient().query({ query: \"SELECT 1\" }));\n\t}\n};\n","import type { DatabaseTypeSchema } from \"@db-studio/shared/types/database.types.js\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { IDbAdapter } from \"./adapter.interface.js\";\nimport type { IKeyValueAdapter } from \"./key-value-adapter.interface.js\";\n\nexport class AdapterRegistry {\n\tprivate adapters = new Map<DatabaseTypeSchema, IDbAdapter>();\n\n\tregister(type: DatabaseTypeSchema, adapter: IDbAdapter): void {\n\t\tthis.adapters.set(type, adapter);\n\t}\n\n\tget(type: DatabaseTypeSchema): IDbAdapter {\n\t\tconst adapter = this.adapters.get(type);\n\t\tif (!adapter) {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: `Unsupported database type: \"${type}\". Supported types: ${this.getSupportedTypes().join(\", \")}`,\n\t\t\t});\n\t\t}\n\t\treturn adapter;\n\t}\n\n\thas(type: string): type is DatabaseTypeSchema {\n\t\treturn this.adapters.has(type as DatabaseTypeSchema);\n\t}\n\n\tgetSupportedTypes(): DatabaseTypeSchema[] {\n\t\treturn [...this.adapters.keys()];\n\t}\n}\n\nexport const adapterRegistry = new AdapterRegistry();\n\n/**\n * Drop-in replacement for getDaoFactory() — resolves to the registered\n * IDbAdapter for the given database type.\n */\nexport function getAdapter(dbType: DatabaseTypeSchema): IDbAdapter {\n\treturn adapterRegistry.get(dbType);\n}\n\nconst isKeyValueAdapter = (adapter: IDbAdapter): adapter is IDbAdapter & IKeyValueAdapter =>\n\t\"scanKeys\" in adapter && typeof adapter.scanKeys === \"function\";\n\nexport function assertKeyValueAdapter(\n\tadapter: IDbAdapter,\n\tdbType: DatabaseTypeSchema,\n): IKeyValueAdapter {\n\tif (!isKeyValueAdapter(adapter)) {\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: `Key browsing is not supported for database type: \"${dbType}\"`,\n\t\t});\n\t}\n\treturn adapter;\n}\n\nexport function getKeyValueAdapter(dbType: DatabaseTypeSchema): IKeyValueAdapter {\n\treturn assertKeyValueAdapter(adapterRegistry.get(dbType), dbType);\n}\n","import type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tCellValue,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tCursorData,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tSortDirection,\n\tTableDataResultSchemaType,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { DatabaseError } from \"pg\";\nimport type { GetTableDataParams, IDbAdapter } from \"@/adapters/adapter.interface.js\";\n\n/** One record's pending updates, addressed by every one of its key columns. */\nexport interface RecordUpdateGroup {\n\tkeyValues: unknown[];\n\trowUpdates: Array<{ columnName: string; value: unknown }>;\n}\n\n/** Bundles a paginated data query together with its companion COUNT query. */\nexport interface QueryBundle {\n\t/** Data query — the final bound parameter must be `limit + 1` for hasMore detection. */\n\tsql: string;\n\tvalues: unknown[];\n\t/** COUNT query that reflects only the active filters (no cursor). */\n\tcountSql: string;\n\tcountValues: unknown[];\n}\n\n/** A single row after adapter-level normalization (column → CellValue). */\nexport type NormalizedRow = Record<string, CellValue>;\n\nfunction notImplemented(method: string): never {\n\tthrow new HTTPException(501, {\n\t\tmessage: `${method} is not implemented for this database type`,\n\t});\n}\n\nexport abstract class BaseAdapter implements IDbAdapter {\n\t// =========================================================\n\t// Abstract — every concrete adapter MUST implement these\n\t// =========================================================\n\n\t/** Execute a parameterised query and return the result rows. */\n\tprotected abstract runQuery<T>(db: string, sql: string, values: unknown[]): Promise<T>;\n\n\t/**\n\t * Build a paginated data query and a companion COUNT query for getTableData().\n\t * The data query must append `limit + 1` as its final bound value so the\n\t * template method can detect whether a next page exists.\n\t */\n\tprotected abstract buildTableDataQuery(params: GetTableDataParams): QueryBundle;\n\n\t/** Map raw DB rows to NormalizedRow records. */\n\tprotected abstract normalizeRows(rawRows: unknown[]): NormalizedRow[];\n\n\t/**\n\t * Compute next/previous cursors from the final page rows.\n\t * Called after rows are trimmed to `limit` and reversed (for desc direction).\n\t */\n\tprotected abstract buildCursors(\n\t\tparams: GetTableDataParams,\n\t\trows: NormalizedRow[],\n\t\thasMore: boolean,\n\t): { nextCursor: string | null; prevCursor: string | null };\n\n\t/** Return the DB-specific quoted form of an identifier (table or column name). */\n\tprotected abstract quoteIdentifier(name: string): string;\n\n\tabstract mapToUniversalType(nativeType: string): DataTypes;\n\tabstract mapFromUniversalType(universalType: string): string;\n\n\t// =========================================================\n\t// Protected helpers — shared across all adapters\n\t// =========================================================\n\n\t/**\n\t * Delete requests carry one key column per row, so on a composite key they would match\n\t * every row sharing that column's value. Refuse until the request addresses whole keys.\n\t */\n\tprotected assertDeletableKey(pkColumns: string[]): void {\n\t\tif (pkColumns.length > 1)\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage:\n\t\t\t\t\t\"Deleting rows from tables with a composite primary key is not supported yet.\",\n\t\t\t});\n\t}\n\n\t/**\n\t * Wrap any thrown value in an HTTPException.\n\t * Detects connection errors for all supported databases and maps them to 503.\n\t * Concrete adapters can override to handle additional DB-specific error codes.\n\t */\n\tprotected wrapError(e: unknown): HTTPException {\n\t\tif (e instanceof HTTPException) return e;\n\n\t\tif (e instanceof Error) {\n\t\t\tconst err = e as { code?: string; errno?: number };\n\t\t\t// fetch-based drivers (libSQL over HTTP) throw \"fetch failed\" and keep the socket error in `cause`\n\t\t\tconst code = err.code ?? (e.cause as { code?: string } | undefined)?.code;\n\n\t\t\tconst isConnectionError =\n\t\t\t\tcode === \"ECONNREFUSED\" ||\n\t\t\t\tcode === \"ENOTFOUND\" ||\n\t\t\t\tcode === \"ETIMEDOUT\" ||\n\t\t\t\tcode === \"ER_ACCESS_DENIED_ERROR\" ||\n\t\t\t\tcode === \"ER_BAD_HOST_ERROR\" ||\n\t\t\t\tcode === \"ECONNRESET\" ||\n\t\t\t\terr.errno === 1045 || // MySQL ER_ACCESS_DENIED_ERROR\n\t\t\t\terr.errno === 2003 || // MySQL can't connect to server\n\t\t\t\terr.errno === 2002 || // MySQL can't connect to local server\n\t\t\t\te.message.includes(\"ECONNREFUSED\") ||\n\t\t\t\te.message.includes(\"connection refused\") ||\n\t\t\t\te.message.includes(\"timeout expired\") ||\n\t\t\t\te.message.includes(\"Connection terminated\") ||\n\t\t\t\te.message.includes(\"MongoNetworkError\") ||\n\t\t\t\te.message.includes(\"MongoServerSelectionError\") ||\n\t\t\t\te.message.includes(\"Login failed\") ||\n\t\t\t\t/HTTP status (401|403)\\b/.test(e.message) || // libSQL / Turso: bad or missing authToken\n\t\t\t\te.message.startsWith(\"NOAUTH\") || // Redis: auth required\n\t\t\t\te.message.startsWith(\"WRONGPASS\") || // Redis: invalid credentials\n\t\t\t\te.message.startsWith(\"LOADING\") || // Redis: dataset loading\n\t\t\t\te.message.startsWith(\"BUSY\") || // Redis: server busy\n\t\t\t\te.message.startsWith(\"READONLY\") || // Redis: read-only replica\n\t\t\t\te.message.startsWith(\"CLUSTERDOWN\") || // Redis: cluster down\n\t\t\t\te.message.includes(\"Redis cluster mode is not supported\") ||\n\t\t\t\te.message.includes(\"Could not set lock on file\") || // DuckDB: file locked by another process\n\t\t\t\t// Oracle: no listener, unknown service/SID, bad credentials, locked account,\n\t\t\t\t// timeout or lost connection; NJS-5xx are the thin driver's network errors\n\t\t\t\t/^(ORA-(01017|03113|03114|03135|12170|12505|12514|12541|28000)|NJS-5(00|01|03|10|11|18|21)):/.test(\n\t\t\t\t\te.message,\n\t\t\t\t) ||\n\t\t\t\te.message.includes(\"Authentication failed: password is incorrect\") || // ClickHouse\n\t\t\t\te.message === \"Timeout error.\" || // @clickhouse/client request timeout\n\t\t\t\t(e instanceof DatabaseError && e.code?.startsWith(\"08\")); // PG connection exception class\n\n\t\t\tif (isConnectionError) {\n\t\t\t\treturn new HTTPException(503, { message: e.message, cause: e });\n\t\t\t}\n\n\t\t\treturn new HTTPException(500, { message: e.message, cause: e });\n\t\t}\n\n\t\treturn new HTTPException(500, { message: \"Internal server error\", cause: e });\n\t}\n\n\t/**\n\t * Resolve the key columns a record update must match on. `primaryKeys` carries\n\t * every component of a composite key; `primaryKey` is the single-column form.\n\t */\n\tprotected resolveKeyColumns(params: UpdateRecordsSchemaType): string[] {\n\t\treturn params.primaryKeys?.length ? params.primaryKeys : [params.primaryKey];\n\t}\n\n\t/**\n\t * An update matched on part of a primary key would write every row sharing those\n\t * values, so the request must name every key column of the table.\n\t */\n\tprotected assertWholeKey(pkColumns: string[], keyColumns: string[]): void {\n\t\tconst missing = pkColumns.filter((column) => !keyColumns.includes(column));\n\t\tif (missing.length > 0)\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: `Updates must match on every primary key column; missing: ${missing.join(\", \")}`,\n\t\t\t});\n\t}\n\n\t/**\n\t * Group updates by the record they target so each row is written once, matched\n\t * on every key column. Throws 400 when a key column is absent from the row.\n\t */\n\tprotected groupUpdatesByKey(\n\t\tparams: UpdateRecordsSchemaType,\n\t\tkeyColumns: string[],\n\t): RecordUpdateGroup[] {\n\t\tconst groups = new Map<string, RecordUpdateGroup>();\n\n\t\tfor (const update of params.updates) {\n\t\t\tconst keyValues = keyColumns.map((column) => {\n\t\t\t\tconst value = update.rowData[column];\n\t\t\t\tif (value === undefined || value === null) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: `Primary key \"${column}\" not found in row data.`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t});\n\n\t\t\tconst groupKey = JSON.stringify(keyValues.map((value) => String(value)));\n\t\t\tconst group: RecordUpdateGroup = groups.get(groupKey) ?? { keyValues, rowUpdates: [] };\n\t\t\tgroup.rowUpdates.push({ columnName: update.columnName, value: update.value });\n\t\t\tgroups.set(groupKey, group);\n\t\t}\n\n\t\treturn [...groups.values()];\n\t}\n\n\t/**\n\t * ORDER BY terms for a page: the requested sorts, then every key column not already\n\t * sorted on, as tie-breakers in the leading sort's direction so paging stays stable.\n\t */\n\tprotected orderTerms<K>(\n\t\tsort: GetTableDataParams[\"sort\"] = [],\n\t\torder: SortDirection,\n\t\tkeyColumns: K[],\n\t): Array<{ column: string | K; direction: SortDirection }> {\n\t\tconst sorts =\n\t\t\ttypeof sort === \"string\" ? (sort ? [{ columnName: sort, direction: order }] : []) : sort;\n\t\tconst tieBreakerDirection = sorts[0]?.direction ?? order;\n\t\treturn [\n\t\t\t...sorts.map((s) => ({ column: s.columnName, direction: s.direction })),\n\t\t\t...keyColumns\n\t\t\t\t.filter((key) => !sorts.some((s) => s.columnName === key))\n\t\t\t\t.map((column) => ({ column, direction: tieBreakerDirection })),\n\t\t];\n\t}\n\n\t/** Human-readable `col = value` list used in \"record not found\" errors. */\n\tprotected describeKey(keyColumns: string[], keyValues: unknown[]): string {\n\t\treturn keyColumns.map((column, i) => `${column} = ${keyValues[i]}`).join(\", \");\n\t}\n\n\tprotected assertDifferentTableName(tableName: string, newTableName: string): void {\n\t\tif (tableName === newTableName) {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: `New table name must be different from \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\t/** Encode cursor data to a URL-safe base64 string. */\n\tprotected encodeCursor(data: CursorData): string {\n\t\treturn Buffer.from(JSON.stringify(data)).toString(\"base64url\");\n\t}\n\n\t/** Decode a base64url cursor string; returns null if malformed. */\n\tprotected decodeCursor(cursor: string): CursorData | null {\n\t\ttry {\n\t\t\treturn JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf-8\"));\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Normalize a single raw row by casting each value to CellValue.\n\t * Convenience helper for use inside normalizeRows() implementations.\n\t */\n\tprotected normalizeRow(row: Record<string, unknown>): NormalizedRow {\n\t\tconst out: NormalizedRow = {};\n\t\tfor (const [k, v] of Object.entries(row)) {\n\t\t\tout[k] = v as CellValue;\n\t\t}\n\t\treturn out;\n\t}\n\n\t// =========================================================\n\t// Template Methods — shared skeleton, DB-specific steps via abstract methods\n\t// =========================================================\n\n\tasync getTableData(params: GetTableDataParams): Promise<TableDataResultSchemaType> {\n\t\ttry {\n\t\t\tconst { db, limit = 50, direction = \"asc\" } = params;\n\t\t\tconst bundle = this.buildTableDataQuery(params);\n\n\t\t\t// Total count with active filters only (no cursor)\n\t\t\tconst countRes = await this.runQuery<Record<string, unknown>[]>(\n\t\t\t\tdb,\n\t\t\t\tbundle.countSql,\n\t\t\t\tbundle.countValues,\n\t\t\t);\n\t\t\tconst total = Number(countRes[0]?.total ?? 0);\n\n\t\t\t// Fetch limit+1 rows to determine whether a next page exists\n\t\t\tlet rawRows = await this.runQuery<unknown[]>(db, bundle.sql, bundle.values);\n\t\t\tconst hasMore = rawRows.length > limit;\n\t\t\tif (hasMore) rawRows = rawRows.slice(0, limit);\n\n\t\t\tlet rows = this.normalizeRows(rawRows);\n\t\t\tif (direction === \"desc\") rows = rows.reverse();\n\n\t\t\tconst { nextCursor, prevCursor } = this.buildCursors(params, rows, hasMore);\n\n\t\t\treturn {\n\t\t\t\tdata: rows,\n\t\t\t\tmeta: {\n\t\t\t\t\tlimit,\n\t\t\t\t\ttotal,\n\t\t\t\t\thasNextPage: direction === \"asc\" ? hasMore : !!params.cursor,\n\t\t\t\t\thasPreviousPage: direction === \"asc\" ? !!params.cursor : hasMore,\n\t\t\t\t\tnextCursor,\n\t\t\t\t\tprevCursor,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync exportTableData({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<{ cols: string[]; rows: Record<string, unknown>[] }> {\n\t\ttry {\n\t\t\tconst sql = `SELECT * FROM ${this.quoteIdentifier(tableName)}`;\n\t\t\tconst rows = await this.runQuery<Record<string, unknown>[]>(db, sql, []);\n\n\t\t\tif (!rows || rows.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Table \"${tableName}\" does not exist or has no data`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst cols = Object.keys(rows[0]);\n\t\t\treturn { cols, rows };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// Default stubs — override in concrete adapters\n\t// =========================================================\n\n\tgetDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\treturn notImplemented(\"getDatabasesList\");\n\t}\n\tgetCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\treturn notImplemented(\"getCurrentDatabase\");\n\t}\n\tgetDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\treturn notImplemented(\"getDatabaseConnectionInfo\");\n\t}\n\tgetTablesList(_db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\treturn notImplemented(\"getTablesList\");\n\t}\n\tcreateTable(_params: {\n\t\ttableData: CreateTableSchemaType;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<void> {\n\t\treturn notImplemented(\"createTable\");\n\t}\n\tdeleteTable(_params: DeleteTableParams): Promise<DeleteTableResult> {\n\t\treturn notImplemented(\"deleteTable\");\n\t}\n\trenameTable(_params: RenameTableParamsSchemaType): Promise<void> {\n\t\treturn notImplemented(\"renameTable\");\n\t}\n\tgetTableSchema(_params: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\treturn notImplemented(\"getTableSchema\");\n\t}\n\tgetTableColumns(_params: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\treturn notImplemented(\"getTableColumns\");\n\t}\n\taddColumn(_params: AddColumnParamsSchemaType): Promise<void> {\n\t\treturn notImplemented(\"addColumn\");\n\t}\n\tdeleteColumn(_params: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\treturn notImplemented(\"deleteColumn\");\n\t}\n\talterColumn(_params: AlterColumnParamsSchemaType): Promise<void> {\n\t\treturn notImplemented(\"alterColumn\");\n\t}\n\trenameColumn(_params: RenameColumnParamsSchemaType): Promise<void> {\n\t\treturn notImplemented(\"renameColumn\");\n\t}\n\taddRecord(_params: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\treturn notImplemented(\"addRecord\");\n\t}\n\tupdateRecords(_params: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\treturn notImplemented(\"updateRecords\");\n\t}\n\tdeleteRecords(_params: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\treturn notImplemented(\"deleteRecords\");\n\t}\n\tforceDeleteRecords(_params: DeleteRecordParams): Promise<{ deletedCount: number }> {\n\t\treturn notImplemented(\"forceDeleteRecords\");\n\t}\n\tbulkInsertRecords(_params: BulkInsertRecordsParams): Promise<BulkInsertResult> {\n\t\treturn notImplemented(\"bulkInsertRecords\");\n\t}\n\texecuteQuery(_params: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\treturn notImplemented(\"executeQuery\");\n\t}\n}\n","import * as dbManager from \"@/db-manager.js\";\n\nexport const getDbPool: typeof dbManager.getDbPool = (database) =>\n\tdbManager.getDbPool(database);\n\nexport const getMysqlPool: typeof dbManager.getMysqlPool = (database) =>\n\tdbManager.getMysqlPool(database);\n\nexport const getMssqlPool: typeof dbManager.getMssqlPool = (database) =>\n\tdbManager.getMssqlPool(database);\n\nexport const getSqliteClient: typeof dbManager.getSqliteClient = () =>\n\tdbManager.getSqliteClient();\n\nexport const withDuckdbConnection: typeof dbManager.withDuckdbConnection = (fn) =>\n\tdbManager.withDuckdbConnection(fn);\n\nexport const getOraclePool: typeof dbManager.getOraclePool = () => dbManager.getOraclePool();\n\nexport const getMongoClient: typeof dbManager.getMongoClient = () =>\n\tdbManager.getMongoClient();\n\nexport const getMongoDbName: typeof dbManager.getMongoDbName = () =>\n\tdbManager.getMongoDbName();\n\nexport const getMongoDb: typeof dbManager.getMongoDb = (dbName) =>\n\tdbManager.getMongoDb(dbName);\n\nexport const getRedisClient: typeof dbManager.getRedisClient = (dbIndex) =>\n\tdbManager.getRedisClient(dbIndex);\n\nexport const getIsolatedRedisClient: typeof dbManager.getIsolatedRedisClient = (dbIndex) =>\n\tdbManager.getIsolatedRedisClient(dbIndex);\n\nexport const getRedisDefaultDb: typeof dbManager.getRedisDefaultDb = () =>\n\tdbManager.getRedisDefaultDb();\n\nexport const getClickhouseClient: typeof dbManager.getClickhouseClient = (database) =>\n\tdbManager.getClickhouseClient(database);\n","import type { FilterType, SortDirection, SortType } from \"@db-studio/shared/types\";\n\nexport const quoteClickhouseIdentifier = (name: string): string =>\n\t`\\`${name.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll(\"`\", \"\\\\`\")}\\``;\n\nconst q = quoteClickhouseIdentifier;\n\n/**\n * Filter values bind as positional `{pN:String}` parameters: ClickHouse converts a\n * string operand to the column's type for comparisons. LIKE needs a string column,\n * so it compares the column's text form.\n */\nexport function buildWhereClause(filters: FilterType[]): { clause: string; values: string[] } {\n\tconst conditions: string[] = [];\n\tconst values: string[] = [];\n\n\tconst bind = (value: string) => {\n\t\tvalues.push(value);\n\t\treturn `{p${values.length - 1}:String}`;\n\t};\n\n\tfor (const { columnName, operator, value } of filters) {\n\t\tconst col = q(columnName);\n\t\tswitch (operator) {\n\t\t\tcase \"=\":\n\t\t\tcase \"!=\":\n\t\t\tcase \">\":\n\t\t\tcase \">=\":\n\t\t\tcase \"<\":\n\t\t\tcase \"<=\":\n\t\t\t\tconditions.push(`${col} ${operator} ${bind(value)}`);\n\t\t\t\tbreak;\n\t\t\tcase \"is\":\n\t\t\t\tconditions.push(\n\t\t\t\t\tvalue.toLowerCase() === \"null\" ? `${col} IS NULL` : `${col} = ${bind(value)}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"is not\":\n\t\t\t\tconditions.push(\n\t\t\t\t\tvalue.toLowerCase() === \"null\" ? `${col} IS NOT NULL` : `${col} != ${bind(value)}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"like\":\n\t\t\t\tconditions.push(`toString(${col}) LIKE ${bind(value)}`);\n\t\t\t\tbreak;\n\t\t\tcase \"not like\":\n\t\t\t\tconditions.push(`toString(${col}) NOT LIKE ${bind(value)}`);\n\t\t\t\tbreak;\n\t\t\tcase \"ilike\":\n\t\t\t\tconditions.push(`toString(${col}) ILIKE ${bind(value)}`);\n\t\t\t\tbreak;\n\t\t\tcase \"not ilike\":\n\t\t\t\tconditions.push(`toString(${col}) NOT ILIKE ${bind(value)}`);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn { clause: conditions.length ? `WHERE ${conditions.join(\" AND \")}` : \"\", values };\n}\n\n/**\n * User sort first, then `tieBreakers` (raw expressions such as the table's sorting\n * key) in the leading sort direction, so OFFSET pages stay stable.\n */\nexport function buildOrderByClause(\n\tsort: SortType[] | string,\n\torder: SortDirection,\n\ttieBreakers: string[],\n): string {\n\tconst sorts: SortType[] = Array.isArray(sort)\n\t\t? sort\n\t\t: sort\n\t\t\t? [{ columnName: sort, direction: order }]\n\t\t\t: [];\n\tconst direction = (sorts[0]?.direction ?? order).toUpperCase();\n\tconst terms = [\n\t\t...sorts.map((s) => `${q(s.columnName)} ${s.direction.toUpperCase()}`),\n\t\t...tieBreakers.map((expr) => `${expr} ${direction}`),\n\t];\n\treturn terms.length ? `ORDER BY ${terms.join(\", \")}` : \"\";\n}\n\n/** Postgres types (from the web form) to ClickHouse. Unknown names pass through as native ClickHouse types. */\nexport function mapColumnTypeToClickhouse(\n\tcolumnType: string,\n\tisArray: boolean,\n\tsupportsJsonType: boolean,\n): string {\n\tconst typeMap: Record<string, string> = {\n\t\tsmallserial: \"UInt16\",\n\t\tserial2: \"UInt16\",\n\t\tserial: \"UInt32\",\n\t\tserial4: \"UInt32\",\n\t\tbigserial: \"UInt64\",\n\t\tserial8: \"UInt64\",\n\t\ttinyint: \"Int8\",\n\t\tsmallint: \"Int16\",\n\t\tint2: \"Int16\",\n\t\tint: \"Int32\",\n\t\tint4: \"Int32\",\n\t\tinteger: \"Int32\",\n\t\tbigint: \"Int64\",\n\t\tint8: \"Int64\",\n\t\tnumeric: \"Decimal(38, 10)\",\n\t\tdecimal: \"Decimal(38, 10)\",\n\t\tmoney: \"Decimal(19, 4)\",\n\t\treal: \"Float32\",\n\t\tfloat4: \"Float32\",\n\t\tfloat: \"Float64\",\n\t\tfloat8: \"Float64\",\n\t\t\"double precision\": \"Float64\",\n\t\tboolean: \"Bool\",\n\t\tbool: \"Bool\",\n\t\ttext: \"String\",\n\t\tvarchar: \"String\",\n\t\t\"character varying\": \"String\",\n\t\tchar: \"String\",\n\t\tcharacter: \"String\",\n\t\tbpchar: \"String\",\n\t\tcitext: \"String\",\n\t\tuuid: \"UUID\",\n\t\tjson: supportsJsonType ? \"JSON\" : \"String\",\n\t\tjsonb: supportsJsonType ? \"JSON\" : \"String\",\n\t\txml: \"String\",\n\t\tdate: \"Date32\",\n\t\ttime: \"String\",\n\t\t\"time without time zone\": \"String\",\n\t\ttimestamp: \"DateTime64(6)\",\n\t\t\"timestamp without time zone\": \"DateTime64(6)\",\n\t\ttimestamptz: \"DateTime64(6, 'UTC')\",\n\t\t\"timestamp with time zone\": \"DateTime64(6, 'UTC')\",\n\t\tinterval: \"String\",\n\t\tbytea: \"String\",\n\t\tinet: \"String\",\n\t\tcidr: \"String\",\n\t\tmacaddr: \"String\",\n\t\tmacaddr8: \"String\",\n\t};\n\n\tconst base = typeMap[columnType.toLowerCase().trim()] ?? columnType.trim();\n\treturn isArray ? `Array(${base})` : base;\n}\n\nconst DEFAULT_FUNCTIONS: Record<string, string> = {\n\t\"now()\": \"now()\",\n\tcurrent_timestamp: \"now()\",\n\t\"current_timestamp()\": \"now()\",\n\tcurrent_date: \"today()\",\n\t\"gen_random_uuid()\": \"generateUUIDv4()\",\n\t\"uuid_generate_v4()\": \"generateUUIDv4()\",\n};\n\ntype ClickhouseColumnInput = {\n\tcolumnName: string;\n\tcolumnType: string;\n\tisArray?: boolean;\n\tisNullable?: boolean;\n\tisPrimaryKey?: boolean;\n\tisIdentity?: boolean;\n\tdefaultValue?: string | null;\n};\n\n/**\n * Identity and serial columns become `UInt64 DEFAULT generateSnowflakeID()`:\n * ClickHouse has no auto-increment, and Snowflake IDs are unique and grow in\n * insertion order.\n */\nexport function buildClickhouseColumnDefinition(\n\tfield: ClickhouseColumnInput,\n\tsupportsJsonType: boolean,\n): string {\n\tconst name = q(field.columnName);\n\tif (field.isIdentity || /serial/i.test(field.columnType)) {\n\t\treturn `${name} UInt64 DEFAULT generateSnowflakeID()`;\n\t}\n\n\tconst type = mapColumnTypeToClickhouse(\n\t\tfield.columnType,\n\t\tfield.isArray ?? false,\n\t\tsupportsJsonType,\n\t);\n\tconst nullable = field.isNullable && !field.isPrimaryKey && !field.isArray;\n\tlet def = `${name} ${nullable ? `Nullable(${type})` : type}`;\n\n\tconst defaultValue = field.defaultValue?.trim();\n\tif (defaultValue) {\n\t\tdef += ` DEFAULT ${DEFAULT_FUNCTIONS[defaultValue.toLowerCase()] ?? defaultValue}`;\n\t}\n\treturn def;\n}\n","import type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tTableDataResultSchemaType,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport {\n\tDATABASE_ENGINES,\n\tmapClickhouseToDataType,\n\tstandardizeClickhouseDataTypeLabel,\n\tunwrapClickhouseType,\n} from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getClickhouseClient } from \"@/adapters/connections.js\";\nimport { parseDatabaseUrl } from \"@/utils/parse-database-url.js\";\nimport {\n\tbuildClickhouseColumnDefinition,\n\tbuildOrderByClause,\n\tbuildWhereClause,\n\tquoteClickhouseIdentifier as q,\n} from \"./clickhouse.query-builder.js\";\n\ninterface ColumnRow {\n\tname: string;\n\ttype: string;\n\tdefault_expression: string;\n\tis_in_sorting_key: number;\n}\n\ninterface TableRow {\n\tengine: string;\n\tsorting_key: string;\n}\n\ntype Params = Record<string, unknown>;\n\n/** Wait for ALTER ... UPDATE/DELETE mutations to finish on every replica before returning. */\nconst MUTATION_SETTINGS = { mutations_sync: \"2\" } as const;\n\nconst isNullableType = (type: string) => /^(LowCardinality\\()?Nullable\\(/.test(type);\n\n/** Shapes a client value for a JSONEachRow insert into a column of `type`. */\nconst toClickhouseValue = (value: unknown, type: string): unknown => {\n\tif (value === undefined || value === null) return null;\n\tconst base = unwrapClickhouseType(type);\n\tif (value === \"\" && base !== \"String\" && !base.startsWith(\"FixedString\")) return null;\n\tif (value instanceof Date) return value.toISOString();\n\tif (base === \"Bool\" && typeof value === \"string\") {\n\t\treturn [\"true\", \"t\", \"1\", \"yes\", \"on\"].includes(value.trim().toLowerCase());\n\t}\n\tif (\n\t\ttypeof value === \"string\" &&\n\t\t(base.startsWith(\"JSON\") || base.startsWith(\"Array(\") || base.startsWith(\"Map(\"))\n\t) {\n\t\ttry {\n\t\t\treturn JSON.parse(value);\n\t\t} catch {\n\t\t\tthrow new HTTPException(400, { message: `Invalid ${base} value: ${value}` });\n\t\t}\n\t}\n\tif (typeof value === \"object\" && base === \"String\") return JSON.stringify(value);\n\treturn value;\n};\n\nexport class ClickhouseAdapter extends BaseAdapter {\n\tprivate serverVersion: number[] | null = null;\n\n\t// =========================================================\n\t// Abstract method implementations\n\t// =========================================================\n\n\tprotected async runQuery<T>(db: string, sql: string, values: unknown[]): Promise<T> {\n\t\tconst params = Object.fromEntries(values.map((value, i) => [`p${i}`, value]));\n\t\treturn (await this.select(db, sql, params)) as T;\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn q(name);\n\t}\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\treturn mapClickhouseToDataType(nativeType);\n\t}\n\n\tmapFromUniversalType(universalType: string): string {\n\t\tconst map: Record<string, string> = {\n\t\t\ttext: \"String\",\n\t\t\tnumber: \"Int64\",\n\t\t\tboolean: \"Bool\",\n\t\t\tjson: \"String\",\n\t\t\tdate: \"DateTime\",\n\t\t\tarray: \"Array(String)\",\n\t\t\tenum: \"String\",\n\t\t};\n\t\treturn map[universalType] ?? \"String\";\n\t}\n\n\tprotected buildTableDataQuery(params: GetTableDataParams): QueryBundle {\n\t\treturn this.buildPageQuery(params, []);\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn (rawRows as Record<string, unknown>[]).map((row) => this.normalizeRow(row));\n\t}\n\n\tprotected buildCursors(\n\t\tparams: GetTableDataParams,\n\t\t_rows: NormalizedRow[],\n\t\thasMore: boolean,\n\t): { nextCursor: string | null; prevCursor: string | null } {\n\t\tconst { cursor, limit = 50 } = params;\n\t\tconst offset = cursor ? this.decodeOffsetCursor(cursor) : 0;\n\t\treturn {\n\t\t\tnextCursor: hasMore ? this.makeCursor(offset + limit) : null,\n\t\t\tprevCursor: offset > 0 ? this.makeCursor(Math.max(0, offset - limit)) : null,\n\t\t};\n\t}\n\n\t// =========================================================\n\t// Offset pagination: the sorting key is not unique, so keyset paging could skip rows\n\t// =========================================================\n\n\toverride async getTableData(params: GetTableDataParams): Promise<TableDataResultSchemaType> {\n\t\ttry {\n\t\t\tconst { db, tableName, limit = 50, cursor } = params;\n\t\t\tconst table = await this.getTable(db, tableName);\n\t\t\tconst tieBreakers = table.sorting_key ? [`(${table.sorting_key})`] : [];\n\t\t\tif (table.engine.endsWith(\"MergeTree\")) tieBreakers.push(\"_part\", \"_part_offset\");\n\n\t\t\tconst bundle = this.buildPageQuery(params, tieBreakers);\n\t\t\tconst [countRows, rawRows] = await Promise.all([\n\t\t\t\tthis.runQuery<{ total: string | number }[]>(db, bundle.countSql, bundle.countValues),\n\t\t\t\tthis.runQuery<Record<string, unknown>[]>(db, bundle.sql, bundle.values),\n\t\t\t]);\n\n\t\t\tconst hasMore = rawRows.length > limit;\n\t\t\tconst rows = this.normalizeRows(hasMore ? rawRows.slice(0, limit) : rawRows);\n\t\t\tconst offset = cursor ? this.decodeOffsetCursor(cursor) : 0;\n\n\t\t\treturn {\n\t\t\t\tdata: rows,\n\t\t\t\tmeta: {\n\t\t\t\t\tlimit,\n\t\t\t\t\ttotal: Number(countRows[0]?.total ?? 0),\n\t\t\t\t\thasNextPage: hasMore,\n\t\t\t\t\thasPreviousPage: offset > 0,\n\t\t\t\t\t...this.buildCursors(params, rows, hasMore),\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// Databases\n\t// =========================================================\n\n\tasync getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst rows = await this.select<{ name: string; size: string }>(\n\t\t\t\tundefined,\n\t\t\t\t`SELECT d.name AS name, formatReadableSize(p.bytes) AS size\n\t\t\t\tFROM system.databases AS d\n\t\t\t\tLEFT JOIN (\n\t\t\t\t\tSELECT database, sum(bytes_on_disk) AS bytes FROM system.parts WHERE active GROUP BY database\n\t\t\t\t) AS p ON p.database = d.name\n\t\t\t\tWHERE d.name NOT IN ('system', 'INFORMATION_SCHEMA', 'information_schema')\n\t\t\t\tORDER BY d.name`,\n\t\t\t);\n\t\t\treturn rows.map((row) => ({ ...row, owner: \"\", encoding: \"UTF-8\" }));\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\ttry {\n\t\t\tconst [row] = await this.select<{ db: string }>(\n\t\t\t\tundefined,\n\t\t\t\t\"SELECT currentDatabase() AS db\",\n\t\t\t);\n\t\t\treturn { db: row?.db ?? \"default\" };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\ttry {\n\t\t\tconst [info] = await this.select<{\n\t\t\t\tversion: string;\n\t\t\t\tuser: string;\n\t\t\t\tdatabase: string;\n\t\t\t\tactive_connections: number;\n\t\t\t\tmax_connections: string;\n\t\t\t}>(\n\t\t\t\tundefined,\n\t\t\t\t`SELECT\n\t\t\t\t\tversion() AS version,\n\t\t\t\t\tcurrentUser() AS user,\n\t\t\t\t\tcurrentDatabase() AS database,\n\t\t\t\t\t(SELECT sum(value) FROM system.metrics WHERE metric IN ('TCPConnection', 'HTTPConnection', 'MySQLConnection', 'PostgreSQLConnection')) AS active_connections,\n\t\t\t\t\t(SELECT value FROM system.server_settings WHERE name = 'max_connections') AS max_connections`,\n\t\t\t);\n\t\t\tif (!info) {\n\t\t\t\tthrow new HTTPException(500, { message: \"No connection information returned\" });\n\t\t\t}\n\t\t\tconst { host, port } = parseDatabaseUrl();\n\t\t\treturn {\n\t\t\t\thost,\n\t\t\t\tport,\n\t\t\t\tuser: info.user,\n\t\t\t\tdatabase: info.database,\n\t\t\t\tversion: `ClickHouse ${info.version}`,\n\t\t\t\tactive_connections: Number(info.active_connections),\n\t\t\t\tmax_connections: Number(info.max_connections),\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// Tables\n\t// =========================================================\n\n\tasync getTablesList(db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst rows = await this.select<{ tableName: string; rowCount: string | number | null }>(\n\t\t\t\tdb,\n\t\t\t\t`SELECT name AS tableName, total_rows AS rowCount\n\t\t\t\tFROM system.tables\n\t\t\t\tWHERE database = currentDatabase() AND NOT is_temporary AND NOT startsWith(name, '.inner')\n\t\t\t\tORDER BY name`,\n\t\t\t);\n\t\t\treturn rows.map((row) => ({\n\t\t\t\ttableName: row.tableName,\n\t\t\t\trowCount: Number(row.rowCount ?? 0),\n\t\t\t}));\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync createTable({\n\t\ttableData,\n\t\tdb,\n\t}: {\n\t\ttableData: CreateTableSchemaType;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<void> {\n\t\tconst { tableName, fields, foreignKeys } = tableData;\n\t\tif (foreignKeys?.length) {\n\t\t\tthrow new HTTPException(400, { message: \"ClickHouse does not support foreign keys\" });\n\t\t}\n\t\tconst unique = fields.find((f) => f.isUnique && !f.isPrimaryKey);\n\t\tif (unique) {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: `ClickHouse does not enforce UNIQUE constraints; clear \"Unique\" on \"${unique.columnName}\"`,\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tconst supportsJson = await this.isAtLeast(db, 25, 3);\n\t\t\tif (fields.some((f) => f.isIdentity || /serial/i.test(f.columnType))) {\n\t\t\t\tif (!(await this.isAtLeast(db, 24, 6))) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: \"Auto-generated ids need ClickHouse 24.6 or newer (generateSnowflakeID)\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst columns = fields.map((f) => buildClickhouseColumnDefinition(f, supportsJson));\n\t\t\tconst keys = fields.filter((f) => f.isPrimaryKey).map((f) => q(f.columnName));\n\t\t\tawait this.command(\n\t\t\t\tdb,\n\t\t\t\t`CREATE TABLE ${q(tableName)} (${columns.join(\", \")}) ENGINE = MergeTree ORDER BY ${keys.length ? `(${keys.join(\", \")})` : \"tuple()\"}`,\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync deleteTable({ tableName, db }: DeleteTableParams): Promise<DeleteTableResult> {\n\t\ttry {\n\t\t\tawait this.getTable(db, tableName);\n\t\t\tconst [row] = await this.select<{ total: string | number }>(\n\t\t\t\tdb,\n\t\t\t\t`SELECT count() AS total FROM ${q(tableName)}`,\n\t\t\t);\n\t\t\tawait this.command(db, `DROP TABLE ${q(tableName)}`);\n\t\t\treturn { deletedCount: Number(row?.total ?? 0), fkViolation: false, relatedRecords: [] };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync renameTable({\n\t\ttableName,\n\t\tnewTableName,\n\t\tdb,\n\t}: RenameTableParamsSchemaType): Promise<void> {\n\t\tthis.assertDifferentTableName(tableName, newTableName);\n\t\ttry {\n\t\t\tawait this.getTable(db, tableName);\n\t\t\tif (await this.findTable(db, newTableName)) {\n\t\t\t\tthrow new HTTPException(409, { message: `Table \"${newTableName}\" already exists` });\n\t\t\t}\n\t\t\tawait this.command(db, `RENAME TABLE ${q(tableName)} TO ${q(newTableName)}`);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getTableSchema({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\ttry {\n\t\t\tawait this.getTable(db, tableName);\n\t\t\tconst [row] = await this.select<{ statement: string }>(\n\t\t\t\tdb,\n\t\t\t\t`SHOW CREATE TABLE ${q(tableName)}`,\n\t\t\t);\n\t\t\treturn row?.statement ?? \"\";\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// Columns\n\t// =========================================================\n\n\tasync getTableColumns({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\ttry {\n\t\t\tawait this.getTable(db, tableName);\n\t\t\tconst columns = await this.getColumns(db, tableName);\n\t\t\treturn columns.map((col) => ({\n\t\t\t\tcolumnName: col.name,\n\t\t\t\tdataType: mapClickhouseToDataType(col.type),\n\t\t\t\tdataTypeLabel: standardizeClickhouseDataTypeLabel(col.type),\n\t\t\t\tisNullable: isNullableType(col.type),\n\t\t\t\tcolumnDefault: col.default_expression || null,\n\t\t\t\tisPrimaryKey: col.is_in_sorting_key === 1,\n\t\t\t\tisForeignKey: false,\n\t\t\t\treferencedTable: null,\n\t\t\t\treferencedColumn: null,\n\t\t\t\tenumValues: /^Enum(8|16)\\(/.test(unwrapClickhouseType(col.type))\n\t\t\t\t\t? [...col.type.matchAll(/'((?:[^'\\\\]|\\\\.)*)'\\s*=/g)].map((m) => m[1] ?? \"\")\n\t\t\t\t\t: null,\n\t\t\t}));\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync addColumn(params: AddColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, db } = params;\n\t\tif (params.isUnique) {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: \"ClickHouse does not enforce UNIQUE constraints\",\n\t\t\t});\n\t\t}\n\t\ttry {\n\t\t\tawait this.getTable(db, tableName);\n\t\t\tconst columns = await this.getColumns(db, tableName);\n\t\t\tif (columns.some((c) => c.name === columnName)) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Column \"${columnName}\" already exists in table \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst def = buildClickhouseColumnDefinition(\n\t\t\t\t{ ...params, isPrimaryKey: false },\n\t\t\t\tawait this.isAtLeast(db, 25, 3),\n\t\t\t);\n\t\t\tawait this.command(db, `ALTER TABLE ${q(tableName)} ADD COLUMN ${def}`);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync deleteColumn({\n\t\ttableName,\n\t\tcolumnName,\n\t\tdb,\n\t}: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\ttry {\n\t\t\tconst column = await this.getColumn(db, tableName, columnName);\n\t\t\tif (column.is_in_sorting_key) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `\"${columnName}\" is part of the sorting key and cannot be dropped`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait this.command(db, `ALTER TABLE ${q(tableName)} DROP COLUMN ${q(columnName)}`);\n\t\t\treturn { deletedCount: 1 };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync alterColumn(params: AlterColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, db } = params;\n\t\ttry {\n\t\t\tconst column = await this.getColumn(db, tableName, columnName);\n\t\t\tconst def = buildClickhouseColumnDefinition(\n\t\t\t\t{ ...params, columnName, isPrimaryKey: column.is_in_sorting_key === 1 },\n\t\t\t\tawait this.isAtLeast(db, 25, 3),\n\t\t\t);\n\t\t\tawait this.command(db, `ALTER TABLE ${q(tableName)} MODIFY COLUMN ${def}`);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync renameColumn({\n\t\ttableName,\n\t\tcolumnName,\n\t\tnewColumnName,\n\t\tdb,\n\t}: RenameColumnParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tawait this.getColumn(db, tableName, columnName);\n\t\t\tconst columns = await this.getColumns(db, tableName);\n\t\t\tif (columns.some((c) => c.name === newColumnName)) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Column \"${newColumnName}\" already exists in table \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait this.command(\n\t\t\t\tdb,\n\t\t\t\t`ALTER TABLE ${q(tableName)} RENAME COLUMN ${q(columnName)} TO ${q(newColumnName)}`,\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// Records\n\t// =========================================================\n\n\tasync addRecord({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\tif (!Object.keys(params.data).length) {\n\t\t\tthrow new HTTPException(400, { message: \"No data provided for insert\" });\n\t\t}\n\t\tawait this.insertRows(db, params.tableName, [params.data]);\n\t\treturn { insertedCount: 1 };\n\t}\n\n\tasync bulkInsertRecords({\n\t\ttableName,\n\t\trecords,\n\t\tdb,\n\t}: BulkInsertRecordsParams): Promise<BulkInsertResult> {\n\t\tif (!records?.length) {\n\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\t\t}\n\t\tawait this.insertRows(db, tableName, records);\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tmessage: `Bulk insert completed: ${records.length} records inserted`,\n\t\t\tsuccessCount: records.length,\n\t\t\tfailureCount: 0,\n\t\t};\n\t}\n\n\tasync updateRecords(_input: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\tthrow new HTTPException(400, { message: DATABASE_ENGINES.clickhouse.rowMutationReason });\n\t}\n\n\tasync deleteRecords(_params: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\tthrow new HTTPException(400, { message: DATABASE_ENGINES.clickhouse.rowMutationReason });\n\t}\n\n\tasync forceDeleteRecords(_params: DeleteRecordParams): Promise<{ deletedCount: number }> {\n\t\tthrow new HTTPException(400, { message: DATABASE_ENGINES.clickhouse.rowMutationReason });\n\t}\n\n\t// =========================================================\n\t// Query\n\t// =========================================================\n\n\tasync executeQuery({\n\t\tquery,\n\t\tdb,\n\t}: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\tconst cleaned = query.trim().replace(/;+\\s*$/, \"\");\n\t\tif (!cleaned) throw new HTTPException(400, { message: \"Query is required\" });\n\n\t\tconst start = performance.now();\n\t\ttry {\n\t\t\tconst client = getClickhouseClient(db);\n\t\t\tconst firstKeyword = cleaned\n\t\t\t\t.replace(/^(\\s*(--[^\\n]*\\n|\\/\\*[\\s\\S]*?\\*\\/))*/, \"\")\n\t\t\t\t.match(/^\\s*(\\w+)/)?.[1]\n\t\t\t\t?.toUpperCase();\n\n\t\t\tif (\n\t\t\t\tfirstKeyword &&\n\t\t\t\t[\"SELECT\", \"WITH\", \"SHOW\", \"DESC\", \"DESCRIBE\", \"EXPLAIN\", \"EXISTS\"].includes(\n\t\t\t\t\tfirstKeyword,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tconst result = await client.query({ query: cleaned, format: \"JSON\" });\n\t\t\t\tconst { meta = [], data } = await result.json<Record<string, unknown>>();\n\t\t\t\treturn {\n\t\t\t\t\tcolumns: meta.map((m) => m.name),\n\t\t\t\t\trows: data,\n\t\t\t\t\trowCount: data.length,\n\t\t\t\t\tduration: performance.now() - start,\n\t\t\t\t\tmessage: data.length === 0 ? \"OK\" : undefined,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst { summary } = await client.command({\n\t\t\t\tquery: cleaned,\n\t\t\t\tclickhouse_settings: MUTATION_SETTINGS,\n\t\t\t});\n\t\t\tconst rowCount = Number(summary?.written_rows ?? 0);\n\t\t\treturn {\n\t\t\t\tcolumns: [],\n\t\t\t\trows: [],\n\t\t\t\trowCount,\n\t\t\t\tduration: performance.now() - start,\n\t\t\t\tmessage: `OK (${rowCount} rows affected)`,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// Private helpers\n\t// =========================================================\n\n\tprivate async select<T = Record<string, unknown>>(\n\t\tdb: string | undefined,\n\t\tquery: string,\n\t\tqueryParams: Params = {},\n\t): Promise<T[]> {\n\t\tconst result = await getClickhouseClient(db).query({\n\t\t\tquery,\n\t\t\tquery_params: queryParams,\n\t\t\tformat: \"JSONEachRow\",\n\t\t});\n\t\treturn result.json<T>();\n\t}\n\n\tprivate async command(\n\t\tdb: string,\n\t\tquery: string,\n\t\tqueryParams: Params = {},\n\t\tsettings: Record<string, string> = {},\n\t): Promise<void> {\n\t\tawait getClickhouseClient(db).command({\n\t\t\tquery,\n\t\t\tquery_params: queryParams,\n\t\t\tclickhouse_settings: settings,\n\t\t});\n\t}\n\n\tprivate buildPageQuery(params: GetTableDataParams, tieBreakers: string[]): QueryBundle {\n\t\tconst { tableName, filters = [], sort = [], order = \"asc\", limit = 50, cursor } = params;\n\t\tconst { clause, values } = buildWhereClause(filters);\n\t\tconst orderBy = buildOrderByClause(sort, order, tieBreakers);\n\t\tconst offset = cursor ? this.decodeOffsetCursor(cursor) : 0;\n\t\tconst n = values.length;\n\n\t\treturn {\n\t\t\tsql: `SELECT * FROM ${q(tableName)} ${clause} ${orderBy} LIMIT {p${n + 1}:UInt64} OFFSET {p${n}:UInt64}`,\n\t\t\tvalues: [...values, offset, limit + 1],\n\t\t\tcountSql: `SELECT count() AS total FROM ${q(tableName)} ${clause}`,\n\t\t\tcountValues: values,\n\t\t};\n\t}\n\n\tprivate async findTable(db: string, tableName: string): Promise<TableRow | undefined> {\n\t\tconst [row] = await this.select<TableRow>(\n\t\t\tdb,\n\t\t\t\"SELECT engine, sorting_key FROM system.tables WHERE database = currentDatabase() AND name = {table:String}\",\n\t\t\t{ table: tableName },\n\t\t);\n\t\treturn row;\n\t}\n\n\tprivate async getTable(db: string, tableName: string): Promise<TableRow> {\n\t\tconst table = await this.findTable(db, tableName);\n\t\tif (!table)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\treturn table;\n\t}\n\n\tprivate getColumns(db: string, tableName: string): Promise<ColumnRow[]> {\n\t\treturn this.select<ColumnRow>(\n\t\t\tdb,\n\t\t\t`SELECT name, type, default_expression, is_in_sorting_key\n\t\t\tFROM system.columns\n\t\t\tWHERE database = currentDatabase() AND table = {table:String}\n\t\t\tORDER BY position`,\n\t\t\t{ table: tableName },\n\t\t);\n\t}\n\n\tprivate async getColumn(db: string, tableName: string, columnName: string) {\n\t\tawait this.getTable(db, tableName);\n\t\tconst column = (await this.getColumns(db, tableName)).find((c) => c.name === columnName);\n\t\tif (!column) {\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t\treturn column;\n\t}\n\n\tprivate async insertRows(\n\t\tdb: string,\n\t\ttableName: string,\n\t\trecords: Record<string, unknown>[],\n\t): Promise<void> {\n\t\ttry {\n\t\t\tawait this.getTable(db, tableName);\n\t\t\tconst types = new Map(\n\t\t\t\t(await this.getColumns(db, tableName)).map((c) => [c.name, c.type]),\n\t\t\t);\n\t\t\tconst values = records.map((record) =>\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tObject.entries(record).flatMap(([column, value]) => {\n\t\t\t\t\t\tconst type = types.get(column);\n\t\t\t\t\t\tif (!type) {\n\t\t\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\t\t\tmessage: `Column \"${column}\" does not exist in table \"${tableName}\"`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst shaped = toClickhouseValue(value, type);\n\t\t\t\t\t\t// Omit nulls for non-nullable columns so ClickHouse applies the column default.\n\t\t\t\t\t\treturn shaped === null && !isNullableType(type) ? [] : [[column, shaped]];\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t);\n\t\t\tawait getClickhouseClient(db).insert({\n\t\t\t\ttable: q(tableName),\n\t\t\t\tvalues,\n\t\t\t\tformat: \"JSONEachRow\",\n\t\t\t\tclickhouse_settings: { date_time_input_format: \"best_effort\" },\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tprivate async isAtLeast(db: string, major: number, minor: number): Promise<boolean> {\n\t\tif (!this.serverVersion) {\n\t\t\tconst [row] = await this.select<{ version: string }>(db, \"SELECT version() AS version\");\n\t\t\tthis.serverVersion = (row?.version ?? \"0.0\").split(\".\").map(Number);\n\t\t}\n\t\tconst [actualMajor = 0, actualMinor = 0] = this.serverVersion;\n\t\treturn actualMajor > major || (actualMajor === major && actualMinor >= minor);\n\t}\n\n\tprivate makeCursor(offset: number): string {\n\t\treturn this.encodeCursor({ values: { _offset: offset }, sortColumns: [\"_offset\"] });\n\t}\n\n\tprivate decodeOffsetCursor(cursor: string): number {\n\t\treturn Number(this.decodeCursor(cursor)?.values._offset ?? 0);\n\t}\n}\n","import type { FilterType, SortDirection } from \"@db-studio/shared/types\";\n\nexport const quoteDuckdbIdent = (name: string) => `\"${name.replaceAll('\"', '\"\"')}\"`;\n\nexport const whereSql = (conditions: string[]) =>\n\tconditions.length ? `WHERE ${conditions.join(\" AND \")}` : \"\";\n\nexport function buildFilterConditions(filters: FilterType[]): {\n\tconditions: string[];\n\tvalues: unknown[];\n} {\n\tconst conditions: string[] = [];\n\tconst values: unknown[] = [];\n\n\tfor (const filter of filters) {\n\t\tconst col = quoteDuckdbIdent(filter.columnName);\n\t\tconst isNull = filter.value.toLowerCase() === \"null\";\n\t\tswitch (filter.operator) {\n\t\t\tcase \"=\":\n\t\t\tcase \"!=\":\n\t\t\tcase \">\":\n\t\t\tcase \">=\":\n\t\t\tcase \"<\":\n\t\t\tcase \"<=\":\n\t\t\t\tconditions.push(`${col} ${filter.operator} ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"is\":\n\t\t\t\tif (isNull) {\n\t\t\t\t\tconditions.push(`${col} IS NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} = ?`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"is not\":\n\t\t\t\tif (isNull) {\n\t\t\t\t\tconditions.push(`${col} IS NOT NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} != ?`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"like\":\n\t\t\tcase \"not like\":\n\t\t\tcase \"ilike\":\n\t\t\tcase \"not ilike\":\n\t\t\t\tconditions.push(`CAST(${col} AS VARCHAR) ${filter.operator.toUpperCase()} ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn { conditions, values };\n}\n\nexport interface OrderTerm {\n\tcolumn: string;\n\tdirection: SortDirection;\n}\n\n/** NULLs sort last in either direction; a backward page reads that order reversed. */\nconst placement = (term: OrderTerm, backward: boolean) => ({\n\tdescending: (term.direction === \"desc\") !== backward,\n\tnullsLast: !backward,\n});\n\nexport const buildOrderBy = (terms: OrderTerm[], backward = false) =>\n\t`ORDER BY ${terms\n\t\t.map((term) => {\n\t\t\tconst { descending, nullsLast } = placement(term, backward);\n\t\t\treturn `${quoteDuckdbIdent(term.column)} ${descending ? \"DESC\" : \"ASC\"} NULLS ${nullsLast ? \"LAST\" : \"FIRST\"}`;\n\t\t})\n\t\t.join(\", \")}`;\n\n/**\n * Rows after the `cursor` row in `buildOrderBy(terms, backward)` order:\n * `(c1 after v1) OR (c1 = v1 AND c2 after v2) OR …`, where \"after\" follows each column's own\n * direction and NULL placement. A row-value comparison `(c1, c2) > (v1, v2)` cannot express\n * mixed directions and never matches NULL.\n */\nexport function buildKeysetPredicate(\n\tterms: OrderTerm[],\n\tcursor: Record<string, unknown>,\n\tbackward: boolean,\n): { clause: string; values: unknown[] } {\n\tconst branches: string[] = [];\n\tconst values: unknown[] = [];\n\tconst equal: string[] = [];\n\tconst equalValues: unknown[] = [];\n\n\tfor (const term of terms) {\n\t\tconst col = quoteDuckdbIdent(term.column);\n\t\tconst value = cursor[term.column] ?? null;\n\t\tconst { descending, nullsLast } = placement(term, backward);\n\n\t\tconst after =\n\t\t\tvalue === null\n\t\t\t\t? nullsLast\n\t\t\t\t\t? null\n\t\t\t\t\t: `${col} IS NOT NULL`\n\t\t\t\t: `${col} ${descending ? \"<\" : \">\"} ?${nullsLast ? ` OR ${col} IS NULL` : \"\"}`;\n\t\tif (after) {\n\t\t\tbranches.push(`(${[...equal, `(${after})`].join(\" AND \")})`);\n\t\t\tvalues.push(...equalValues, ...(value === null ? [] : [value]));\n\t\t}\n\n\t\tif (value === null) {\n\t\t\tequal.push(`${col} IS NULL`);\n\t\t} else {\n\t\t\tequal.push(`${col} = ?`);\n\t\t\tequalValues.push(value);\n\t\t}\n\t}\n\n\treturn { clause: branches.length ? `(${branches.join(\" OR \")})` : \"FALSE\", values };\n}\n\nconst SERIAL_TYPES = new Set([\n\t\"serial\",\n\t\"serial4\",\n\t\"bigserial\",\n\t\"serial8\",\n\t\"smallserial\",\n\t\"serial2\",\n]);\n\nexport const isSerialType = (columnType: string) =>\n\tSERIAL_TYPES.has(columnType.toLowerCase().trim());\n\n/** Translate a PostgreSQL type name from the web form into a DuckDB column type. */\nexport function mapColumnTypeToDuckdb(columnType: string, isArray: boolean): string {\n\tconst normalized = columnType.toLowerCase().trim();\n\tconst typeMap: Record<string, string> = {\n\t\tserial: \"INTEGER\",\n\t\tserial4: \"INTEGER\",\n\t\tbigserial: \"BIGINT\",\n\t\tserial8: \"BIGINT\",\n\t\tsmallserial: \"SMALLINT\",\n\t\tserial2: \"SMALLINT\",\n\t\tint: \"INTEGER\",\n\t\tint4: \"INTEGER\",\n\t\tinteger: \"INTEGER\",\n\t\tbigint: \"BIGINT\",\n\t\tint8: \"BIGINT\",\n\t\tsmallint: \"SMALLINT\",\n\t\tint2: \"SMALLINT\",\n\t\tnumeric: \"DECIMAL(18, 3)\",\n\t\tdecimal: \"DECIMAL(18, 3)\",\n\t\treal: \"FLOAT\",\n\t\tfloat4: \"FLOAT\",\n\t\tfloat: \"DOUBLE\",\n\t\t\"double precision\": \"DOUBLE\",\n\t\tfloat8: \"DOUBLE\",\n\t\tmoney: \"DECIMAL(19, 4)\",\n\t\tboolean: \"BOOLEAN\",\n\t\tbool: \"BOOLEAN\",\n\t\ttext: \"VARCHAR\",\n\t\tvarchar: \"VARCHAR\",\n\t\t\"character varying\": \"VARCHAR\",\n\t\tchar: \"VARCHAR\",\n\t\tcharacter: \"VARCHAR\",\n\t\tbpchar: \"VARCHAR\",\n\t\tuuid: \"UUID\",\n\t\tjson: \"JSON\",\n\t\tjsonb: \"JSON\",\n\t\txml: \"VARCHAR\",\n\t\tdate: \"DATE\",\n\t\ttime: \"TIME\",\n\t\t\"time without time zone\": \"TIME\",\n\t\ttimestamp: \"TIMESTAMP\",\n\t\t\"timestamp without time zone\": \"TIMESTAMP\",\n\t\t\"timestamp with time zone\": \"TIMESTAMPTZ\",\n\t\ttimestamptz: \"TIMESTAMPTZ\",\n\t\tinterval: \"INTERVAL\",\n\t\tbytea: \"BLOB\",\n\t\tinet: \"VARCHAR\",\n\t\tcidr: \"VARCHAR\",\n\t\tmacaddr: \"VARCHAR\",\n\t\tmacaddr8: \"VARCHAR\",\n\t\tpoint: \"VARCHAR\",\n\t\tline: \"VARCHAR\",\n\t\tpolygon: \"VARCHAR\",\n\t};\n\tconst mapped = typeMap[normalized] ?? columnType.toUpperCase();\n\treturn isArray ? `${mapped}[]` : mapped;\n}\n","import { statSync } from \"node:fs\";\nimport type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tRelatedRecord,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tTableDataResultSchemaType,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { mapDuckdbToDataType, standardizeDuckdbDataTypeLabel } from \"@db-studio/shared/types\";\nimport {\n\ttype DuckDBConnection,\n\ttype DuckDBResultReader,\n\tDuckDBTypeId,\n\ttype DuckDBValue,\n\ttype Json,\n\tResultReturnType,\n\tStatementType,\n} from \"@duckdb/node-api\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { withDuckdbConnection } from \"@/adapters/connections.js\";\nimport {\n\tbuildFilterConditions,\n\tbuildKeysetPredicate,\n\tbuildOrderBy,\n\tquoteDuckdbIdent as ident,\n\tisSerialType,\n\tmapColumnTypeToDuckdb,\n\ttype OrderTerm,\n\twhereSql,\n} from \"./duckdb.query-builder.js\";\n\ntype Row = Record<string, Json>;\n\n/** One FOREIGN KEY constraint; composite keys keep their columns together, in order. */\ntype ForeignKey = {\n\tconstraintName: string;\n\ttable: string;\n\tcolumns: string[];\n\treferencedTable: string;\n\treferencedColumns: string[];\n};\n\ntype ColumnRow = {\n\tcolumn_name: string;\n\tdata_type: string;\n\tis_nullable: boolean;\n\tcolumn_default: string | null;\n};\n\nconst IN_CURRENT_SCHEMA =\n\t\"database_name = current_database() AND schema_name = current_schema()\";\n\nconst BIG_INTEGER_TYPES = new Set<DuckDBTypeId>([\n\tDuckDBTypeId.BIGINT,\n\tDuckDBTypeId.UBIGINT,\n\tDuckDBTypeId.HUGEINT,\n\tDuckDBTypeId.UHUGEINT,\n]);\n\n/**\n * The driver boundary for reads. `getRowObjectsJson()` already renders every DuckDB value\n * JSON-safe (decimals, dates and timestamps as strings, LIST/STRUCT/MAP as JSON), but it\n * renders all 64/128-bit integers as strings; turn the ones that fit a double back into numbers.\n */\nconst toRows = (reader: DuckDBResultReader): Row[] => {\n\tconst types = reader.columnTypes();\n\tconst bigColumns = reader\n\t\t.columnNames()\n\t\t.filter((_, i) => BIG_INTEGER_TYPES.has(types[i].typeId));\n\tconst rows = reader.getRowObjectsJson();\n\tfor (const row of rows) {\n\t\tfor (const column of bigColumns) {\n\t\t\tconst value = row[column];\n\t\t\tif (typeof value === \"string\" && Number.isSafeInteger(Number(value)))\n\t\t\t\trow[column] = Number(value);\n\t\t}\n\t}\n\treturn rows;\n};\n\n/** The driver boundary for writes. DuckDB casts the bound value to the column type. */\nconst toDuckdbValue = (value: unknown): DuckDBValue => {\n\tif (value === null || value === undefined) return null;\n\tif (\n\t\ttypeof value === \"string\" ||\n\t\ttypeof value === \"number\" ||\n\t\ttypeof value === \"boolean\" ||\n\t\ttypeof value === \"bigint\"\n\t)\n\t\treturn value;\n\tif (value instanceof Date) return value.toISOString();\n\treturn JSON.stringify(value);\n};\n\nconst query = async <T extends Row = Row>(\n\tconn: DuckDBConnection,\n\tsql: string,\n\tvalues: unknown[] = [],\n): Promise<T[]> => toRows(await conn.runAndReadAll(sql, values.map(toDuckdbValue))) as T[];\n\nconst execute = async (conn: DuckDBConnection, sql: string, values: unknown[] = []) =>\n\t(await conn.runAndReadAll(sql, values.map(toDuckdbValue))).rowsChanged;\n\nconst inTransaction = async <T>(conn: DuckDBConnection, fn: () => Promise<T>): Promise<T> => {\n\tawait conn.run(\"BEGIN TRANSACTION\");\n\ttry {\n\t\tconst result = await fn();\n\t\tawait conn.run(\"COMMIT\");\n\t\treturn result;\n\t} catch (e) {\n\t\tawait conn.run(\"ROLLBACK\").catch(() => {});\n\t\tthrow e;\n\t}\n};\n\nconst placeholders = (values: unknown[]) => values.map(() => \"?\").join(\", \");\n\n/** Join condition from a referencing row `c` to the referenced row `p`. */\nconst joinOn = (fk: ForeignKey) =>\n\tfk.columns\n\t\t.map((c, i) => `c.${ident(c)} = p.${ident(fk.referencedColumns[i])}`)\n\t\t.join(\" AND \");\n\nconst sequenceNamesIn = (columns: ColumnRow[]) =>\n\tcolumns.flatMap((c) =>\n\t\t[...(c.column_default ?? \"\").matchAll(/nextval\\('([^']+)'\\)/g)].map((m) => m[1]),\n\t);\n\n/** DuckDB limitations that surface as engine errors; each maps to a 400 with a readable reason. */\nconst LIMITATIONS: Array<[signature: string, reason: string]> = [\n\t[\n\t\t\"Dependency Error\",\n\t\t\"DuckDB cannot alter or rename a table that another table's foreign key references or that has an index. Drop the referencing table or the index first.\",\n\t],\n\t[\n\t\t\"has a CHECK constraint\",\n\t\t\"DuckDB cannot change the type of a column that has a CHECK constraint.\",\n\t],\n\t[\n\t\t\"an index depends on it\",\n\t\t\"DuckDB cannot alter or drop a column covered by an index, primary key or unique constraint.\",\n\t],\n];\n\nconst FK_ACTIONS_DUCKDB_REJECTS = new Set([\"CASCADE\", \"SET NULL\", \"SET DEFAULT\"]);\n\nexport class DuckDbAdapter extends BaseAdapter {\n\t// =========================================================\n\t// Abstract method implementations\n\t// =========================================================\n\n\tprotected async runQuery<T>(_db: string, sql: string, values: unknown[]): Promise<T> {\n\t\treturn withDuckdbConnection((conn) => query(conn, sql, values)) as Promise<T>;\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn ident(name);\n\t}\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\treturn mapDuckdbToDataType(nativeType);\n\t}\n\n\tmapFromUniversalType(universalType: string): string {\n\t\tconst map: Record<string, string> = {\n\t\t\ttext: \"VARCHAR\",\n\t\t\tnumber: \"DOUBLE\",\n\t\t\tboolean: \"BOOLEAN\",\n\t\t\tjson: \"JSON\",\n\t\t\tdate: \"TIMESTAMP\",\n\t\t\tarray: \"VARCHAR[]\",\n\t\t\tenum: \"VARCHAR\",\n\t\t};\n\t\treturn map[universalType] ?? \"VARCHAR\";\n\t}\n\n\t// getTableData is overridden: keyset pagination needs the table's key columns and column\n\t// types, which the synchronous template hooks cannot look up.\n\tprotected buildTableDataQuery(_params: GetTableDataParams): QueryBundle {\n\t\tthrow new Error(\"DuckDbAdapter.getTableData builds its own query\");\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn (rawRows as Row[]).map((row) => this.normalizeRow(row));\n\t}\n\n\tprotected buildCursors(): { nextCursor: string | null; prevCursor: string | null } {\n\t\tthrow new Error(\"DuckDbAdapter.getTableData builds its own cursors\");\n\t}\n\n\tprotected override wrapError(e: unknown): HTTPException {\n\t\tif (e instanceof Error) {\n\t\t\tconst limitation = LIMITATIONS.find(([signature]) => e.message.includes(signature));\n\t\t\tif (limitation)\n\t\t\t\treturn new HTTPException(400, {\n\t\t\t\t\tmessage: `${limitation[1]} (${e.message})`,\n\t\t\t\t\tcause: e,\n\t\t\t\t});\n\t\t}\n\t\treturn super.wrapError(e);\n\t}\n\n\tprivate withConnection<T>(fn: (conn: DuckDBConnection) => Promise<T>): Promise<T> {\n\t\treturn withDuckdbConnection(fn).catch((e) => {\n\t\t\tthrow this.wrapError(e);\n\t\t});\n\t}\n\n\t// =========================================================\n\t// Records — paginated read\n\t// =========================================================\n\n\toverride async getTableData(params: GetTableDataParams): Promise<TableDataResultSchemaType> {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tlimit = 50,\n\t\t\tdirection = \"asc\",\n\t\t\tsort = [],\n\t\t\torder = \"asc\",\n\t\t\tcursor,\n\t\t\tfilters = [],\n\t\t} = params;\n\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tawait this.requireColumns(conn, tableName);\n\t\t\tconst primaryKey = await this.primaryKey(conn, tableName);\n\t\t\tconst terms: OrderTerm[] = this.orderTerms(\n\t\t\t\tsort,\n\t\t\t\torder,\n\t\t\t\tprimaryKey.length ? primaryKey : [\"rowid\"],\n\t\t\t);\n\n\t\t\tconst backward = direction === \"desc\";\n\t\t\tconst filter = buildFilterConditions(filters);\n\t\t\tconst cursorData = cursor ? this.decodeCursor(cursor) : null;\n\t\t\tconst keyset = cursorData\n\t\t\t\t? buildKeysetPredicate(terms, cursorData.values, backward)\n\t\t\t\t: null;\n\t\t\tconst orderBy = buildOrderBy(terms, backward);\n\t\t\tconst select = primaryKey.length ? \"*\" : \"*, rowid\";\n\t\t\tconst where = whereSql(\n\t\t\t\tkeyset ? [...filter.conditions, keyset.clause] : filter.conditions,\n\t\t\t);\n\n\t\t\tconst [countRow] = await query(\n\t\t\t\tconn,\n\t\t\t\t`SELECT COUNT(*) AS total FROM ${ident(tableName)} ${whereSql(filter.conditions)}`,\n\t\t\t\tfilter.values,\n\t\t\t);\n\t\t\tconst fetched = await query(\n\t\t\t\tconn,\n\t\t\t\t`SELECT ${select} FROM ${ident(tableName)} ${where} ${orderBy} LIMIT ?`,\n\t\t\t\t[...filter.values, ...(keyset?.values ?? []), limit + 1],\n\t\t\t);\n\n\t\t\tconst hasMore = fetched.length > limit;\n\t\t\tconst page = fetched.slice(0, limit);\n\t\t\tif (backward) page.reverse();\n\n\t\t\tconst cursorOf = (row: Row) =>\n\t\t\t\tthis.encodeCursor({\n\t\t\t\t\tvalues: Object.fromEntries(terms.map((t) => [t.column, row[t.column]])),\n\t\t\t\t\tsortColumns: terms.map((t) => t.column),\n\t\t\t\t});\n\t\t\tconst first = page[0];\n\t\t\tconst last = page.at(-1);\n\t\t\tconst hasNextPage = backward ? !!cursor : hasMore;\n\t\t\tconst hasPreviousPage = backward ? hasMore : !!cursor;\n\n\t\t\treturn {\n\t\t\t\tdata: page.map((row) => {\n\t\t\t\t\tif (primaryKey.length) return this.normalizeRow(row);\n\t\t\t\t\tconst { rowid: _rowid, ...rest } = row;\n\t\t\t\t\treturn this.normalizeRow(rest);\n\t\t\t\t}),\n\t\t\t\tmeta: {\n\t\t\t\t\tlimit,\n\t\t\t\t\ttotal: Number(countRow?.total ?? 0),\n\t\t\t\t\thasNextPage,\n\t\t\t\t\thasPreviousPage,\n\t\t\t\t\tnextCursor: hasNextPage && last ? cursorOf(last) : null,\n\t\t\t\t\tprevCursor: hasPreviousPage && first ? cursorOf(first) : null,\n\t\t\t\t},\n\t\t\t};\n\t\t});\n\t}\n\n\t// =========================================================\n\t// Databases\n\t// =========================================================\n\n\tasync getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst rows = await query<{ database_name: string; path: string | null }>(\n\t\t\t\tconn,\n\t\t\t\t\"SELECT database_name, path FROM duckdb_databases() WHERE database_name = current_database()\",\n\t\t\t);\n\t\t\treturn rows.map((row) => ({\n\t\t\t\tname: row.database_name,\n\t\t\t\tsize: this.getFileSize(row.path),\n\t\t\t\towner: \"\",\n\t\t\t\tencoding: \"UTF-8\",\n\t\t\t}));\n\t\t});\n\t}\n\n\tasync getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst [row] = await query<{ db: string }>(conn, \"SELECT current_database() AS db\");\n\t\t\treturn { db: row.db };\n\t\t});\n\t}\n\n\tasync getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst [row] = await query<{ db: string; version: string }>(\n\t\t\t\tconn,\n\t\t\t\t\"SELECT current_database() AS db, version() AS version\",\n\t\t\t);\n\t\t\treturn {\n\t\t\t\thost: null,\n\t\t\t\tport: null,\n\t\t\t\tuser: \"\",\n\t\t\t\tdatabase: row.db,\n\t\t\t\tversion: `DuckDB ${row.version}`,\n\t\t\t\tactive_connections: 1,\n\t\t\t\tmax_connections: 1,\n\t\t\t};\n\t\t});\n\t}\n\n\t// =========================================================\n\t// Tables\n\t// =========================================================\n\n\tasync getTablesList(_db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst tables = await query<{ table_name: string }>(\n\t\t\t\tconn,\n\t\t\t\t`SELECT table_name FROM duckdb_tables() WHERE ${IN_CURRENT_SCHEMA} AND NOT temporary ORDER BY table_name`,\n\t\t\t);\n\t\t\tconst result: TableInfoSchemaType[] = [];\n\t\t\tfor (const { table_name } of tables) {\n\t\t\t\tconst [row] = await query<{ count: number }>(\n\t\t\t\t\tconn,\n\t\t\t\t\t`SELECT COUNT(*) AS count FROM ${ident(table_name)}`,\n\t\t\t\t);\n\t\t\t\tresult.push({ tableName: table_name, rowCount: Number(row?.count ?? 0) });\n\t\t\t}\n\t\t\treturn result;\n\t\t});\n\t}\n\n\tasync createTable({ tableData }: { tableData: CreateTableSchemaType }): Promise<void> {\n\t\tconst { tableName, fields, foreignKeys = [] } = tableData;\n\n\t\tfor (const fk of foreignKeys) {\n\t\t\tconst rejected = [fk.onUpdate, fk.onDelete].find((a) =>\n\t\t\t\tFK_ACTIONS_DUCKDB_REJECTS.has(a),\n\t\t\t);\n\t\t\tif (rejected)\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `DuckDB foreign keys do not support ${rejected} (on \"${fk.columnName}\"). Use NO ACTION or RESTRICT.`,\n\t\t\t\t});\n\t\t}\n\n\t\tconst sequences: string[] = [];\n\t\tconst primaryKey = fields.filter((f) => f.isPrimaryKey).map((f) => f.columnName);\n\t\tconst columnDefs = fields.map((field) => {\n\t\t\tlet def = `${ident(field.columnName)} ${mapColumnTypeToDuckdb(field.columnType, field.isArray)}`;\n\t\t\tif (primaryKey.length === 1 && field.isPrimaryKey) def += \" PRIMARY KEY\";\n\t\t\tif (field.isUnique && !field.isPrimaryKey) def += \" UNIQUE\";\n\t\t\tif (!field.isNullable && !field.isPrimaryKey) def += \" NOT NULL\";\n\t\t\tif (field.isIdentity || isSerialType(field.columnType)) {\n\t\t\t\tconst sequence = `${tableName}_${field.columnName}_seq`;\n\t\t\t\tsequences.push(sequence);\n\t\t\t\tdef += ` DEFAULT nextval('${sequence.replaceAll(\"'\", \"''\")}')`;\n\t\t\t} else if (field.defaultValue?.trim()) {\n\t\t\t\tdef += ` DEFAULT ${field.defaultValue.trim()}`;\n\t\t\t}\n\t\t\treturn def;\n\t\t});\n\t\tif (primaryKey.length > 1)\n\t\t\tcolumnDefs.push(`PRIMARY KEY (${primaryKey.map(ident).join(\", \")})`);\n\t\tconst fkDefs = foreignKeys.map(\n\t\t\t(fk) =>\n\t\t\t\t`FOREIGN KEY (${ident(fk.columnName)}) REFERENCES ${ident(fk.referencedTable)} (${ident(fk.referencedColumn)}) ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}`,\n\t\t);\n\n\t\tawait this.withConnection((conn) =>\n\t\t\tinTransaction(conn, async () => {\n\t\t\t\tfor (const sequence of sequences) await conn.run(`CREATE SEQUENCE ${ident(sequence)}`);\n\t\t\t\tawait conn.run(\n\t\t\t\t\t`CREATE TABLE ${ident(tableName)} (${[...columnDefs, ...fkDefs].join(\", \")})`,\n\t\t\t\t);\n\t\t\t}),\n\t\t);\n\t}\n\n\tasync deleteTable({ tableName, cascade }: DeleteTableParams): Promise<DeleteTableResult> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst columns = await this.requireColumns(conn, tableName);\n\t\t\tconst referencing = (await this.foreignKeys(conn, \"referenced_table\", tableName)).filter(\n\t\t\t\t(fk) => fk.table !== tableName,\n\t\t\t);\n\t\t\tif (referencing.length) {\n\t\t\t\tif (cascade)\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: `DuckDB cannot drop \"${tableName}\" while ${[...new Set(referencing.map((fk) => `\"${fk.table}\"`))].join(\", \")} reference it, and it cannot remove those foreign keys. Delete the referencing tables first.`,\n\t\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tdeletedCount: 0,\n\t\t\t\t\tfkViolation: true,\n\t\t\t\t\trelatedRecords: await this.sampleReferencingRows(conn, referencing),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst [row] = await query<{ count: number }>(\n\t\t\t\tconn,\n\t\t\t\t`SELECT COUNT(*) AS count FROM ${ident(tableName)}`,\n\t\t\t);\n\t\t\tawait conn.run(`DROP TABLE ${ident(tableName)}`);\n\t\t\tfor (const sequence of sequenceNamesIn(columns)) {\n\t\t\t\t// A sequence another table still uses stays; DuckDB refuses with a Dependency Error.\n\t\t\t\tawait conn.run(`DROP SEQUENCE IF EXISTS ${ident(sequence)}`).catch(() => {});\n\t\t\t}\n\t\t\treturn { deletedCount: Number(row?.count ?? 0), fkViolation: false, relatedRecords: [] };\n\t\t});\n\t}\n\n\tasync renameTable({ tableName, newTableName }: RenameTableParamsSchemaType): Promise<void> {\n\t\tthis.assertDifferentTableName(tableName, newTableName);\n\t\tawait this.withConnection(async (conn) => {\n\t\t\tawait this.requireColumns(conn, tableName);\n\t\t\tif ((await this.columns(conn, newTableName)).length)\n\t\t\t\tthrow new HTTPException(409, { message: `Table \"${newTableName}\" already exists` });\n\t\t\tawait conn.run(`ALTER TABLE ${ident(tableName)} RENAME TO ${ident(newTableName)}`);\n\t\t});\n\t}\n\n\tasync getTableSchema({ tableName }: { tableName: string }): Promise<string> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst [row] = await query<{ sql: string }>(\n\t\t\t\tconn,\n\t\t\t\t`SELECT sql FROM duckdb_tables() WHERE ${IN_CURRENT_SCHEMA} AND table_name = ?`,\n\t\t\t\t[tableName],\n\t\t\t);\n\t\t\tif (!row)\n\t\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t\treturn row.sql;\n\t\t});\n\t}\n\n\t// =========================================================\n\t// Columns\n\t// =========================================================\n\n\tasync getTableColumns({\n\t\ttableName,\n\t}: {\n\t\ttableName: string;\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst columns = await this.requireColumns(conn, tableName);\n\t\t\tconst primaryKey = new Set(await this.primaryKey(conn, tableName));\n\t\t\tconst references = new Map(\n\t\t\t\t(await this.foreignKeys(conn, \"table_name\", tableName)).flatMap((fk) =>\n\t\t\t\t\tfk.columns.map((column, i) => [\n\t\t\t\t\t\tcolumn,\n\t\t\t\t\t\t{ table: fk.referencedTable, column: fk.referencedColumns[i] },\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t);\n\n\t\t\treturn columns.map((col) => {\n\t\t\t\tconst fk = references.get(col.column_name);\n\t\t\t\tconst isPrimaryKey = primaryKey.has(col.column_name);\n\t\t\t\treturn {\n\t\t\t\t\tcolumnName: col.column_name,\n\t\t\t\t\tdataType: mapDuckdbToDataType(col.data_type),\n\t\t\t\t\tdataTypeLabel: standardizeDuckdbDataTypeLabel(col.data_type),\n\t\t\t\t\tisNullable: col.is_nullable && !isPrimaryKey,\n\t\t\t\t\tcolumnDefault: col.column_default,\n\t\t\t\t\tisPrimaryKey,\n\t\t\t\t\tisForeignKey: !!fk,\n\t\t\t\t\treferencedTable: fk?.table ?? null,\n\t\t\t\t\treferencedColumn: fk?.column ?? null,\n\t\t\t\t\tenumValues: col.data_type.startsWith(\"ENUM(\")\n\t\t\t\t\t\t? [...col.data_type.matchAll(/'((?:[^']|'')*)'/g)].map((m) =>\n\t\t\t\t\t\t\t\tm[1].replaceAll(\"''\", \"'\"),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: null,\n\t\t\t\t};\n\t\t\t});\n\t\t});\n\t}\n\n\tasync addColumn(params: AddColumnParamsSchemaType): Promise<void> {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tcolumnName,\n\t\t\tcolumnType,\n\t\t\tdefaultValue,\n\t\t\tisNullable,\n\t\t\tisUnique,\n\t\t\tisPrimaryKey,\n\t\t} = params;\n\t\tif (isUnique || isPrimaryKey)\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: `DuckDB cannot add a ${isPrimaryKey ? \"PRIMARY KEY\" : \"UNIQUE\"} column to an existing table. Add the column without it, or recreate the table.`,\n\t\t\t});\n\n\t\tconst sequence =\n\t\t\tparams.isIdentity || isSerialType(columnType) ? `${tableName}_${columnName}_seq` : null;\n\t\tlet def = `${ident(columnName)} ${mapColumnTypeToDuckdb(columnType, params.isArray)}`;\n\t\tif (sequence) def += ` DEFAULT nextval('${sequence.replaceAll(\"'\", \"''\")}')`;\n\t\telse if (defaultValue?.trim()) def += ` DEFAULT ${defaultValue.trim()}`;\n\n\t\tawait this.withConnection(async (conn) => {\n\t\t\tconst columns = await this.requireColumns(conn, tableName);\n\t\t\tif (columns.some((c) => c.column_name === columnName))\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Column \"${columnName}\" already exists in table \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t// DuckDB rejects constraints inside ADD COLUMN, so NOT NULL is applied afterwards.\n\t\t\tawait inTransaction(conn, async () => {\n\t\t\t\tif (sequence) await conn.run(`CREATE SEQUENCE ${ident(sequence)}`);\n\t\t\t\tawait conn.run(`ALTER TABLE ${ident(tableName)} ADD COLUMN ${def}`);\n\t\t\t\tif (!isNullable)\n\t\t\t\t\tawait conn\n\t\t\t\t\t\t.run(\n\t\t\t\t\t\t\t`ALTER TABLE ${ident(tableName)} ALTER COLUMN ${ident(columnName)} SET NOT NULL`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.catch((e) => {\n\t\t\t\t\t\t\tif (!String(e).includes(\"NOT NULL constraint failed\")) throw e;\n\t\t\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\t\t\tmessage: `Column \"${columnName}\" needs a default value to be NOT NULL, because \"${tableName}\" already has rows.`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t});\n\t\t});\n\t}\n\n\tasync deleteColumn({\n\t\ttableName,\n\t\tcolumnName,\n\t}: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\tawait this.withConnection(async (conn) => {\n\t\t\tawait this.requireColumn(conn, tableName, columnName);\n\t\t\tawait conn.run(`ALTER TABLE ${ident(tableName)} DROP COLUMN ${ident(columnName)}`);\n\t\t});\n\t\treturn { deletedCount: 1 };\n\t}\n\n\tasync alterColumn(params: AlterColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, columnType, isNullable, defaultValue } = params;\n\t\tconst alter = `ALTER TABLE ${ident(tableName)} ALTER COLUMN ${ident(columnName)}`;\n\t\tawait this.withConnection(async (conn) => {\n\t\t\tawait this.requireColumn(conn, tableName, columnName);\n\t\t\tawait inTransaction(conn, async () => {\n\t\t\t\tawait conn.run(`${alter} TYPE ${mapColumnTypeToDuckdb(columnType, false)}`);\n\t\t\t\tawait conn.run(`${alter} ${isNullable ? \"DROP\" : \"SET\"} NOT NULL`);\n\t\t\t\tawait conn.run(\n\t\t\t\t\tdefaultValue?.trim()\n\t\t\t\t\t\t? `${alter} SET DEFAULT ${defaultValue.trim()}`\n\t\t\t\t\t\t: `${alter} DROP DEFAULT`,\n\t\t\t\t);\n\t\t\t});\n\t\t});\n\t}\n\n\tasync renameColumn({\n\t\ttableName,\n\t\tcolumnName,\n\t\tnewColumnName,\n\t}: RenameColumnParamsSchemaType): Promise<void> {\n\t\tawait this.withConnection(async (conn) => {\n\t\t\tconst columns = await this.requireColumn(conn, tableName, columnName);\n\t\t\tif (columns.some((c) => c.column_name === newColumnName))\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Column \"${newColumnName}\" already exists in table \"${tableName}\"`,\n\t\t\t\t});\n\t\t\tawait conn.run(\n\t\t\t\t`ALTER TABLE ${ident(tableName)} RENAME COLUMN ${ident(columnName)} TO ${ident(newColumnName)}`,\n\t\t\t);\n\t\t});\n\t}\n\n\t// =========================================================\n\t// Records\n\t// =========================================================\n\n\tasync addRecord({\n\t\tparams,\n\t}: {\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\tconst { tableName, data } = params;\n\t\tconst columns = Object.keys(data);\n\t\tif (!columns.length)\n\t\t\tthrow new HTTPException(400, { message: \"No data provided for insert\" });\n\n\t\tconst insertedCount = await this.withConnection((conn) =>\n\t\t\texecute(\n\t\t\t\tconn,\n\t\t\t\t`INSERT INTO ${ident(tableName)} (${columns.map(ident).join(\", \")}) VALUES (${placeholders(columns)})`,\n\t\t\t\tObject.values(data),\n\t\t\t),\n\t\t);\n\t\treturn { insertedCount };\n\t}\n\n\tasync updateRecords({\n\t\tparams,\n\t}: {\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\tconst { tableName } = params;\n\t\tconst keyColumns = this.resolveKeyColumns(params);\n\t\tconst groups = this.groupUpdatesByKey(params, keyColumns);\n\n\t\tconst updatedCount = await this.withConnection((conn) =>\n\t\t\tinTransaction(conn, async () => {\n\t\t\t\tthis.assertWholeKey(await this.primaryKey(conn, tableName), keyColumns);\n\t\t\t\tlet total = 0;\n\t\t\t\tfor (const { keyValues, rowUpdates } of groups) {\n\t\t\t\t\tconst changed = await execute(\n\t\t\t\t\t\tconn,\n\t\t\t\t\t\t`UPDATE ${ident(tableName)} SET ${rowUpdates.map((u) => `${ident(u.columnName)} = ?`).join(\", \")} WHERE ${keyColumns.map((c) => `${ident(c)} = ?`).join(\" AND \")}`,\n\t\t\t\t\t\t[...rowUpdates.map((u) => u.value), ...keyValues],\n\t\t\t\t\t);\n\t\t\t\t\tif (changed === 0)\n\t\t\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\t\t\tmessage: `Record with ${this.describeKey(keyColumns, keyValues)} not found in table \"${tableName}\"`,\n\t\t\t\t\t\t});\n\t\t\t\t\ttotal += changed;\n\t\t\t\t}\n\t\t\t\treturn total;\n\t\t\t}),\n\t\t);\n\t\treturn { updatedCount };\n\t}\n\n\tasync deleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t}: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\t\tconst values = primaryKeys.map((pk) => pk.value);\n\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tthis.assertDeletableKey(await this.primaryKey(conn, tableName));\n\t\t\ttry {\n\t\t\t\tconst deletedCount = await execute(\n\t\t\t\t\tconn,\n\t\t\t\t\t`DELETE FROM ${ident(tableName)} WHERE ${ident(pkColumn)} IN (${placeholders(values)})`,\n\t\t\t\t\tvalues,\n\t\t\t\t);\n\t\t\t\treturn { deletedCount, fkViolation: false, relatedRecords: [] };\n\t\t\t} catch (e) {\n\t\t\t\tif (!(e instanceof Error) || !e.message.includes(\"Violates foreign key constraint\"))\n\t\t\t\t\tthrow e;\n\t\t\t\tconst relatedRecords: RelatedRecord[] = [];\n\t\t\t\tfor (const fk of await this.foreignKeys(conn, \"referenced_table\", tableName)) {\n\t\t\t\t\tconst records = await query(\n\t\t\t\t\t\tconn,\n\t\t\t\t\t\t`SELECT c.* FROM ${ident(fk.table)} c JOIN ${ident(tableName)} p ON ${joinOn(fk)} WHERE p.${ident(pkColumn)} IN (${placeholders(values)}) LIMIT 100`,\n\t\t\t\t\t\tvalues,\n\t\t\t\t\t);\n\t\t\t\t\tif (records.length)\n\t\t\t\t\t\trelatedRecords.push({\n\t\t\t\t\t\t\ttableName: fk.table,\n\t\t\t\t\t\t\tcolumnName: fk.columns.join(\", \"),\n\t\t\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\t\t\trecords,\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t});\n\t}\n\n\tasync forceDeleteRecords(params: DeleteRecordParams): Promise<{ deletedCount: number }> {\n\t\tconst result = await this.deleteRecords(params);\n\t\tif (result.fkViolation) {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage:\n\t\t\t\t\t\"DuckDB cannot atomically delete a row and its dependent rows. Delete the dependent rows explicitly, then retry. Nothing was deleted.\",\n\t\t\t});\n\t\t}\n\t\treturn { deletedCount: result.deletedCount };\n\t}\n\n\tasync bulkInsertRecords({\n\t\ttableName,\n\t\trecords,\n\t}: BulkInsertRecordsParams): Promise<BulkInsertResult> {\n\t\tif (!records?.length)\n\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\n\t\tconst columns = Object.keys(records[0]);\n\t\tconst successCount = await this.withConnection((conn) =>\n\t\t\tinTransaction(conn, async () => {\n\t\t\t\tconst statement = await conn.prepare(\n\t\t\t\t\t`INSERT INTO ${ident(tableName)} (${columns.map(ident).join(\", \")}) VALUES (${placeholders(columns)})`,\n\t\t\t\t);\n\t\t\t\tfor (const record of records) {\n\t\t\t\t\tstatement.bind(columns.map((col) => toDuckdbValue(record[col])));\n\t\t\t\t\tawait statement.run();\n\t\t\t\t}\n\t\t\t\treturn records.length;\n\t\t\t}),\n\t\t);\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tmessage: `Bulk insert completed: ${successCount} records inserted`,\n\t\t\tsuccessCount,\n\t\t\tfailureCount: 0,\n\t\t};\n\t}\n\n\t// =========================================================\n\t// Query\n\t// =========================================================\n\n\tasync executeQuery({ query: sql }: { query: string }): Promise<ExecuteQueryResult> {\n\t\tif (!sql?.trim()) throw new HTTPException(400, { message: \"Query is required\" });\n\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst start = performance.now();\n\t\t\tconst statements = await conn.extractStatements(sql);\n\t\t\tif (statements.count !== 1) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t\"The query runner runs one statement at a time. Run each statement separately.\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst statement = await statements.prepare(0);\n\t\t\ttry {\n\t\t\t\tif (statement.statementType === StatementType.TRANSACTION) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\"Transactions cannot span query-runner requests. BEGIN, COMMIT, and ROLLBACK are not supported.\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst reader = await statement.runAndReadAll();\n\t\t\t\tconst duration = performance.now() - start;\n\n\t\t\t\tif (reader.returnType === ResultReturnType.CHANGED_ROWS)\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcolumns: [],\n\t\t\t\t\t\trows: [],\n\t\t\t\t\t\trowCount: reader.rowsChanged,\n\t\t\t\t\t\tduration,\n\t\t\t\t\t\tmessage: `OK (${reader.rowsChanged} rows affected)`,\n\t\t\t\t\t};\n\t\t\t\tif (reader.returnType === ResultReturnType.NOTHING)\n\t\t\t\t\treturn { columns: [], rows: [], rowCount: 0, duration, message: \"OK\" };\n\n\t\t\t\tconst rows = toRows(reader);\n\t\t\t\treturn {\n\t\t\t\t\tcolumns: reader.columnNames(),\n\t\t\t\t\trows,\n\t\t\t\t\trowCount: rows.length,\n\t\t\t\t\tduration,\n\t\t\t\t\tmessage: rows.length === 0 ? \"OK\" : undefined,\n\t\t\t\t};\n\t\t\t} finally {\n\t\t\t\tstatement.destroySync();\n\t\t\t}\n\t\t});\n\t}\n\n\t// =========================================================\n\t// Private helpers\n\t// =========================================================\n\n\tprivate getFileSize(filePath: string | null): string {\n\t\tif (!filePath) return \"in-memory\";\n\t\ttry {\n\t\t\tconst bytes = statSync(filePath).size;\n\t\t\tif (bytes < 1024) return `${bytes} B`;\n\t\t\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\t\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n\t\t} catch {\n\t\t\treturn \"N/A\";\n\t\t}\n\t}\n\n\tprivate columns(conn: DuckDBConnection, tableName: string): Promise<ColumnRow[]> {\n\t\treturn query<ColumnRow>(\n\t\t\tconn,\n\t\t\t`SELECT column_name, data_type, is_nullable, column_default FROM duckdb_columns() WHERE ${IN_CURRENT_SCHEMA} AND table_name = ? ORDER BY column_index`,\n\t\t\t[tableName],\n\t\t);\n\t}\n\n\tprivate async requireColumns(\n\t\tconn: DuckDBConnection,\n\t\ttableName: string,\n\t): Promise<ColumnRow[]> {\n\t\tconst columns = await this.columns(conn, tableName);\n\t\tif (!columns.length)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\treturn columns;\n\t}\n\n\tprivate async requireColumn(\n\t\tconn: DuckDBConnection,\n\t\ttableName: string,\n\t\tcolumnName: string,\n\t): Promise<ColumnRow[]> {\n\t\tconst columns = await this.requireColumns(conn, tableName);\n\t\tif (!columns.some((c) => c.column_name === columnName))\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\t\treturn columns;\n\t}\n\n\tprivate async primaryKey(conn: DuckDBConnection, tableName: string): Promise<string[]> {\n\t\tconst [row] = await query<{ columns: string[] }>(\n\t\t\tconn,\n\t\t\t`SELECT constraint_column_names AS columns FROM duckdb_constraints() WHERE ${IN_CURRENT_SCHEMA} AND table_name = ? AND constraint_type = 'PRIMARY KEY'`,\n\t\t\t[tableName],\n\t\t);\n\t\treturn row?.columns ?? [];\n\t}\n\n\t/** Foreign keys declared on `tableName` (\"table_name\") or pointing at it (\"referenced_table\"). */\n\tprivate async foreignKeys(\n\t\tconn: DuckDBConnection,\n\t\tside: \"table_name\" | \"referenced_table\",\n\t\ttableName: string,\n\t): Promise<ForeignKey[]> {\n\t\treturn query<ForeignKey>(\n\t\t\tconn,\n\t\t\t`SELECT constraint_name AS \"constraintName\", table_name AS \"table\", constraint_column_names AS \"columns\", referenced_table AS \"referencedTable\", referenced_column_names AS \"referencedColumns\" FROM duckdb_constraints() WHERE ${IN_CURRENT_SCHEMA} AND constraint_type = 'FOREIGN KEY' AND ${side} = ?`,\n\t\t\t[tableName],\n\t\t);\n\t}\n\n\tprivate async sampleReferencingRows(\n\t\tconn: DuckDBConnection,\n\t\treferences: ForeignKey[],\n\t): Promise<RelatedRecord[]> {\n\t\tconst related: RelatedRecord[] = [];\n\t\tfor (const fk of references) {\n\t\t\tconst records = await query(\n\t\t\t\tconn,\n\t\t\t\t`SELECT * FROM ${ident(fk.table)} WHERE ${fk.columns.map((c) => `${ident(c)} IS NOT NULL`).join(\" AND \")} LIMIT 100`,\n\t\t\t);\n\t\t\tif (records.length)\n\t\t\t\trelated.push({\n\t\t\t\t\ttableName: fk.table,\n\t\t\t\t\tcolumnName: fk.columns.join(\", \"),\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords,\n\t\t\t\t});\n\t\t}\n\t\treturn related;\n\t}\n}\n","/**\n * Mongo reports only databases that physically exist, so a freshly created\n * (empty) database never appears in `listDatabases`. Filtering system databases\n * therefore has to re-add the connected database explicitly, otherwise a user\n * connected to an empty database sees an empty selector — or, worse, a fallback\n * that shows exactly the `admin`/`config`/`local` entries we set out to hide.\n */\n\nconst SYSTEM_DATABASES = new Set([\"admin\", \"config\", \"local\"]);\n\nexport interface MongoDatabaseSummary {\n\tname: string;\n\tsizeOnDisk?: number;\n}\n\n/**\n * Hide Mongo's system databases while keeping the connected database visible,\n * whether or not `listDatabases` reported it.\n *\n * @param databases - Raw entries from `admin().listDatabases()`\n * @param currentDb - The database the connection string points at\n */\nexport const visibleMongoDatabases = (\n\tdatabases: readonly MongoDatabaseSummary[],\n\tcurrentDb: string,\n): MongoDatabaseSummary[] => {\n\tconst visible = databases.filter(\n\t\t(db) => !SYSTEM_DATABASES.has(db.name) || db.name === currentDb,\n\t);\n\n\tif (!currentDb || visible.some((db) => db.name === currentDb)) return visible;\n\treturn [...visible, { name: currentDb, sizeOnDisk: 0 }];\n};\n","import type { FilterType, SortDirection, SortType } from \"@db-studio/shared/types\";\nimport { coerceObjectId, isValidObjectId } from \"@/db-manager.js\";\n\nconst escapeRegex = (value: string) => value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\nconst parseFilterValue = (raw: string): unknown => {\n\tconst trimmed = raw.trim();\n\tif (trimmed === \"null\") return null;\n\tif (trimmed === \"true\") return true;\n\tif (trimmed === \"false\") return false;\n\tconst asNumber = Number(trimmed);\n\tif (!Number.isNaN(asNumber) && trimmed !== \"\") return asNumber;\n\tif (isValidObjectId(trimmed)) return coerceObjectId(trimmed);\n\treturn trimmed;\n};\n\nexport function buildMatchStage(filters: FilterType[]): Record<string, unknown> {\n\tif (!filters || filters.length === 0) return {};\n\tconst andConditions: Record<string, unknown>[] = [];\n\n\tfor (const filter of filters) {\n\t\tconst field = filter.columnName;\n\t\tconst value = parseFilterValue(filter.value);\n\t\tconst op = filter.operator.toLowerCase();\n\t\tif (!field) continue;\n\n\t\tswitch (op) {\n\t\t\tcase \"=\":\n\t\t\t\tandConditions.push({ [field]: value });\n\t\t\t\tbreak;\n\t\t\tcase \"!=\":\n\t\t\t\tandConditions.push({ [field]: { $ne: value } });\n\t\t\t\tbreak;\n\t\t\tcase \">\":\n\t\t\t\tandConditions.push({ [field]: { $gt: value } });\n\t\t\t\tbreak;\n\t\t\tcase \">=\":\n\t\t\t\tandConditions.push({ [field]: { $gte: value } });\n\t\t\t\tbreak;\n\t\t\tcase \"<\":\n\t\t\t\tandConditions.push({ [field]: { $lt: value } });\n\t\t\t\tbreak;\n\t\t\tcase \"<=\":\n\t\t\t\tandConditions.push({ [field]: { $lte: value } });\n\t\t\t\tbreak;\n\t\t\tcase \"is\":\n\t\t\t\tandConditions.push({ [field]: value });\n\t\t\t\tbreak;\n\t\t\tcase \"is not\":\n\t\t\t\tandConditions.push({ [field]: { $ne: value } });\n\t\t\t\tbreak;\n\t\t\tcase \"like\":\n\t\t\t\tandConditions.push({ [field]: { $regex: escapeRegex(String(value)), $options: \"\" } });\n\t\t\t\tbreak;\n\t\t\tcase \"not like\":\n\t\t\t\tandConditions.push({\n\t\t\t\t\t[field]: { $not: { $regex: escapeRegex(String(value)), $options: \"\" } },\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"ilike\":\n\t\t\t\tandConditions.push({ [field]: { $regex: escapeRegex(String(value)), $options: \"i\" } });\n\t\t\t\tbreak;\n\t\t\tcase \"not ilike\":\n\t\t\t\tandConditions.push({\n\t\t\t\t\t[field]: { $not: { $regex: escapeRegex(String(value)), $options: \"i\" } },\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tandConditions.push({ [field]: value });\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn andConditions.length ? { $and: andConditions } : {};\n}\n\nexport function buildSortStage(\n\tsort: string | SortType[] | undefined,\n\torder?: SortDirection,\n): Record<string, 1 | -1> {\n\tif (!sort) return { _id: 1 };\n\tif (Array.isArray(sort)) {\n\t\tif (sort.length === 0) return { _id: 1 };\n\t\treturn Object.fromEntries(\n\t\t\tsort.map((s) => [s.columnName, s.direction === \"desc\" ? -1 : 1]),\n\t\t);\n\t}\n\tif (typeof sort === \"string\" && sort.length > 0) {\n\t\treturn { [sort]: order === \"desc\" ? -1 : 1 };\n\t}\n\treturn { _id: 1 };\n}\n\nexport function encodeMongoCursor(offset: number): string {\n\treturn Buffer.from(JSON.stringify({ offset })).toString(\"base64url\");\n}\n\nexport function decodeMongoCursor(cursor?: string): number {\n\tif (!cursor) return 0;\n\ttry {\n\t\tconst parsed = JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf-8\")) as {\n\t\t\toffset?: number;\n\t\t};\n\t\treturn typeof parsed.offset === \"number\" ? parsed.offset : 0;\n\t} catch {\n\t\treturn 0;\n\t}\n}\n","import type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tTableDataResultSchemaType,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getMongoClient, getMongoDb, getMongoDbName } from \"@/adapters/connections.js\";\nimport { coerceObjectId, isValidObjectId } from \"@/db-manager.js\";\nimport { visibleMongoDatabases } from \"@/utils/mongo-database-visibility.js\";\nimport { parseDatabaseUrl } from \"@/utils/parse-database-url.js\";\nimport {\n\tbuildMatchStage,\n\tbuildSortStage,\n\tdecodeMongoCursor,\n\tencodeMongoCursor,\n} from \"./mongo.pipeline-builder.js\";\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst normalizeValue = (value: unknown): unknown => {\n\tif (value instanceof Date) return value.toISOString();\n\tif (typeof value === \"bigint\") return value.toString();\n\tif (value && typeof value === \"object\") {\n\t\tif (\"_bsontype\" in value && (value as { _bsontype?: string })._bsontype === \"ObjectId\") {\n\t\t\treturn (value as unknown as { toHexString: () => string }).toHexString();\n\t\t}\n\t\tif (Array.isArray(value)) return value.map((item) => normalizeValue(item));\n\t\treturn Object.fromEntries(\n\t\t\tObject.entries(value as Record<string, unknown>).map(([k, v]) => [k, normalizeValue(v)]),\n\t\t);\n\t}\n\treturn value;\n};\n\nconst normalizeDoc = (doc: unknown): Record<string, unknown> =>\n\tnormalizeValue(doc) as Record<string, unknown>;\n\nconst inferValueType = (value: unknown): DataTypes => {\n\tif (value instanceof Date) return \"date\";\n\tif (value && typeof value === \"object\") {\n\t\tif (Array.isArray(value)) return \"array\";\n\t\tif (\"_bsontype\" in value) return \"text\";\n\t\treturn \"json\";\n\t}\n\tif (typeof value === \"boolean\") return \"boolean\";\n\tif (typeof value === \"number\" || typeof value === \"bigint\") return \"number\";\n\treturn \"text\";\n};\n\nconst dataTypeLabel = (dt: DataTypes): string => {\n\tswitch (dt) {\n\t\tcase \"number\":\n\t\t\treturn \"numeric\";\n\t\tcase \"boolean\":\n\t\t\treturn \"boolean\";\n\t\tcase \"json\":\n\t\t\treturn \"json\";\n\t\tcase \"date\":\n\t\t\treturn \"date\";\n\t\tcase \"array\":\n\t\t\treturn \"array\";\n\t\tcase \"enum\":\n\t\t\treturn \"enum\";\n\t\tdefault:\n\t\t\treturn \"text\";\n\t}\n};\n\nconst canCoerce = (value: unknown): boolean =>\n\ttypeof value === \"string\" && isValidObjectId(value);\n\nconst toMongoId = (value: unknown) => coerceObjectId(value as string);\n\nconst formatBytes = (bytes: number): string => {\n\tif (!Number.isFinite(bytes)) return \"n/a\";\n\tconst units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n\tlet v = bytes;\n\tlet i = 0;\n\twhile (v >= 1024 && i < units.length - 1) {\n\t\tv /= 1024;\n\t\ti++;\n\t}\n\treturn `${v.toFixed(1)} ${units[i]}`;\n};\n\nconst MONGO_BSON_TYPES = new Set([\n\t\"double\",\n\t\"string\",\n\t\"object\",\n\t\"array\",\n\t\"binData\",\n\t\"undefined\",\n\t\"objectId\",\n\t\"bool\",\n\t\"date\",\n\t\"null\",\n\t\"regex\",\n\t\"dbPointer\",\n\t\"javascript\",\n\t\"symbol\",\n\t\"javascriptWithScope\",\n\t\"int\",\n\t\"timestamp\",\n\t\"long\",\n\t\"decimal\",\n\t\"minKey\",\n\t\"maxKey\",\n]);\n\nconst mapBsonType = (rawType: string): string => {\n\tconst n = rawType.trim();\n\tif (MONGO_BSON_TYPES.has(n)) return n;\n\tswitch (n.toLowerCase()) {\n\t\tcase \"boolean\":\n\t\t\treturn \"bool\";\n\t\tcase \"objectid\":\n\t\t\treturn \"objectId\";\n\t\tcase \"binary\":\n\t\t\treturn \"binData\";\n\t\tdefault:\n\t\t\treturn n;\n\t}\n};\n\nconst inferBsonType = (value: unknown): string => {\n\tif (value === null || value === undefined) return \"null\";\n\tif (value instanceof Date) return \"date\";\n\tif (typeof value === \"boolean\") return \"bool\";\n\tif (typeof value === \"number\") return Number.isInteger(value) ? \"int\" : \"double\";\n\tif (typeof value === \"bigint\") return \"long\";\n\tif (Array.isArray(value)) return \"array\";\n\tif (typeof value === \"object\") {\n\t\tconst bson = (value as { _bsontype?: string })._bsontype;\n\t\tif (bson === \"ObjectId\") return \"objectId\";\n\t\tif (bson === \"Decimal128\") return \"decimal\";\n\t\tif (bson === \"Binary\") return \"binData\";\n\t\tif (bson === \"Timestamp\") return \"timestamp\";\n\t\tif (bson) return bson.toLowerCase();\n\t\treturn \"object\";\n\t}\n\treturn \"string\";\n};\n\nconst resolveFieldDefault = (\n\tdefaultValue: string | null | undefined,\n\tcolumnType: string,\n): unknown => {\n\tif (defaultValue !== undefined && defaultValue !== null && defaultValue.trim() !== \"\") {\n\t\ttry {\n\t\t\treturn JSON.parse(defaultValue);\n\t\t} catch {\n\t\t\treturn defaultValue;\n\t\t}\n\t}\n\tswitch (columnType) {\n\t\tcase \"string\":\n\t\t\treturn \"\";\n\t\tcase \"int\":\n\t\tcase \"long\":\n\t\tcase \"double\":\n\t\tcase \"decimal\":\n\t\t\treturn 0;\n\t\tcase \"bool\":\n\t\t\treturn false;\n\t\tcase \"array\":\n\t\t\treturn [];\n\t\tcase \"object\":\n\t\t\treturn {};\n\t\tcase \"date\":\n\t\t\treturn new Date();\n\t\tdefault:\n\t\t\treturn null;\n\t}\n};\n\nconst normalizeIdFilter = (filter: Record<string, unknown>): Record<string, unknown> => {\n\tif (filter._id && typeof filter._id === \"string\") {\n\t\treturn { ...filter, _id: toMongoId(filter._id) };\n\t}\n\tif (filter._id && typeof filter._id === \"object\") {\n\t\tconst obj = filter._id as Record<string, unknown>;\n\t\tif (Array.isArray(obj.$in)) {\n\t\t\treturn {\n\t\t\t\t...filter,\n\t\t\t\t_id: {\n\t\t\t\t\t...obj,\n\t\t\t\t\t$in: obj.$in.map((v) => (typeof v === \"string\" ? toMongoId(v) : v)),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tif (Array.isArray(obj.$nin)) {\n\t\t\treturn {\n\t\t\t\t...filter,\n\t\t\t\t_id: {\n\t\t\t\t\t...obj,\n\t\t\t\t\t$nin: obj.$nin.map((v) => (typeof v === \"string\" ? toMongoId(v) : v)),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\treturn filter;\n};\n\ntype MongoQueryPayload = {\n\tcollection: string;\n\toperation:\n\t\t| \"find\"\n\t\t| \"aggregate\"\n\t\t| \"insertOne\"\n\t\t| \"insertMany\"\n\t\t| \"updateOne\"\n\t\t| \"updateMany\"\n\t\t| \"deleteOne\"\n\t\t| \"deleteMany\"\n\t\t| \"count\";\n\tfilter?: Record<string, unknown>;\n\tpipeline?: Record<string, unknown>[];\n\tdocument?: Record<string, unknown> | Record<string, unknown>[];\n\tupdate?: Record<string, unknown>;\n\toptions?: Record<string, unknown>;\n\tsort?: Record<string, 1 | -1>;\n\tlimit?: number;\n\tskip?: number;\n};\n\n// ---------------------------------------------------------------------------\n// MongoAdapter\n// ---------------------------------------------------------------------------\n\nexport class MongoAdapter extends BaseAdapter {\n\t// -----------------------------------------------------------------------\n\t// Abstract stubs — MongoDB does not use SQL\n\t// -----------------------------------------------------------------------\n\n\tprotected runQuery<T>(): Promise<T> {\n\t\tthrow new HTTPException(501, { message: \"runQuery is not supported for MongoDB\" });\n\t}\n\n\tprotected buildTableDataQuery(_params: GetTableDataParams): QueryBundle {\n\t\tthrow new HTTPException(501, {\n\t\t\tmessage: \"buildTableDataQuery is not supported for MongoDB\",\n\t\t});\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn rawRows.map((row) => this.normalizeRow(normalizeDoc(row)));\n\t}\n\n\tprotected buildCursors(): { nextCursor: string | null; prevCursor: string | null } {\n\t\treturn { nextCursor: null, prevCursor: null };\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn name;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Type mapping\n\t// -----------------------------------------------------------------------\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\tswitch (nativeType.toLowerCase()) {\n\t\t\tcase \"int\":\n\t\t\tcase \"long\":\n\t\t\tcase \"double\":\n\t\t\tcase \"decimal\":\n\t\t\t\treturn \"number\";\n\t\t\tcase \"bool\":\n\t\t\t\treturn \"boolean\";\n\t\t\tcase \"date\":\n\t\t\t\treturn \"date\";\n\t\t\tcase \"array\":\n\t\t\t\treturn \"array\";\n\t\t\tcase \"object\":\n\t\t\t\treturn \"json\";\n\t\t\tdefault:\n\t\t\t\treturn \"text\";\n\t\t}\n\t}\n\n\tmapFromUniversalType(universalType: string): string {\n\t\tswitch (universalType) {\n\t\t\tcase \"number\":\n\t\t\t\treturn \"double\";\n\t\t\tcase \"boolean\":\n\t\t\t\treturn \"bool\";\n\t\t\tcase \"date\":\n\t\t\t\treturn \"date\";\n\t\t\tcase \"array\":\n\t\t\t\treturn \"array\";\n\t\t\tcase \"json\":\n\t\t\t\treturn \"object\";\n\t\t\tdefault:\n\t\t\t\treturn \"string\";\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// wrapError override — adds MongoDB-specific connection error names\n\t// -----------------------------------------------------------------------\n\n\tprotected override wrapError(e: unknown): HTTPException {\n\t\tif (e instanceof HTTPException) return e;\n\t\tif (e instanceof Error) {\n\t\t\tconst name = (e as { name?: string }).name ?? \"\";\n\t\t\tif (\n\t\t\t\tname === \"MongoNetworkError\" ||\n\t\t\t\tname === \"MongoServerSelectionError\" ||\n\t\t\t\tname === \"MongoTopologyClosedError\"\n\t\t\t) {\n\t\t\t\treturn new HTTPException(503, { message: e.message, cause: e });\n\t\t\t}\n\t\t}\n\t\treturn super.wrapError(e);\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// getTableData — full override (skip/limit pagination)\n\t// -----------------------------------------------------------------------\n\n\toverride async getTableData(params: GetTableDataParams): Promise<TableDataResultSchemaType> {\n\t\ttry {\n\t\t\tconst { tableName, db, cursor, limit, direction = \"asc\", sort, order, filters } = params;\n\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst filterObj = buildMatchStage(filters ?? []);\n\t\t\tconst sortObj = buildSortStage(sort ?? \"\", order);\n\n\t\t\tconst safeLimit = limit && limit > 0 ? limit : 50;\n\t\t\tconst decodedOffset = decodeMongoCursor(cursor);\n\t\t\tconst offset = Number.isFinite(decodedOffset) && decodedOffset >= 0 ? decodedOffset : 0;\n\t\t\tconst skip = direction === \"desc\" ? Math.max(offset - safeLimit, 0) : offset;\n\n\t\t\tconst [total, rows] = await Promise.all([\n\t\t\t\tcollection.countDocuments(filterObj),\n\t\t\t\tcollection.find(filterObj).sort(sortObj).skip(skip).limit(safeLimit).toArray(),\n\t\t\t]);\n\n\t\t\tconst normalizedRows = rows.map((row) => normalizeDoc(row));\n\t\t\tconst nextOffset = skip + safeLimit;\n\t\t\tconst prevOffset = Math.max(skip - safeLimit, 0);\n\n\t\t\treturn {\n\t\t\t\tdata: normalizedRows,\n\t\t\t\tmeta: {\n\t\t\t\t\tlimit: safeLimit,\n\t\t\t\t\ttotal,\n\t\t\t\t\thasNextPage: nextOffset < total,\n\t\t\t\t\thasPreviousPage: skip > 0,\n\t\t\t\t\tnextCursor: nextOffset < total ? encodeMongoCursor(nextOffset) : null,\n\t\t\t\t\tprevCursor: skip > 0 ? encodeMongoCursor(prevOffset) : null,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// exportTableData — full override (no SELECT * in Mongo)\n\t// -----------------------------------------------------------------------\n\n\toverride async exportTableData({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<{ cols: string[]; rows: Record<string, unknown>[] }> {\n\t\ttry {\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst rows = await collection.find({}).limit(10000).toArray();\n\t\t\t// Nested documents stay nested: the JSON export needs the real structure,\n\t\t\t// and `getExportFile` flattens them for the CSV/XLSX sheet writer.\n\t\t\tconst normalized = rows.map((row) => normalizeDoc(row));\n\t\t\tconst cols = Array.from(new Set(normalized.flatMap((row) => Object.keys(row))));\n\t\t\treturn { cols, rows: normalized };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Database operations\n\t// -----------------------------------------------------------------------\n\n\toverride async getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst client = await getMongoClient();\n\t\t\tconst admin = client.db().admin();\n\t\t\tconst result = await admin.listDatabases();\n\t\t\tconst databases = result.databases ?? [];\n\t\t\tif (!databases[0]) {\n\t\t\t\tthrow new HTTPException(500, { message: \"No databases returned from MongoDB\" });\n\t\t\t}\n\t\t\treturn visibleMongoDatabases(databases, getMongoDbName()).map((db) => ({\n\t\t\t\tname: db.name,\n\t\t\t\tsize: formatBytes(db.sizeOnDisk ?? 0),\n\t\t\t\towner: \"n/a\",\n\t\t\t\tencoding: \"n/a\",\n\t\t\t}));\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\treturn { db: getMongoDbName() };\n\t}\n\n\toverride async getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\ttry {\n\t\t\tconst client = await getMongoClient();\n\t\t\tconst admin = client.db().admin();\n\t\t\tconst urlDefaults = parseDatabaseUrl();\n\t\t\tlet serverStatus: {\n\t\t\t\tversion?: string;\n\t\t\t\tconnections?: { current?: number; available?: number };\n\t\t\t} = {};\n\t\t\ttry {\n\t\t\t\tserverStatus = await admin.serverStatus();\n\t\t\t} catch (error) {\n\t\t\t\tconsole.warn(\"Failed to read MongoDB serverStatus:\", error);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\thost: urlDefaults.host,\n\t\t\t\tport: urlDefaults.port,\n\t\t\t\tuser: \"n/a\",\n\t\t\t\tdatabase: getMongoDbName(),\n\t\t\t\tversion: serverStatus.version ?? \"unknown\",\n\t\t\t\tactive_connections: serverStatus.connections?.current ?? 0,\n\t\t\t\tmax_connections:\n\t\t\t\t\t(serverStatus.connections?.current ?? 0) +\n\t\t\t\t\t(serverStatus.connections?.available ?? 0),\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Table operations\n\t// -----------------------------------------------------------------------\n\n\toverride async getTablesList(db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collections = await mongoDb.listCollections().toArray();\n\t\t\tconst results: TableInfoSchemaType[] = [];\n\t\t\tfor (const col of collections) {\n\t\t\t\tconst rowCount = await mongoDb.collection(col.name).estimatedDocumentCount();\n\t\t\t\tresults.push({ tableName: col.name, rowCount });\n\t\t\t}\n\t\t\treturn results;\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async createTable({\n\t\ttableData,\n\t\tdb,\n\t}: {\n\t\ttableData: CreateTableSchemaType;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<void> {\n\t\ttry {\n\t\t\tconst tableName = tableData?.tableName ?? \"\";\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collections = await mongoDb.listCollections({ name: tableName }).toArray();\n\t\t\tif (collections.length > 0) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Collection \"${tableName}\" already exists`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst fields = tableData?.fields ?? [];\n\t\t\tif (fields.length === 0) {\n\t\t\t\tawait mongoDb.createCollection(tableName);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst properties: Record<string, unknown> = {};\n\t\t\tconst required: string[] = [];\n\t\t\tfor (const field of fields) {\n\t\t\t\tconst bsonType = mapBsonType(field.columnType);\n\t\t\t\tif (!MONGO_BSON_TYPES.has(bsonType)) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: `Unsupported MongoDB BSON type \"${field.columnType}\" for field \"${field.columnName}\"`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (field.isArray) {\n\t\t\t\t\tproperties[field.columnName] = {\n\t\t\t\t\t\tbsonType: \"array\",\n\t\t\t\t\t\t...(bsonType !== \"array\" ? { items: { bsonType } } : {}),\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tproperties[field.columnName] = { bsonType };\n\t\t\t\t}\n\t\t\t\tif (!field.isNullable) required.push(field.columnName);\n\t\t\t}\n\n\t\t\tawait mongoDb.createCollection(tableName, {\n\t\t\t\tvalidator: {\n\t\t\t\t\t$jsonSchema: {\n\t\t\t\t\t\tbsonType: \"object\",\n\t\t\t\t\t\trequired,\n\t\t\t\t\t\tproperties,\n\t\t\t\t\t\tadditionalProperties: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tvalidationAction: \"error\",\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async deleteTable({\n\t\ttableName,\n\t\tdb,\n\t}: DeleteTableParams): Promise<DeleteTableResult> {\n\t\ttry {\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst rowCount = await collection.estimatedDocumentCount();\n\t\t\tawait collection.drop();\n\t\t\treturn { deletedCount: rowCount, fkViolation: false, relatedRecords: [] };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async renameTable(params: RenameTableParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, newTableName, db } = params;\n\t\t\tthis.assertDifferentTableName(tableName, newTableName);\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst existing = await mongoDb.listCollections({ name: tableName }).toArray();\n\t\t\tif (existing.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Collection \"${tableName}\" does not exist`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst target = await mongoDb.listCollections({ name: newTableName }).toArray();\n\t\t\tif (target.length > 0) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Collection \"${newTableName}\" already exists`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait mongoDb.collection(tableName).rename(newTableName);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async getTableSchema({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\ttry {\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collections = await mongoDb.listCollections({ name: tableName }).toArray();\n\t\t\tif (collections.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Collection \"${tableName}\" does not exist`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst docs = await collection.find({}).limit(200).toArray();\n\t\t\tconst totalDocs = await collection.estimatedDocumentCount();\n\n\t\t\tconst fieldTypes = new Map<string, Set<string>>();\n\t\t\tconst fieldPresence = new Map<string, number>();\n\t\t\tfor (const doc of docs) {\n\t\t\t\tfor (const [key, value] of Object.entries(doc)) {\n\t\t\t\t\tconst bsonType = inferBsonType(value);\n\t\t\t\t\tif (!fieldTypes.has(key)) {\n\t\t\t\t\t\tfieldTypes.set(key, new Set());\n\t\t\t\t\t\tfieldPresence.set(key, 0);\n\t\t\t\t\t}\n\t\t\t\t\tfieldTypes.get(key)?.add(bsonType);\n\t\t\t\t\tfieldPresence.set(key, (fieldPresence.get(key) ?? 0) + 1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst properties: Record<string, unknown> = {};\n\t\t\tconst required: string[] = [];\n\t\t\tfor (const [field, types] of fieldTypes.entries()) {\n\t\t\t\tconst presence = fieldPresence.get(field) ?? 0;\n\t\t\t\tconst typeList = Array.from(types).filter((t) => t !== \"null\");\n\t\t\t\tconst isNullable = types.has(\"null\") || presence < docs.length;\n\t\t\t\tif (presence === docs.length && docs.length > 0 && !isNullable) required.push(field);\n\t\t\t\tproperties[field] =\n\t\t\t\t\ttypeList.length === 1\n\t\t\t\t\t\t? { bsonType: isNullable ? [typeList[0], \"null\"] : typeList[0] }\n\t\t\t\t\t\t: { bsonType: isNullable ? [...typeList, \"null\"] : typeList };\n\t\t\t}\n\n\t\t\tconst schema = {\n\t\t\t\tcollection: tableName,\n\t\t\t\testimatedDocumentCount: totalDocs,\n\t\t\t\tsampledDocuments: docs.length,\n\t\t\t\tjsonSchema: {\n\t\t\t\t\tbsonType: \"object\",\n\t\t\t\t\trequired: required.length > 0 ? required : undefined,\n\t\t\t\t\tproperties,\n\t\t\t\t},\n\t\t\t};\n\t\t\treturn JSON.stringify(schema, null, 2);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Column operations\n\t// -----------------------------------------------------------------------\n\n\toverride async getTableColumns({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst documents = await collection.find({}).limit(200).toArray();\n\t\t\tconst totalDocs = documents.length;\n\n\t\t\tconst columnMap = new Map<\n\t\t\t\tstring,\n\t\t\t\t{ types: Set<DataTypes>; nullable: boolean; presentCount: number }\n\t\t\t>();\n\n\t\t\tconst ensureColumn = (columnName: string, value: unknown) => {\n\t\t\t\tconst dt = inferValueType(value);\n\t\t\t\tif (!columnMap.has(columnName)) {\n\t\t\t\t\tcolumnMap.set(columnName, {\n\t\t\t\t\t\ttypes: new Set([dt]),\n\t\t\t\t\t\tnullable: false,\n\t\t\t\t\t\tpresentCount: 1,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tconst entry = columnMap.get(columnName)!;\n\t\t\t\t\tentry.types.add(dt);\n\t\t\t\t\tentry.presentCount += 1;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfor (const doc of documents) {\n\t\t\t\tfor (const [key, value] of Object.entries(doc)) {\n\t\t\t\t\tif (value === null || value === undefined) {\n\t\t\t\t\t\tif (!columnMap.has(key)) {\n\t\t\t\t\t\t\tcolumnMap.set(key, {\n\t\t\t\t\t\t\t\ttypes: new Set([\"text\"]),\n\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\tpresentCount: 1,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst entry = columnMap.get(key)!;\n\t\t\t\t\t\t\tentry.nullable = true;\n\t\t\t\t\t\t\tentry.presentCount += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tensureColumn(key, value);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (totalDocs > 0) {\n\t\t\t\tfor (const entry of columnMap.values()) {\n\t\t\t\t\tif (entry.presentCount < totalDocs) entry.nullable = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!columnMap.has(\"_id\")) {\n\t\t\t\tcolumnMap.set(\"_id\", {\n\t\t\t\t\ttypes: new Set([\"text\"]),\n\t\t\t\t\tnullable: false,\n\t\t\t\t\tpresentCount: totalDocs,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn Array.from(columnMap.entries()).map(([columnName, meta]) => {\n\t\t\t\tconst dt = (meta.types.values().next().value ?? \"text\") as DataTypes;\n\t\t\t\treturn {\n\t\t\t\t\tcolumnName,\n\t\t\t\t\tdataType: dt,\n\t\t\t\t\tdataTypeLabel: dataTypeLabel(dt) as ColumnInfoSchemaType[\"dataTypeLabel\"],\n\t\t\t\t\tisNullable: meta.nullable,\n\t\t\t\t\tcolumnDefault: null,\n\t\t\t\t\tisPrimaryKey: columnName === \"_id\",\n\t\t\t\t\tisForeignKey: false,\n\t\t\t\t\treferencedTable: null,\n\t\t\t\t\treferencedColumn: null,\n\t\t\t\t\tenumValues: null,\n\t\t\t\t};\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async addColumn(params: AddColumnParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, columnName, columnType, defaultValue, isNullable, db } = params;\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collections = await mongoDb.listCollections({ name: tableName }).toArray();\n\t\t\tif (collections.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Collection \"${tableName}\" does not exist`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst conflict = await mongoDb\n\t\t\t\t.collection(tableName)\n\t\t\t\t.findOne({ [columnName]: { $exists: true } });\n\t\t\tif (conflict) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Field \"${columnName}\" already exists in collection \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst resolvedDefault = resolveFieldDefault(defaultValue, columnType);\n\t\t\tawait mongoDb\n\t\t\t\t.collection(tableName)\n\t\t\t\t.updateMany({}, { $set: { [columnName]: resolvedDefault } });\n\n\t\t\tconst collInfo = collections[0] as {\n\t\t\t\toptions?: {\n\t\t\t\t\tvalidator?: {\n\t\t\t\t\t\t$jsonSchema?: {\n\t\t\t\t\t\t\tproperties?: Record<string, unknown>;\n\t\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tconst existingSchema = collInfo.options?.validator?.$jsonSchema ?? {};\n\t\t\tconst properties: Record<string, unknown> = {\n\t\t\t\t...((existingSchema.properties as Record<string, unknown>) ?? {}),\n\t\t\t\t[columnName]: { bsonType: isNullable ? [columnType, \"null\"] : columnType },\n\t\t\t};\n\t\t\tconst required: string[] = [...(existingSchema.required ?? [])];\n\t\t\tif (!isNullable && !required.includes(columnName)) required.push(columnName);\n\n\t\t\tawait mongoDb.command({\n\t\t\t\tcollMod: tableName,\n\t\t\t\tvalidator: {\n\t\t\t\t\t$jsonSchema: {\n\t\t\t\t\t\t...existingSchema,\n\t\t\t\t\t\tbsonType: \"object\",\n\t\t\t\t\t\tproperties,\n\t\t\t\t\t\t...(required.length > 0 ? { required } : {}),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tvalidationAction: \"warn\",\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async deleteColumn({\n\t\ttableName,\n\t\tcolumnName,\n\t\tdb,\n\t}: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\ttry {\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst result = await collection.updateMany({}, { $unset: { [columnName]: \"\" } });\n\t\t\treturn { deletedCount: result.modifiedCount };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async alterColumn(params: AlterColumnParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, columnName, columnType, isNullable, db } = params;\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collections = await mongoDb.listCollections({ name: tableName }).toArray();\n\t\t\tif (collections.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Collection \"${tableName}\" does not exist`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (columnName === \"_id\") {\n\t\t\t\tthrow new HTTPException(400, { message: 'Cannot alter the \"_id\" field' });\n\t\t\t}\n\n\t\t\tconst collInfo = collections[0] as {\n\t\t\t\toptions?: {\n\t\t\t\t\tvalidator?: {\n\t\t\t\t\t\t$jsonSchema?: {\n\t\t\t\t\t\t\tproperties?: Record<string, unknown>;\n\t\t\t\t\t\t\trequired?: string[];\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tconst existingSchema = collInfo.options?.validator?.$jsonSchema ?? {};\n\t\t\tconst properties: Record<string, unknown> = {\n\t\t\t\t...((existingSchema.properties as Record<string, unknown>) ?? {}),\n\t\t\t};\n\t\t\tconst required: string[] = [...(existingSchema.required ?? [])];\n\n\t\t\tproperties[columnName] = {\n\t\t\t\tbsonType: isNullable ? [columnType, \"null\"] : columnType,\n\t\t\t};\n\n\t\t\tconst reqIndex = required.indexOf(columnName);\n\t\t\tif (!isNullable && reqIndex === -1) required.push(columnName);\n\t\t\telse if (isNullable && reqIndex !== -1) required.splice(reqIndex, 1);\n\n\t\t\tawait mongoDb.command({\n\t\t\t\tcollMod: tableName,\n\t\t\t\tvalidator: {\n\t\t\t\t\t$jsonSchema: {\n\t\t\t\t\t\t...existingSchema,\n\t\t\t\t\t\tbsonType: \"object\",\n\t\t\t\t\t\tproperties,\n\t\t\t\t\t\t...(required.length > 0 ? { required } : {}),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tvalidationAction: \"warn\",\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async renameColumn(params: RenameColumnParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, columnName, newColumnName, db } = params;\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collections = await mongoDb.listCollections({ name: tableName }).toArray();\n\t\t\tif (collections.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Collection \"${tableName}\" does not exist`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (columnName === \"_id\") {\n\t\t\t\tthrow new HTTPException(400, { message: 'Cannot rename the \"_id\" field' });\n\t\t\t}\n\n\t\t\tconst sample = await mongoDb\n\t\t\t\t.collection(tableName)\n\t\t\t\t.findOne({ [columnName]: { $exists: true } });\n\t\t\tif (!sample) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Field \"${columnName}\" does not exist in collection \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst conflict = await mongoDb\n\t\t\t\t.collection(tableName)\n\t\t\t\t.findOne({ [newColumnName]: { $exists: true } });\n\t\t\tif (conflict) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Field \"${newColumnName}\" already exists in collection \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait mongoDb\n\t\t\t\t.collection(tableName)\n\t\t\t\t.updateMany(\n\t\t\t\t\t{ [columnName]: { $exists: true } },\n\t\t\t\t\t{ $rename: { [columnName]: newColumnName } },\n\t\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Record operations\n\t// -----------------------------------------------------------------------\n\n\toverride async addRecord({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\ttry {\n\t\t\tconst { tableName, data } = params;\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst payload = normalizeDoc(data);\n\t\t\tif (payload._id === \"\" || payload._id === null) delete payload._id;\n\t\t\tconst result = await collection.insertOne(payload);\n\t\t\tif (!result.insertedId) {\n\t\t\t\tthrow new HTTPException(500, {\n\t\t\t\t\tmessage: `Failed to insert record into \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { insertedCount: 1 };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async updateRecords({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\ttry {\n\t\t\tconst { tableName } = params;\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\n\t\t\tlet totalUpdated = 0;\n\t\t\tconst keyColumns = this.resolveKeyColumns(params).map((column) => column || \"_id\");\n\t\t\tconst groups = this.groupUpdatesByKey(\n\t\t\t\t{ ...params, primaryKeys: keyColumns },\n\t\t\t\tkeyColumns,\n\t\t\t);\n\n\t\t\tfor (const { keyValues, rowUpdates } of groups) {\n\t\t\t\t// MongoDB rejects $set on the immutable _id field, so surface it as a\n\t\t\t\t// client error instead of letting the driver fail mid-write.\n\t\t\t\tif (rowUpdates.some((update) => update.columnName === \"_id\")) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: 'The \"_id\" field is immutable and cannot be updated.',\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst updateSet: Record<string, unknown> = {};\n\t\t\t\tfor (const update of rowUpdates) updateSet[update.columnName] = update.value;\n\n\t\t\t\tconst filter: Record<string, unknown> = {};\n\t\t\t\tkeyColumns.forEach((column, i) => {\n\t\t\t\t\tconst value = keyValues[i];\n\t\t\t\t\tfilter[column] = column === \"_id\" && canCoerce(value) ? toMongoId(value) : value;\n\t\t\t\t});\n\n\t\t\t\tconst result = await collection.updateOne(filter, { $set: updateSet });\n\t\t\t\tif (result.matchedCount === 0) {\n\t\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\t\tmessage: `Record with ${this.describeKey(keyColumns, keyValues)} not found in \"${tableName}\"`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\ttotalUpdated += result.modifiedCount;\n\t\t\t}\n\n\t\t\treturn { updatedCount: totalUpdated };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async deleteRecords(params: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\ttry {\n\t\t\tconst { tableName, primaryKeys, db } = params;\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst pkColumn = primaryKeys[0]?.columnName ?? \"_id\";\n\t\t\tconst pkValues = primaryKeys.map((pk) =>\n\t\t\t\tpkColumn === \"_id\" && canCoerce(pk.value) ? toMongoId(pk.value) : pk.value,\n\t\t\t);\n\t\t\tconst result = await collection.deleteMany({ [pkColumn]: { $in: pkValues } });\n\t\t\treturn {\n\t\t\t\tdeletedCount: result.deletedCount ?? 0,\n\t\t\t\tfkViolation: false,\n\t\t\t\trelatedRecords: [],\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async forceDeleteRecords(\n\t\tparams: DeleteRecordParams,\n\t): Promise<{ deletedCount: number }> {\n\t\tconst result = await this.deleteRecords(params);\n\t\treturn { deletedCount: result.deletedCount };\n\t}\n\n\toverride async bulkInsertRecords(\n\t\tparams: BulkInsertRecordsParams,\n\t): Promise<BulkInsertResult> {\n\t\ttry {\n\t\t\tconst { tableName, records, db } = params;\n\t\t\tif (!records || records.length === 0) {\n\t\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\t\t\t}\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(tableName);\n\t\t\tconst docs = records.map((record) => {\n\t\t\t\tconst normalized = normalizeDoc(record);\n\t\t\t\tif (normalized._id === \"\" || normalized._id === null) delete normalized._id;\n\t\t\t\treturn normalized;\n\t\t\t});\n\t\t\tconst result = await collection.insertMany(docs, { ordered: false });\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `Successfully inserted ${result.insertedCount} record${result.insertedCount !== 1 ? \"s\" : \"\"}`,\n\t\t\t\tsuccessCount: result.insertedCount,\n\t\t\t\tfailureCount: records.length - result.insertedCount,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Query execution\n\t// -----------------------------------------------------------------------\n\n\toverride async executeQuery({\n\t\tquery,\n\t\tdb,\n\t}: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\ttry {\n\t\t\tif (!query?.trim()) {\n\t\t\t\tthrow new HTTPException(400, { message: \"Query is required\" });\n\t\t\t}\n\n\t\t\tlet payload: MongoQueryPayload;\n\t\t\ttry {\n\t\t\t\tpayload = JSON.parse(query) as MongoQueryPayload;\n\t\t\t} catch {\n\t\t\t\tthrow new HTTPException(400, { message: \"Mongo query must be valid JSON\" });\n\t\t\t}\n\n\t\t\tif (!payload.collection || !payload.operation) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: \"Mongo query must include collection and operation\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst mongoDb = await getMongoDb(db);\n\t\t\tconst collection = mongoDb.collection(payload.collection);\n\n\t\t\tconst startTime = performance.now();\n\t\t\tlet rows: Record<string, unknown>[] = [];\n\t\t\tlet rowCount = 0;\n\t\t\tlet message: string | undefined;\n\n\t\t\tswitch (payload.operation) {\n\t\t\t\tcase \"find\": {\n\t\t\t\t\tconst filter = normalizeIdFilter(payload.filter ?? {});\n\t\t\t\t\tconst cursor = collection.find(filter, payload.options ?? {});\n\t\t\t\t\tcursor.sort(payload.sort ?? buildSortStage(\"\", undefined));\n\t\t\t\t\tif (payload.skip) cursor.skip(payload.skip);\n\t\t\t\t\tif (payload.limit) cursor.limit(payload.limit);\n\t\t\t\t\trows = await cursor.toArray();\n\t\t\t\t\trowCount = rows.length;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"aggregate\": {\n\t\t\t\t\trows = await collection\n\t\t\t\t\t\t.aggregate(payload.pipeline ?? [], payload.options ?? {})\n\t\t\t\t\t\t.toArray();\n\t\t\t\t\trowCount = rows.length;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"insertOne\": {\n\t\t\t\t\tconst doc = payload.document as Record<string, unknown> | undefined;\n\t\t\t\t\tif (!doc) throw new HTTPException(400, { message: \"document is required\" });\n\t\t\t\t\tconst result = await collection.insertOne(doc);\n\t\t\t\t\trowCount = result.insertedId ? 1 : 0;\n\t\t\t\t\tmessage = \"OK\";\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"insertMany\": {\n\t\t\t\t\tconst docs = payload.document as Record<string, unknown>[] | undefined;\n\t\t\t\t\tif (!Array.isArray(docs))\n\t\t\t\t\t\tthrow new HTTPException(400, { message: \"document array is required\" });\n\t\t\t\t\tconst result = await collection.insertMany(docs);\n\t\t\t\t\trowCount = result.insertedCount ?? 0;\n\t\t\t\t\tmessage = \"OK\";\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"updateOne\": {\n\t\t\t\t\tconst filter = normalizeIdFilter(payload.filter ?? {});\n\t\t\t\t\tif (!payload.update) throw new HTTPException(400, { message: \"update is required\" });\n\t\t\t\t\tconst result = await collection.updateOne(\n\t\t\t\t\t\tfilter,\n\t\t\t\t\t\tpayload.update,\n\t\t\t\t\t\tpayload.options ?? {},\n\t\t\t\t\t);\n\t\t\t\t\trowCount = result.matchedCount ?? 0;\n\t\t\t\t\tmessage = `OK (${result.modifiedCount ?? 0} modified)`;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"updateMany\": {\n\t\t\t\t\tconst filter = normalizeIdFilter(payload.filter ?? {});\n\t\t\t\t\tif (!payload.update) throw new HTTPException(400, { message: \"update is required\" });\n\t\t\t\t\tconst result = await collection.updateMany(\n\t\t\t\t\t\tfilter,\n\t\t\t\t\t\tpayload.update,\n\t\t\t\t\t\tpayload.options ?? {},\n\t\t\t\t\t);\n\t\t\t\t\trowCount = result.matchedCount ?? 0;\n\t\t\t\t\tmessage = `OK (${result.modifiedCount ?? 0} modified)`;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"deleteOne\": {\n\t\t\t\t\tconst filter = normalizeIdFilter(payload.filter ?? {});\n\t\t\t\t\tconst result = await collection.deleteOne(filter, payload.options ?? {});\n\t\t\t\t\trowCount = result.deletedCount ?? 0;\n\t\t\t\t\tmessage = \"OK\";\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"deleteMany\": {\n\t\t\t\t\tconst filter = normalizeIdFilter(payload.filter ?? {});\n\t\t\t\t\tconst result = await collection.deleteMany(filter, payload.options ?? {});\n\t\t\t\t\trowCount = result.deletedCount ?? 0;\n\t\t\t\t\tmessage = \"OK\";\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"count\": {\n\t\t\t\t\tconst filter = normalizeIdFilter(payload.filter ?? {});\n\t\t\t\t\trowCount = await collection.countDocuments(filter);\n\t\t\t\t\trows = [{ count: rowCount }];\n\t\t\t\t\tmessage = \"OK\";\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new HTTPException(400, { message: \"Unsupported Mongo operation\" });\n\t\t\t}\n\n\t\t\tconst duration = performance.now() - startTime;\n\t\t\tconst normalizedRows = rows.map((row) => normalizeDoc(row));\n\t\t\tconst columns = normalizedRows[0] ? Object.keys(normalizedRows[0]) : [];\n\n\t\t\treturn { columns, rows: normalizedRows, rowCount, duration, message };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n}\n","import type { FilterType, SortDirection, SortType } from \"@db-studio/shared/types\";\n\nexport function buildWhereClause(\n\tfilters: FilterType[],\n\tstartIdx = 0,\n): { clause: string; values: unknown[]; nextIdx: number } {\n\tif (filters.length === 0) return { clause: \"\", values: [], nextIdx: startIdx };\n\n\tconst conditions: string[] = [];\n\tconst values: unknown[] = [];\n\tlet idx = startIdx;\n\n\tfor (const filter of filters) {\n\t\tconst col = `[${filter.columnName}]`;\n\t\tswitch (filter.operator) {\n\t\t\tcase \"=\":\n\t\t\tcase \"!=\":\n\t\t\tcase \">\":\n\t\t\tcase \">=\":\n\t\t\tcase \"<\":\n\t\t\tcase \"<=\":\n\t\t\t\tconditions.push(`${col} ${filter.operator} @p${idx}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tidx++;\n\t\t\t\tbreak;\n\t\t\tcase \"is\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${col} IS NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} = @p${idx}`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t\tidx++;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"is not\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${col} IS NOT NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} != @p${idx}`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t\tidx++;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"like\":\n\t\t\tcase \"ilike\":\n\t\t\t\tconditions.push(`${col} LIKE @p${idx}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tidx++;\n\t\t\t\tbreak;\n\t\t\tcase \"not like\":\n\t\t\tcase \"not ilike\":\n\t\t\t\tconditions.push(`${col} NOT LIKE @p${idx}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tidx++;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (conditions.length === 0) return { clause: \"\", values: [], nextIdx: startIdx };\n\treturn { clause: `WHERE ${conditions.join(\" AND \")}`, values, nextIdx: idx };\n}\n\nexport function buildSortClause(sorts: SortType[] | string, order: SortDirection): string {\n\tif (Array.isArray(sorts)) {\n\t\tif (sorts.length === 0) return \"\";\n\t\treturn `ORDER BY ${sorts.map((s) => `[${s.columnName}] ${s.direction.toUpperCase()}`).join(\", \")}`;\n\t}\n\tif (sorts && typeof sorts === \"string\") {\n\t\treturn `ORDER BY [${sorts}] ${order?.toUpperCase() || \"ASC\"}`;\n\t}\n\treturn \"\";\n}\n\nexport function buildOrderByClause(\n\tsorts: SortType[] | string,\n\torder: SortDirection,\n\tkeyColumns: string[],\n): string {\n\tconst sortClause = buildSortClause(sorts, order);\n\tconst sortColumns = Array.isArray(sorts) ? sorts.map((s) => s.columnName) : [sorts];\n\tconst direction = (\n\t\tArray.isArray(sorts) ? (sorts[0]?.direction ?? order) : order\n\t).toUpperCase();\n\tconst tieBreakers = keyColumns\n\t\t.filter((col) => !sortColumns.includes(col))\n\t\t.map((col) => `[${col}] ${direction}`)\n\t\t.join(\", \");\n\n\tif (!tieBreakers) return sortClause || \"ORDER BY (SELECT NULL)\";\n\treturn sortClause ? `${sortClause}, ${tieBreakers}` : `ORDER BY ${tieBreakers}`;\n}\n\nexport function mapColumnTypeToMssql(columnType: string, isArray: boolean): string {\n\tif (isArray) return \"NVARCHAR(MAX)\";\n\n\tconst normalized = columnType.toLowerCase().trim();\n\tconst typeMap: Record<string, string> = {\n\t\tserial: \"INT IDENTITY(1,1)\",\n\t\tserial4: \"INT IDENTITY(1,1)\",\n\t\tbigserial: \"BIGINT IDENTITY(1,1)\",\n\t\tserial8: \"BIGINT IDENTITY(1,1)\",\n\t\tint: \"INT\",\n\t\tint4: \"INT\",\n\t\tinteger: \"INT\",\n\t\tbigint: \"BIGINT\",\n\t\tint8: \"BIGINT\",\n\t\tsmallint: \"SMALLINT\",\n\t\tint2: \"SMALLINT\",\n\t\ttinyint: \"TINYINT\",\n\t\tnumeric: \"NUMERIC\",\n\t\tdecimal: \"DECIMAL\",\n\t\treal: \"REAL\",\n\t\tfloat4: \"REAL\",\n\t\tfloat: \"FLOAT\",\n\t\t\"double precision\": \"FLOAT\",\n\t\tfloat8: \"FLOAT\",\n\t\tmoney: \"MONEY\",\n\t\tboolean: \"BIT\",\n\t\tbool: \"BIT\",\n\t\ttext: \"NVARCHAR(MAX)\",\n\t\tvarchar: \"VARCHAR(255)\",\n\t\t\"character varying\": \"VARCHAR(255)\",\n\t\tchar: \"CHAR(1)\",\n\t\tcharacter: \"CHAR(1)\",\n\t\tbpchar: \"CHAR\",\n\t\tuuid: \"UNIQUEIDENTIFIER\",\n\t\tjson: \"NVARCHAR(MAX)\",\n\t\tjsonb: \"NVARCHAR(MAX)\",\n\t\txml: \"XML\",\n\t\tdate: \"DATE\",\n\t\ttime: \"TIME\",\n\t\t\"time without time zone\": \"TIME\",\n\t\ttimestamp: \"DATETIME2\",\n\t\t\"timestamp without time zone\": \"DATETIME2\",\n\t\t\"timestamp with time zone\": \"DATETIMEOFFSET\",\n\t\ttimestamptz: \"DATETIMEOFFSET\",\n\t\tinterval: \"VARCHAR(255)\",\n\t\tbytea: \"VARBINARY(MAX)\",\n\t\tinet: \"VARCHAR(45)\",\n\t\tcidr: \"VARCHAR(45)\",\n\t\tmacaddr: \"VARCHAR(17)\",\n\t\tmacaddr8: \"VARCHAR(23)\",\n\t};\n\n\treturn typeMap[normalized] || columnType.toUpperCase();\n}\n\nexport function formatMssqlDefaultValue(\n\tdefaultValue: string,\n\tcolumnType: string,\n): string | null {\n\tconst trimmed = defaultValue.trim().toLowerCase();\n\n\tif (trimmed.includes(\"(\") && trimmed.includes(\")\")) {\n\t\tif (trimmed.includes(\"newid()\")) {\n\t\t\tif (!columnType.toUpperCase().includes(\"UNIQUEIDENTIFIER\")) return null;\n\t\t\treturn \"NEWID()\";\n\t\t}\n\t\tif (trimmed.includes(\"getdate\") || trimmed.includes(\"current_timestamp\"))\n\t\t\treturn \"GETDATE()\";\n\t\treturn defaultValue.trim();\n\t}\n\n\tif (trimmed === \"null\") return \"NULL\";\n\tif (trimmed === \"true\" || trimmed === \"false\") return trimmed === \"true\" ? \"1\" : \"0\";\n\treturn defaultValue.trim();\n}\n\ntype MssqlColumnDefinitionInput = {\n\tcolumnName: string;\n\tcolumnType: string;\n\tdefaultValue?: string | null;\n\tisPrimaryKey?: boolean;\n\tisNullable?: boolean;\n\tisUnique?: boolean;\n\tisIdentity?: boolean;\n\tisArray?: boolean;\n};\n\nexport function buildMssqlColumnDefinition(\n\tfield: MssqlColumnDefinitionInput,\n\toptions: { includePrimaryKey?: boolean; includeUnique?: boolean } = {},\n): string {\n\tconst mappedType = mapColumnTypeToMssql(field.columnType, field.isArray ?? false);\n\tlet def = `[${field.columnName}] ${mappedType}`;\n\n\tif (field.isIdentity && !mappedType.includes(\"IDENTITY\")) {\n\t\tdef += \" IDENTITY(1,1)\";\n\t}\n\n\tif (!field.isNullable && !field.isPrimaryKey) def += \" NOT NULL\";\n\n\tif (field.defaultValue?.trim() && !mappedType.includes(\"IDENTITY\")) {\n\t\tconst dv = formatMssqlDefaultValue(field.defaultValue, mappedType);\n\t\tif (dv !== null) def += ` DEFAULT ${dv}`;\n\t}\n\n\tif (options.includeUnique && field.isUnique && !field.isPrimaryKey) def += \" UNIQUE\";\n\tif (options.includePrimaryKey && field.isPrimaryKey) def += \" PRIMARY KEY\";\n\n\treturn def;\n}\n","import type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteRecordSchemaType,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tFieldDataType,\n\tForeignKeyConstraint,\n\tForeignKeyDataType,\n\tRelatedRecord,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tTableDataResultSchemaType,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { mapMssqlToDataType, standardizeMssqlDataTypeLabel } from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { ConnectionPool as MssqlPool } from \"mssql\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getMssqlPool } from \"@/adapters/connections.js\";\nimport { parseDatabaseUrl } from \"@/utils/parse-database-url.js\";\nimport {\n\tbuildMssqlColumnDefinition,\n\tbuildOrderByClause,\n\tbuildSortClause,\n\tbuildWhereClause,\n\tformatMssqlDefaultValue,\n\tmapColumnTypeToMssql,\n} from \"./mssql.query-builder.js\";\n\nconst MSSQL_FK_VIOLATION = 547;\nconst MSSQL_FK_DEPENDENCY = 3726;\n\ninterface FkConstraintRow {\n\tconstraint_name: string;\n\treferencing_table: string;\n\treferencing_column: string;\n\treferenced_table: string;\n\treferenced_column: string;\n}\n\nexport class MsSqlAdapter extends BaseAdapter {\n\t// =========================================================\n\t// Abstract method implementations\n\t// =========================================================\n\n\tprotected async runQuery<T>(db: string, sql: string, values: unknown[]): Promise<T> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst request = pool.request();\n\t\tvalues.forEach((val, idx) => {\n\t\t\trequest.input(`p${idx}`, val);\n\t\t});\n\t\tconst result = await request.query(sql);\n\t\treturn result.recordset as T;\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn `[${name}]`;\n\t}\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\treturn mapMssqlToDataType(nativeType);\n\t}\n\n\tmapFromUniversalType(universalType: string): string {\n\t\tconst map: Record<string, string> = {\n\t\t\ttext: \"NVARCHAR(MAX)\",\n\t\t\tnumber: \"INT\",\n\t\t\tboolean: \"BIT\",\n\t\t\tjson: \"NVARCHAR(MAX)\",\n\t\t\tdate: \"DATETIME2\",\n\t\t\tarray: \"NVARCHAR(MAX)\",\n\t\t\tenum: \"NVARCHAR(255)\",\n\t\t};\n\t\treturn map[universalType] ?? \"NVARCHAR(MAX)\";\n\t}\n\n\tprotected buildTableDataQuery(params: GetTableDataParams): QueryBundle {\n\t\tconst { tableName, filters = [], sort = [], order = \"asc\", limit = 50, cursor } = params;\n\t\tconst {\n\t\t\tclause: filterWhere,\n\t\t\tvalues: filterValues,\n\t\t\tnextIdx,\n\t\t} = buildWhereClause(filters, 0);\n\t\tconst sortClause = buildSortClause(sort, order) || \"ORDER BY (SELECT NULL)\";\n\t\tconst currentOffset = cursor ? this.decodeOffsetCursor(cursor) : 0;\n\n\t\tconst sql = `SELECT * FROM [${tableName}] ${filterWhere} ${sortClause} OFFSET @p${nextIdx} ROWS FETCH NEXT @p${nextIdx + 1} ROWS ONLY`;\n\t\tconst values = [...filterValues, currentOffset, limit + 1];\n\n\t\tconst countSql = `SELECT COUNT(*) as total FROM [${tableName}] ${filterWhere}`;\n\t\treturn { sql, values, countSql, countValues: filterValues };\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn (rawRows as Record<string, unknown>[]).map((row) => this.normalizeRow(row));\n\t}\n\n\tprotected buildCursors(\n\t\tparams: GetTableDataParams,\n\t\t_rows: NormalizedRow[],\n\t\thasMore: boolean,\n\t): { nextCursor: string | null; prevCursor: string | null } {\n\t\tconst { cursor, limit = 50 } = params;\n\t\tconst currentOffset = cursor ? this.decodeOffsetCursor(cursor) : 0;\n\t\treturn {\n\t\t\tnextCursor: hasMore ? this.makeCursor(currentOffset + limit) : null,\n\t\t\tprevCursor:\n\t\t\t\tcurrentOffset > 0 ? this.makeCursor(Math.max(0, currentOffset - limit)) : null,\n\t\t};\n\t}\n\n\t// =========================================================\n\t// Override getTableData for MSSQL OFFSET/FETCH pagination\n\t// =========================================================\n\n\toverride async getTableData(params: GetTableDataParams): Promise<TableDataResultSchemaType> {\n\t\ttry {\n\t\t\tconst {\n\t\t\t\ttableName,\n\t\t\t\tdb,\n\t\t\t\tlimit = 50,\n\t\t\t\tsort = [],\n\t\t\t\torder = \"asc\",\n\t\t\t\tcursor,\n\t\t\t\tfilters = [],\n\t\t\t} = params;\n\t\t\tconst pool = await getMssqlPool(db);\n\n\t\t\tconst pkColumns = await this.getPrimaryKeyColumns(pool, tableName);\n\n\t\t\tconst currentOffset = cursor ? this.decodeOffsetCursor(cursor) : 0;\n\t\t\tconst {\n\t\t\t\tclause: filterWhere,\n\t\t\t\tvalues: filterValues,\n\t\t\t\tnextIdx,\n\t\t\t} = buildWhereClause(filters, 0);\n\t\t\tconst sortClause = buildOrderByClause(sort, order, pkColumns);\n\n\t\t\tconst countRequest = pool.request();\n\t\t\tfilterValues.forEach((val, idx) => {\n\t\t\t\tcountRequest.input(`p${idx}`, val);\n\t\t\t});\n\t\t\tconst countResult = await countRequest.query(\n\t\t\t\t`SELECT COUNT(*) as total FROM [${tableName}] ${filterWhere}`,\n\t\t\t);\n\t\t\tconst total = Number(countResult.recordset[0]?.total ?? 0);\n\n\t\t\tconst dataRequest = pool.request();\n\t\t\tfilterValues.forEach((val, idx) => {\n\t\t\t\tdataRequest.input(`p${idx}`, val);\n\t\t\t});\n\t\t\tdataRequest.input(`p${nextIdx}`, currentOffset);\n\t\t\tdataRequest.input(`p${nextIdx + 1}`, limit + 1);\n\n\t\t\tconst dataResult = await dataRequest.query(\n\t\t\t\t`SELECT * FROM [${tableName}] ${filterWhere} ${sortClause} OFFSET @p${nextIdx} ROWS FETCH NEXT @p${nextIdx + 1} ROWS ONLY`,\n\t\t\t);\n\n\t\t\tlet rows = dataResult.recordset as Record<string, unknown>[];\n\t\t\tconst hasMore = rows.length > limit;\n\t\t\tif (hasMore) rows = rows.slice(0, limit);\n\n\t\t\treturn {\n\t\t\t\tdata: rows,\n\t\t\t\tmeta: {\n\t\t\t\t\tlimit,\n\t\t\t\t\ttotal,\n\t\t\t\t\thasNextPage: hasMore,\n\t\t\t\t\thasPreviousPage: currentOffset > 0,\n\t\t\t\t\tnextCursor: hasMore ? this.makeCursor(currentOffset + limit) : null,\n\t\t\t\t\tprevCursor:\n\t\t\t\t\t\tcurrentOffset > 0 ? this.makeCursor(Math.max(0, currentOffset - limit)) : null,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// IDbAdapter implementations\n\t// =========================================================\n\n\t// --- Databases ---\n\n\tasync getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst pool = await getMssqlPool();\n\t\t\tconst result = await pool.request().query(`\n\t\t\t\tSELECT\n\t\t\t\t d.name AS name,\n\t\t\t\t CAST(ROUND(CAST(SUM(mf.size) * 8.0 / 1024 AS DECIMAL(10,2)), 2) AS VARCHAR(20)) + ' MB' AS size,\n\t\t\t\t SUSER_SNAME(d.owner_sid) AS owner,\n\t\t\t\t d.collation_name AS encoding\n\t\t\t\tFROM sys.databases d\n\t\t\t\tJOIN sys.master_files mf ON d.database_id = mf.database_id\n\t\t\t\tWHERE (d.database_id > 4 OR d.name = DB_NAME())\n\t\t\t\tGROUP BY d.name, d.owner_sid, d.collation_name\n\t\t\t\tORDER BY d.name\n\t\t\t`);\n\t\t\tif (!result.recordset[0]) {\n\t\t\t\tthrow new HTTPException(500, { message: \"No databases returned from server\" });\n\t\t\t}\n\t\t\treturn result.recordset as DatabaseInfoSchemaType[];\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\tconst pool = await getMssqlPool();\n\t\tconst result = await pool.request().query(\"SELECT DB_NAME() AS db\");\n\t\tif (!result.recordset[0]) {\n\t\t\tthrow new HTTPException(500, { message: \"No current database returned from server\" });\n\t\t}\n\t\treturn result.recordset[0] as DatabaseSchemaType;\n\t}\n\n\tasync getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\tconst pool = await getMssqlPool();\n\t\tconst result = await pool.request().query(`\n\t\t\tSELECT\n\t\t\t @@VERSION AS version,\n\t\t\t DB_NAME() AS database_name,\n\t\t\t SUSER_NAME() AS [user],\n\t\t\t @@SERVERNAME AS host,\n\t\t\t (SELECT local_tcp_port FROM sys.dm_exec_connections WHERE session_id = @@SPID) AS port,\n\t\t\t @@MAX_CONNECTIONS AS max_connections,\n\t\t\t (SELECT COUNT(*) FROM sys.dm_exec_sessions WHERE is_user_process = 1) AS active_connections\n\t\t`);\n\t\tif (!result.recordset[0]) {\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: \"No connection information returned from server\",\n\t\t\t});\n\t\t}\n\t\tconst info = result.recordset[0] as Record<string, string | number>;\n\t\tconst urlDefaults = parseDatabaseUrl();\n\t\treturn {\n\t\t\thost: String(info.host || urlDefaults.host),\n\t\t\tport: Number(info.port || urlDefaults.port),\n\t\t\tuser: String(info.user),\n\t\t\tdatabase: String(info.database_name ?? \"\"),\n\t\t\tversion: String(info.version),\n\t\t\tactive_connections: Number(info.active_connections ?? 0),\n\t\t\tmax_connections: Number(info.max_connections),\n\t\t};\n\t}\n\n\t// --- Tables ---\n\n\tasync getTablesList(db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst result = await pool.request().query(`\n\t\t\tSELECT table_name AS tableName\n\t\t\tFROM information_schema.tables\n\t\t\tWHERE table_catalog = DB_NAME()\n\t\t\t AND table_type = 'BASE TABLE'\n\t\t\t AND table_schema = 'dbo'\n\t\t\tORDER BY table_name\n\t\t`);\n\t\tif (!result.recordset || result.recordset.length === 0) return [];\n\n\t\treturn Promise.all(\n\t\t\t(result.recordset as Array<{ tableName: string }>).map(async (table) => {\n\t\t\t\tconst countResult = await pool\n\t\t\t\t\t.request()\n\t\t\t\t\t.query(`SELECT COUNT(*) as count FROM [${table.tableName}]`);\n\t\t\t\treturn {\n\t\t\t\t\ttableName: table.tableName,\n\t\t\t\t\trowCount: (countResult.recordset[0] as { count: number })?.count ?? 0,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\t}\n\n\tasync createTable({\n\t\ttableData,\n\t\tdb,\n\t}: {\n\t\ttableData: CreateTableSchemaType;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<void> {\n\t\tconst { tableName, fields, foreignKeys } = tableData;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst columnDefs = fields.map((field: FieldDataType) => {\n\t\t\tconst mappedType = mapColumnTypeToMssql(field.columnType, field.isArray ?? false);\n\t\t\tlet colDef = `[${field.columnName}] ${mappedType}`;\n\t\t\tif (!field.isNullable && !field.isPrimaryKey) colDef += \" NOT NULL\";\n\t\t\tif (field.defaultValue && !mappedType.includes(\"IDENTITY\")) {\n\t\t\t\tconst dv = formatMssqlDefaultValue(field.defaultValue, mappedType);\n\t\t\t\tif (dv !== null) colDef += ` DEFAULT ${dv}`;\n\t\t\t}\n\t\t\treturn colDef;\n\t\t});\n\n\t\tconst constraintDefs: string[] = [];\n\t\tconst primaryKeyFields = fields.filter((f: FieldDataType) => f.isPrimaryKey);\n\t\tif (primaryKeyFields.length > 0) {\n\t\t\tconstraintDefs.push(\n\t\t\t\t`PRIMARY KEY (${primaryKeyFields.map((f: FieldDataType) => `[${f.columnName}]`).join(\", \")})`,\n\t\t\t);\n\t\t}\n\t\tfor (const field of fields as FieldDataType[]) {\n\t\t\tif (field.isUnique && !field.isPrimaryKey) {\n\t\t\t\tconstraintDefs.push(`UNIQUE ([${field.columnName}])`);\n\t\t\t}\n\t\t}\n\n\t\tconst fkDefs =\n\t\t\tforeignKeys?.map((fk: ForeignKeyDataType) => {\n\t\t\t\tconst name = `FK_${tableName}_${fk.columnName}`;\n\t\t\t\treturn `CONSTRAINT [${name}] FOREIGN KEY ([${fk.columnName}]) REFERENCES [${fk.referencedTable}] ([${fk.referencedColumn}]) ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}`;\n\t\t\t}) ?? [];\n\n\t\tawait pool\n\t\t\t.request()\n\t\t\t.query(\n\t\t\t\t`CREATE TABLE [${tableName}] (\\n\\t\\t\\t${[...columnDefs, ...constraintDefs, ...fkDefs].join(\",\\n\\t\\t\\t\")}\\n\\t\\t)`,\n\t\t\t);\n\t}\n\n\tasync deleteTable(params: DeleteTableParams): Promise<DeleteTableResult> {\n\t\tconst { tableName, db, cascade } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst tableCheck = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.TABLES\n\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND TABLE_SCHEMA = 'dbo'\n\t\t\t`);\n\t\tif (Number(tableCheck.recordset[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\n\t\tconst rowCount = await this.getTableRowCount(tableName, db);\n\n\t\tif (!cascade) {\n\t\t\tconst relatedRecords = await this.getRelatedRecordsForTable(tableName, db);\n\t\t\tif (relatedRecords.length > 0) {\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tif (cascade) {\n\t\t\t\tconst fkConstraints = await this.getForeignKeyReferences(tableName, db);\n\t\t\t\tfor (const fk of fkConstraints) {\n\t\t\t\t\tawait pool\n\t\t\t\t\t\t.request()\n\t\t\t\t\t\t.query(\n\t\t\t\t\t\t\t`ALTER TABLE [${fk.referencingTable}] DROP CONSTRAINT [${fk.constraintName}]`,\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait pool.request().query(`DROP TABLE [${tableName}]`);\n\t\t\treturn { deletedCount: rowCount, fkViolation: false, relatedRecords: [] };\n\t\t} catch (error: unknown) {\n\t\t\tconst mssqlError = error as { number?: number };\n\t\t\tif (mssqlError.number === MSSQL_FK_DEPENDENCY) {\n\t\t\t\tconst relatedRecords = await this.getRelatedRecordsForTable(tableName, db);\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to delete table \"${tableName}\"` });\n\t\t}\n\t}\n\n\tasync renameTable(params: RenameTableParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, newTableName, db } = params;\n\t\t\tthis.assertDifferentTableName(tableName, newTableName);\n\t\t\tconst pool = await getMssqlPool(db);\n\n\t\t\tawait this.assertTableExists(pool, tableName);\n\n\t\t\tconst targetCheck = await pool\n\t\t\t\t.request()\n\t\t\t\t.input(\"tableName\", newTableName)\n\t\t\t\t.query(`\n\t\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.TABLES\n\t\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND TABLE_SCHEMA = 'dbo'\n\t\t\t\t`);\n\t\t\tif (Number(targetCheck.recordset[0]?.cnt ?? 0) > 0) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Table \"${newTableName}\" already exists`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait pool\n\t\t\t\t.request()\n\t\t\t\t.input(\"oldName\", tableName)\n\t\t\t\t.input(\"newName\", newTableName)\n\t\t\t\t.query(\"EXEC sp_rename @oldName, @newName\");\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getTableSchema({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst tableCheck = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.TABLES\n\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND TABLE_SCHEMA = 'dbo'\n\t\t\t`);\n\t\tif (Number(tableCheck.recordset[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\n\t\tconst schemaResult = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT\n\t\t\t\t c.COLUMN_NAME,\n\t\t\t\t c.DATA_TYPE,\n\t\t\t\t c.CHARACTER_MAXIMUM_LENGTH,\n\t\t\t\t c.NUMERIC_PRECISION,\n\t\t\t\t c.NUMERIC_SCALE,\n\t\t\t\t c.IS_NULLABLE,\n\t\t\t\t c.COLUMN_DEFAULT,\n\t\t\t\t CASE\n\t\t\t\t WHEN pk.COLUMN_NAME IS NOT NULL THEN 'PRIMARY KEY'\n\t\t\t\t WHEN fk.COLUMN_NAME IS NOT NULL THEN 'FOREIGN KEY'\n\t\t\t\t ELSE ''\n\t\t\t\t END AS KEY_TYPE\n\t\t\t\tFROM INFORMATION_SCHEMA.COLUMNS c\n\t\t\t\tLEFT JOIN (\n\t\t\t\t SELECT ku.TABLE_SCHEMA, ku.TABLE_NAME, ku.COLUMN_NAME\n\t\t\t\t FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc\n\t\t\t\t JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku\n\t\t\t\t ON tc.CONSTRAINT_NAME = ku.CONSTRAINT_NAME\n\t\t\t\t WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY'\n\t\t\t\t) pk ON c.TABLE_SCHEMA = pk.TABLE_SCHEMA\n\t\t\t\t AND c.TABLE_NAME = pk.TABLE_NAME\n\t\t\t\t AND c.COLUMN_NAME = pk.COLUMN_NAME\n\t\t\t\tLEFT JOIN (\n\t\t\t\t SELECT ku.TABLE_SCHEMA, ku.TABLE_NAME, ku.COLUMN_NAME\n\t\t\t\t FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc\n\t\t\t\t JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku\n\t\t\t\t ON rc.CONSTRAINT_NAME = ku.CONSTRAINT_NAME\n\t\t\t\t) fk ON c.TABLE_SCHEMA = fk.TABLE_SCHEMA\n\t\t\t\t AND c.TABLE_NAME = fk.TABLE_NAME\n\t\t\t\t AND c.COLUMN_NAME = fk.COLUMN_NAME\n\t\t\t\tWHERE c.TABLE_CATALOG = DB_NAME()\n\t\t\t\t AND c.TABLE_NAME = @tableName\n\t\t\t\t AND c.TABLE_SCHEMA = 'dbo'\n\t\t\t\tORDER BY c.ORDINAL_POSITION\n\t\t\t`);\n\n\t\tif (!schemaResult.recordset || schemaResult.recordset.length === 0) {\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to retrieve schema for table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\tconst columns = (\n\t\t\tschemaResult.recordset as Array<{\n\t\t\t\tCOLUMN_NAME: string;\n\t\t\t\tDATA_TYPE: string;\n\t\t\t\tCHARACTER_MAXIMUM_LENGTH: number | null;\n\t\t\t\tNUMERIC_PRECISION: number | null;\n\t\t\t\tNUMERIC_SCALE: number | null;\n\t\t\t\tIS_NULLABLE: string;\n\t\t\t\tCOLUMN_DEFAULT: string | null;\n\t\t\t}>\n\t\t).map((col) => {\n\t\t\tlet colDef = ` [${col.COLUMN_NAME}] ${col.DATA_TYPE}`;\n\t\t\tif (col.CHARACTER_MAXIMUM_LENGTH) {\n\t\t\t\tcolDef +=\n\t\t\t\t\tcol.CHARACTER_MAXIMUM_LENGTH === -1 ? \"(MAX)\" : `(${col.CHARACTER_MAXIMUM_LENGTH})`;\n\t\t\t} else if (col.NUMERIC_PRECISION !== null && col.NUMERIC_SCALE !== null) {\n\t\t\t\tcolDef += `(${col.NUMERIC_PRECISION},${col.NUMERIC_SCALE})`;\n\t\t\t} else if (col.NUMERIC_PRECISION !== null) {\n\t\t\t\tcolDef += `(${col.NUMERIC_PRECISION})`;\n\t\t\t}\n\t\t\tcolDef += col.IS_NULLABLE === \"YES\" ? \" NULL\" : \" NOT NULL\";\n\t\t\tif (col.COLUMN_DEFAULT) colDef += ` DEFAULT ${col.COLUMN_DEFAULT}`;\n\t\t\treturn colDef;\n\t\t});\n\n\t\treturn `CREATE TABLE [${tableName}] (\\n${columns.join(\",\\n\")}\\n)`;\n\t}\n\n\t// --- Columns ---\n\n\tasync getTableColumns({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst result = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT\n\t\t\t\t c.COLUMN_NAME AS columnName,\n\t\t\t\t c.DATA_TYPE AS dataType,\n\t\t\t\t CASE WHEN c.IS_NULLABLE = 'YES' THEN 1 ELSE 0 END AS isNullable,\n\t\t\t\t c.COLUMN_DEFAULT AS columnDefault,\n\t\t\t\t CASE WHEN pk.COLUMN_NAME IS NOT NULL THEN 1 ELSE 0 END AS isPrimaryKey,\n\t\t\t\t CASE WHEN fk.COLUMN_NAME IS NOT NULL THEN 1 ELSE 0 END AS isForeignKey,\n\t\t\t\t fk.REFERENCED_TABLE_NAME AS referencedTable,\n\t\t\t\t fk.REFERENCED_COLUMN_NAME AS referencedColumn\n\t\t\t\tFROM INFORMATION_SCHEMA.COLUMNS c\n\t\t\t\tLEFT JOIN (\n\t\t\t\t SELECT ku.TABLE_SCHEMA, ku.TABLE_NAME, ku.COLUMN_NAME\n\t\t\t\t FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc\n\t\t\t\t JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku\n\t\t\t\t ON tc.CONSTRAINT_NAME = ku.CONSTRAINT_NAME\n\t\t\t\t AND tc.TABLE_SCHEMA = ku.TABLE_SCHEMA\n\t\t\t\t AND tc.TABLE_NAME = ku.TABLE_NAME\n\t\t\t\t WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY'\n\t\t\t\t) pk ON c.TABLE_SCHEMA = pk.TABLE_SCHEMA\n\t\t\t\t AND c.TABLE_NAME = pk.TABLE_NAME\n\t\t\t\t AND c.COLUMN_NAME = pk.COLUMN_NAME\n\t\t\t\tLEFT JOIN (\n\t\t\t\t SELECT ku.TABLE_SCHEMA, ku.TABLE_NAME, ku.COLUMN_NAME,\n\t\t\t\t ku2.TABLE_NAME AS REFERENCED_TABLE_NAME,\n\t\t\t\t ku2.COLUMN_NAME AS REFERENCED_COLUMN_NAME\n\t\t\t\t FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc\n\t\t\t\t JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku\n\t\t\t\t ON rc.CONSTRAINT_NAME = ku.CONSTRAINT_NAME AND rc.CONSTRAINT_SCHEMA = ku.TABLE_SCHEMA\n\t\t\t\t JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku2\n\t\t\t\t ON rc.UNIQUE_CONSTRAINT_NAME = ku2.CONSTRAINT_NAME AND rc.UNIQUE_CONSTRAINT_SCHEMA = ku2.TABLE_SCHEMA\n\t\t\t\t) fk ON c.TABLE_SCHEMA = fk.TABLE_SCHEMA\n\t\t\t\t AND c.TABLE_NAME = fk.TABLE_NAME\n\t\t\t\t AND c.COLUMN_NAME = fk.COLUMN_NAME\n\t\t\t\tWHERE c.TABLE_CATALOG = DB_NAME()\n\t\t\t\t AND c.TABLE_NAME = @tableName\n\t\t\t\t AND c.TABLE_SCHEMA = 'dbo'\n\t\t\t\tORDER BY c.ORDINAL_POSITION\n\t\t\t`);\n\n\t\tif (!result.recordset || result.recordset.length === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\n\t\tconst checkResult = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT cc.COLUMN_NAME AS columnName, chk.CHECK_CLAUSE AS checkClause\n\t\t\t\tFROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS chk\n\t\t\t\tJOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cc\n\t\t\t\t ON chk.CONSTRAINT_NAME = cc.CONSTRAINT_NAME AND cc.TABLE_SCHEMA = 'dbo'\n\t\t\t\tWHERE cc.TABLE_NAME = @tableName AND cc.TABLE_CATALOG = DB_NAME()\n\t\t\t`);\n\n\t\tconst checkEnumMap = new Map<string, string[]>();\n\t\tfor (const row of checkResult.recordset as { columnName: string; checkClause: string }[]) {\n\t\t\tconst values = this.parseCheckConstraintValues(row.checkClause);\n\t\t\tif (values) checkEnumMap.set(row.columnName, values);\n\t\t}\n\n\t\treturn (\n\t\t\tresult.recordset as Array<{\n\t\t\t\tcolumnName: string;\n\t\t\t\tdataType: string;\n\t\t\t\tisNullable: number;\n\t\t\t\tcolumnDefault: string | null;\n\t\t\t\tisPrimaryKey: number;\n\t\t\t\tisForeignKey: number;\n\t\t\t\treferencedTable: string | null;\n\t\t\t\treferencedColumn: string | null;\n\t\t\t}>\n\t\t).map((r) => {\n\t\t\tconst enumValues = checkEnumMap.get(r.columnName) ?? null;\n\t\t\treturn {\n\t\t\t\tcolumnName: r.columnName,\n\t\t\t\tdataType: enumValues ? \"enum\" : mapMssqlToDataType(r.dataType),\n\t\t\t\tdataTypeLabel: enumValues ? \"enum\" : standardizeMssqlDataTypeLabel(r.dataType),\n\t\t\t\tisNullable: Boolean(r.isNullable),\n\t\t\t\tcolumnDefault: r.columnDefault ?? null,\n\t\t\t\tisPrimaryKey: Boolean(r.isPrimaryKey),\n\t\t\t\tisForeignKey: Boolean(r.isForeignKey),\n\t\t\t\treferencedTable: r.referencedTable ?? null,\n\t\t\t\treferencedColumn: r.referencedColumn ?? null,\n\t\t\t\tenumValues,\n\t\t\t};\n\t\t});\n\t}\n\n\tasync addColumn(params: AddColumnParamsSchemaType): Promise<void> {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tcolumnName,\n\t\t\tcolumnType,\n\t\t\tdefaultValue,\n\t\t\tisPrimaryKey,\n\t\t\tisNullable,\n\t\t\tisUnique,\n\t\t\tisIdentity,\n\t\t\tdb,\n\t\t} = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\n\t\tconst colCheck = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.input(\"columnName\", columnName)\n\t\t\t.query(`\n\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.COLUMNS\n\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND COLUMN_NAME = @columnName AND TABLE_SCHEMA = 'dbo'\n\t\t\t`);\n\t\tif (Number(colCheck.recordset[0]?.cnt ?? 0) > 0) {\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${columnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\tconst colDef = buildMssqlColumnDefinition(\n\t\t\t{ columnName, columnType, defaultValue, isPrimaryKey, isNullable, isUnique, isIdentity },\n\t\t\t{ includePrimaryKey: true, includeUnique: true },\n\t\t);\n\t\tawait pool.request().query(`ALTER TABLE [${tableName}] ADD ${colDef}`);\n\t}\n\n\tasync deleteColumn(params: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\tconst { tableName, columnName, db } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\t\tawait this.assertColumnExists(pool, tableName, columnName);\n\n\t\tconst result = await pool\n\t\t\t.request()\n\t\t\t.query(`ALTER TABLE [${tableName}] DROP COLUMN [${columnName}]`);\n\t\treturn { deletedCount: result.rowsAffected[0] ?? 1 };\n\t}\n\n\tasync alterColumn(params: AlterColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, columnType, isNullable, defaultValue, db } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\t\tawait this.assertColumnExists(pool, tableName, columnName);\n\n\t\tconst defaultConstraintResult = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.input(\"columnName\", columnName)\n\t\t\t.query(`\n\t\t\t\tSELECT dc.name AS constraint_name\n\t\t\t\tFROM sys.default_constraints dc\n\t\t\t\tJOIN sys.columns c\n\t\t\t\t ON dc.parent_object_id = c.object_id AND dc.parent_column_id = c.column_id\n\t\t\t\tWHERE OBJECT_NAME(dc.parent_object_id) = @tableName AND c.name = @columnName\n\t\t\t`);\n\t\tconst constraintName = defaultConstraintResult.recordset[0]?.constraint_name as\n\t\t\t| string\n\t\t\t| undefined;\n\t\tif (constraintName) {\n\t\t\tawait pool\n\t\t\t\t.request()\n\t\t\t\t.query(`ALTER TABLE [${tableName}] DROP CONSTRAINT [${constraintName}]`);\n\t\t}\n\n\t\tconst nullability = isNullable ? \"NULL\" : \"NOT NULL\";\n\t\tawait pool\n\t\t\t.request()\n\t\t\t.query(\n\t\t\t\t`ALTER TABLE [${tableName}] ALTER COLUMN [${columnName}] ${columnType} ${nullability}`,\n\t\t\t);\n\n\t\tif (defaultValue?.trim()) {\n\t\t\tawait pool\n\t\t\t\t.request()\n\t\t\t\t.query(\n\t\t\t\t\t`ALTER TABLE [${tableName}] ADD DEFAULT ${defaultValue.trim()} FOR [${columnName}]`,\n\t\t\t\t);\n\t\t}\n\t}\n\n\tasync renameColumn(params: RenameColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, newColumnName, db } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\t\tawait this.assertColumnExists(pool, tableName, columnName);\n\n\t\tconst newColCheck = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.input(\"columnName\", newColumnName)\n\t\t\t.query(`\n\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.COLUMNS\n\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND COLUMN_NAME = @columnName AND TABLE_SCHEMA = 'dbo'\n\t\t\t`);\n\t\tif (Number(newColCheck.recordset[0]?.cnt ?? 0) > 0) {\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${newColumnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\tawait pool\n\t\t\t.request()\n\t\t\t.query(`EXEC sp_rename '${tableName}.${columnName}', '${newColumnName}', 'COLUMN'`);\n\t}\n\n\t// --- Records ---\n\n\tasync addRecord({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\tconst { tableName, data } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\tconst identityResult = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(\n\t\t\t\t`SELECT name FROM sys.columns WHERE object_id = OBJECT_ID(@tableName) AND is_identity = 1`,\n\t\t\t);\n\t\tconst identityColumns = new Set(\n\t\t\t(identityResult.recordset as { name: string }[]).map((r) => r.name),\n\t\t);\n\n\t\tconst columns = Object.keys(data).filter((col) => !identityColumns.has(col));\n\t\tconst values = columns.map((col) => {\n\t\t\tconst value = data[col];\n\t\t\tif (booleanColumns.has(col) && typeof value === \"string\") {\n\t\t\t\treturn value === \"true\" ? 1 : 0;\n\t\t\t}\n\t\t\treturn value;\n\t\t});\n\n\t\tconst columnNames = columns.map((col) => `[${col}]`).join(\", \");\n\t\tconst paramNames = columns.map((_col, idx) => `@param${idx}`).join(\", \");\n\n\t\tconst request = pool.request();\n\t\tcolumns.forEach((_col, idx) => {\n\t\t\trequest.input(`param${idx}`, values[idx]);\n\t\t});\n\n\t\tconst result = await request.query(\n\t\t\t`INSERT INTO [${tableName}] (${columnNames}) VALUES (${paramNames})`,\n\t\t);\n\t\tif (result.rowsAffected[0] === 0) {\n\t\t\tthrow new HTTPException(500, { message: `Failed to insert record into \"${tableName}\"` });\n\t\t}\n\t\treturn { insertedCount: result.rowsAffected[0] ?? 0 };\n\t}\n\n\tasync updateRecords({\n\t\tparams,\n\t\tdb,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\tconst { tableName } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\tconst keyColumns = this.resolveKeyColumns(params);\n\t\tthis.assertWholeKey(await this.getPrimaryKeyColumns(pool, tableName), keyColumns);\n\t\tconst groups = this.groupUpdatesByKey(params, keyColumns);\n\n\t\tconst transaction = pool.transaction();\n\t\tawait transaction.begin();\n\n\t\ttry {\n\t\t\tlet total = 0;\n\t\t\tfor (const { keyValues, rowUpdates } of groups) {\n\t\t\t\tconst request = transaction.request();\n\t\t\t\tconst setClauses = rowUpdates.map((u, idx) => `[${u.columnName}] = @value${idx}`);\n\n\t\t\t\trowUpdates.forEach((u, idx) => {\n\t\t\t\t\tlet value = u.value;\n\t\t\t\t\tif (value !== null && typeof value === \"object\") value = JSON.stringify(value);\n\t\t\t\t\tif (booleanColumns.has(u.columnName) && typeof value === \"string\") {\n\t\t\t\t\t\tvalue = value === \"true\" ? 1 : 0;\n\t\t\t\t\t}\n\t\t\t\t\trequest.input(`value${idx}`, value);\n\t\t\t\t});\n\t\t\t\tkeyValues.forEach((value, idx) => {\n\t\t\t\t\trequest.input(`pkValue${idx}`, value);\n\t\t\t\t});\n\t\t\t\tconst whereClauses = keyColumns.map((column, idx) => `[${column}] = @pkValue${idx}`);\n\n\t\t\t\tconst result = await request.query(\n\t\t\t\t\t`UPDATE [${tableName}] SET ${setClauses.join(\", \")} WHERE ${whereClauses.join(\" AND \")}`,\n\t\t\t\t);\n\t\t\t\tif (result.rowsAffected[0] === 0) {\n\t\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\t\tmessage: `Record with ${this.describeKey(keyColumns, keyValues)} not found in table \"${tableName}\"`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\ttotal += result.rowsAffected[0] ?? 0;\n\t\t\t}\n\t\t\tawait transaction.commit();\n\t\t\treturn { updatedCount: total };\n\t\t} catch (error) {\n\t\t\tawait transaction.rollback();\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to update records in \"${tableName}\"` });\n\t\t}\n\t}\n\n\tasync deleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\t\tthis.assertDeletableKey(await this.getPrimaryKeyColumns(pool, tableName));\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst transaction = pool.transaction();\n\t\tawait transaction.begin();\n\n\t\ttry {\n\t\t\tconst request = transaction.request();\n\t\t\tpkValues.forEach((value, idx) => {\n\t\t\t\trequest.input(`pk${idx}`, value);\n\t\t\t});\n\t\t\tconst paramList = pkValues.map((_, idx) => `@pk${idx}`).join(\", \");\n\n\t\t\tconst result = await request.query(\n\t\t\t\t`DELETE FROM [${tableName}] WHERE [${pkColumn}] IN (${paramList})`,\n\t\t\t);\n\t\t\tawait transaction.commit();\n\t\t\treturn {\n\t\t\t\tdeletedCount: result.rowsAffected[0] ?? 0,\n\t\t\t\tfkViolation: false,\n\t\t\t\trelatedRecords: [],\n\t\t\t};\n\t\t} catch (error: unknown) {\n\t\t\tawait transaction.rollback();\n\t\t\tconst mssqlError = error as { number?: number };\n\t\t\tif (mssqlError.number === MSSQL_FK_VIOLATION) {\n\t\t\t\tconst relatedRecords = await this.getRelatedRecords(tableName, primaryKeys, db);\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to delete records from \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\tasync forceDeleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<{ deletedCount: number }> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\t\tthis.assertDeletableKey(await this.getPrimaryKeyColumns(pool, tableName));\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst transaction = pool.transaction();\n\t\tawait transaction.begin();\n\n\t\ttry {\n\t\t\tconst fkConstraints = await this.getForeignKeyReferences(tableName, db);\n\t\t\tlet totalRelated = 0;\n\t\t\tconst deletedTables = new Set<string>();\n\t\t\tconst visited = new Set<string>();\n\n\t\t\tconst deleteRelatedRecursively = async (\n\t\t\t\ttargetTable: string,\n\t\t\t\ttargetColumn: string,\n\t\t\t\tvalues: unknown[],\n\t\t\t\tvisitedSet: Set<string>,\n\t\t\t) => {\n\t\t\t\tconst key = `${targetTable}.${targetColumn}`;\n\t\t\t\tif (visitedSet.has(key)) return;\n\t\t\t\tvisitedSet.add(key);\n\n\t\t\t\tconst nestedFks = await this.getForeignKeyReferences(targetTable, db);\n\t\t\t\tfor (const nestedFk of nestedFks) {\n\t\t\t\t\tconst selectRequest = transaction.request();\n\t\t\t\t\tvalues.forEach((val, idx) => {\n\t\t\t\t\t\tselectRequest.input(`val${idx}`, val);\n\t\t\t\t\t});\n\t\t\t\t\tconst selectParamList = values.map((_, idx) => `@val${idx}`).join(\", \");\n\n\t\t\t\t\tconst selectResult = await selectRequest.query(\n\t\t\t\t\t\t`SELECT [${nestedFk.referencedColumn}] FROM [${targetTable}] WHERE [${targetColumn}] IN (${selectParamList})`,\n\t\t\t\t\t);\n\t\t\t\t\tconst nestedValues = (selectResult.recordset as Record<string, unknown>[]).map(\n\t\t\t\t\t\t(row) => row[nestedFk.referencedColumn],\n\t\t\t\t\t);\n\t\t\t\t\tif (nestedValues.length > 0) {\n\t\t\t\t\t\tawait deleteRelatedRecursively(\n\t\t\t\t\t\t\tnestedFk.referencingTable,\n\t\t\t\t\t\t\tnestedFk.referencingColumn,\n\t\t\t\t\t\t\tnestedValues,\n\t\t\t\t\t\t\tvisitedSet,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst deleteRequest = transaction.request();\n\t\t\t\tvalues.forEach((val, idx) => {\n\t\t\t\t\tdeleteRequest.input(`delVal${idx}`, val);\n\t\t\t\t});\n\t\t\t\tconst deleteParamList = values.map((_, idx) => `@delVal${idx}`).join(\", \");\n\n\t\t\t\tconst deleteResult = await deleteRequest.query(\n\t\t\t\t\t`DELETE FROM [${targetTable}] WHERE [${targetColumn}] IN (${deleteParamList})`,\n\t\t\t\t);\n\t\t\t\ttotalRelated += deleteResult.rowsAffected[0] ?? 0;\n\t\t\t\tdeletedTables.add(targetTable);\n\t\t\t};\n\n\t\t\tfor (const constraint of fkConstraints) {\n\t\t\t\tif (!deletedTables.has(constraint.referencingTable)) {\n\t\t\t\t\tawait deleteRelatedRecursively(\n\t\t\t\t\t\tconstraint.referencingTable,\n\t\t\t\t\t\tconstraint.referencingColumn,\n\t\t\t\t\t\tpkValues,\n\t\t\t\t\t\tvisited,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst mainRequest = transaction.request();\n\t\t\tpkValues.forEach((val, idx) => {\n\t\t\t\tmainRequest.input(`mainPk${idx}`, val);\n\t\t\t});\n\t\t\tconst mainParamList = pkValues.map((_, idx) => `@mainPk${idx}`).join(\", \");\n\n\t\t\tconst result = await mainRequest.query(\n\t\t\t\t`DELETE FROM [${tableName}] WHERE [${pkColumn}] IN (${mainParamList})`,\n\t\t\t);\n\t\t\tawait transaction.commit();\n\t\t\treturn { deletedCount: (result.rowsAffected[0] ?? 0) + totalRelated };\n\t\t} catch (error) {\n\t\t\tawait transaction.rollback();\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to force delete records from \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\tasync bulkInsertRecords({\n\t\ttableName,\n\t\trecords,\n\t\tdb,\n\t}: BulkInsertRecordsParams): Promise<BulkInsertResult> {\n\t\tif (!records || records.length === 0) {\n\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\t\t}\n\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst transaction = pool.transaction();\n\n\t\ttry {\n\t\t\tconst columns = Object.keys(records[0]);\n\t\t\tconst columnNames = columns.map((col) => `[${col}]`).join(\", \");\n\t\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\t\tawait transaction.begin();\n\n\t\t\tfor (let i = 0; i < records.length; i++) {\n\t\t\t\tconst record = records[i];\n\t\t\t\tconst request = transaction.request();\n\t\t\t\tconst values = columns.map((col) => {\n\t\t\t\t\tconst value = record[col];\n\t\t\t\t\tif (booleanColumns.has(col) && typeof value === \"string\") {\n\t\t\t\t\t\treturn value === \"true\" ? 1 : 0;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t});\n\n\t\t\t\tconst paramNames = columns.map((_, idx) => `@p${i}_${idx}`).join(\", \");\n\t\t\t\tcolumns.forEach((_col, idx) => {\n\t\t\t\t\trequest.input(`p${i}_${idx}`, values[idx]);\n\t\t\t\t});\n\n\t\t\t\ttry {\n\t\t\t\t\tawait request.query(\n\t\t\t\t\t\t`INSERT INTO [${tableName}] (${columnNames}) VALUES (${paramNames})`,\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new HTTPException(500, {\n\t\t\t\t\t\tmessage: `Failed to insert record ${i + 1}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait transaction.commit();\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `Successfully inserted ${records.length} record${records.length !== 1 ? \"s\" : \"\"}`,\n\t\t\t\tsuccessCount: records.length,\n\t\t\t\tfailureCount: 0,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tawait transaction.rollback();\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to bulk insert records into \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\t// --- Query ---\n\n\tasync executeQuery({\n\t\tquery,\n\t\tdb,\n\t}: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tif (!query?.trim()) throw new HTTPException(400, { message: \"Query is required\" });\n\n\t\tconst cleanedQuery = query.trim().replace(/;+$/, \"\");\n\t\tconst start = performance.now();\n\t\tconst result = await pool.request().query(cleanedQuery);\n\t\tconst duration = performance.now() - start;\n\n\t\tif (result.recordset) {\n\t\t\tconst rows = result.recordset as Record<string, unknown>[];\n\t\t\tconst columns = result.recordset.columns\n\t\t\t\t? Object.keys(result.recordset.columns)\n\t\t\t\t: Object.keys(rows[0] ?? {});\n\t\t\treturn {\n\t\t\t\tcolumns,\n\t\t\t\trows,\n\t\t\t\trowCount: rows.length,\n\t\t\t\tduration,\n\t\t\t\tmessage: rows.length === 0 ? \"OK\" : undefined,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tcolumns: [],\n\t\t\trows: [],\n\t\t\trowCount: result.rowsAffected[0] ?? 0,\n\t\t\tduration,\n\t\t\tmessage: `OK — ${result.rowsAffected[0] ?? 0} row(s) affected`,\n\t\t};\n\t}\n\n\t// =========================================================\n\t// Private helpers\n\t// =========================================================\n\n\tprivate async getForeignKeyReferences(\n\t\ttableName: string,\n\t\tdb: string,\n\t): Promise<ForeignKeyConstraint[]> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst result = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT\n\t\t\t\t fk.name AS constraint_name,\n\t\t\t\t OBJECT_NAME(fk.parent_object_id) AS referencing_table,\n\t\t\t\t COL_NAME(fkc.parent_object_id, fkc.parent_column_id) AS referencing_column,\n\t\t\t\t OBJECT_NAME(fk.referenced_object_id) AS referenced_table,\n\t\t\t\t COL_NAME(fkc.referenced_object_id, fkc.referenced_column_id) AS referenced_column\n\t\t\t\tFROM sys.foreign_keys fk\n\t\t\t\tINNER JOIN sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id\n\t\t\t\tWHERE OBJECT_NAME(fk.referenced_object_id) = @tableName\n\t\t\t`);\n\t\treturn (result.recordset as FkConstraintRow[]).map((row) => ({\n\t\t\tconstraintName: row.constraint_name,\n\t\t\treferencingTable: row.referencing_table,\n\t\t\treferencingColumn: row.referencing_column,\n\t\t\treferencedTable: row.referenced_table,\n\t\t\treferencedColumn: row.referenced_column,\n\t\t}));\n\t}\n\n\tprivate async getRelatedRecordsForTable(\n\t\ttableName: string,\n\t\tdb: string,\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getForeignKeyReferences(tableName, db);\n\t\tif (fks.length === 0) return [];\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst results: RelatedRecord[] = [];\n\t\tfor (const fk of fks) {\n\t\t\tconst relatedResult = await pool\n\t\t\t\t.request()\n\t\t\t\t.query(`SELECT TOP 100 * FROM [${fk.referencingTable}]`);\n\t\t\tif (relatedResult.recordset.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: relatedResult.recordset as Record<string, unknown>[],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate async getRelatedRecords(\n\t\ttableName: string,\n\t\tprimaryKeys: DeleteRecordSchemaType[\"primaryKeys\"],\n\t\tdb: string,\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getForeignKeyReferences(tableName, db);\n\t\tif (fks.length === 0) return [];\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst results: RelatedRecord[] = [];\n\n\t\tconst constraintsByTable = new Map<string, ForeignKeyConstraint[]>();\n\t\tfor (const fk of fks) {\n\t\t\tconst key = `${fk.referencingTable}.${fk.referencingColumn}`;\n\t\t\tif (!constraintsByTable.has(key)) constraintsByTable.set(key, []);\n\t\t\tconstraintsByTable.get(key)?.push(fk);\n\t\t}\n\n\t\tfor (const [, constraints] of constraintsByTable) {\n\t\t\tconst fk = constraints[0];\n\t\t\tif (!fk) continue;\n\t\t\tconst matchingPk = primaryKeys.find((pk) => pk.columnName === fk.referencedColumn);\n\t\t\tif (!matchingPk) continue;\n\n\t\t\tconst request = pool.request();\n\t\t\tpkValues.forEach((value, idx) => {\n\t\t\t\trequest.input(`pk${idx}`, value);\n\t\t\t});\n\t\t\tconst paramList = pkValues.map((_, idx) => `@pk${idx}`).join(\", \");\n\n\t\t\tconst relatedResult = await request.query(\n\t\t\t\t`SELECT TOP 100 * FROM [${fk.referencingTable}] WHERE [${fk.referencingColumn}] IN (${paramList})`,\n\t\t\t);\n\t\t\tif (relatedResult.recordset.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: relatedResult.recordset as Record<string, unknown>[],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate async getTableRowCount(tableName: string, db: string): Promise<number> {\n\t\tconst pool = await getMssqlPool(db);\n\t\tconst result = await pool.request().query(`SELECT COUNT(*) as count FROM [${tableName}]`);\n\t\treturn Number(result.recordset[0]?.count ?? 0);\n\t}\n\n\tprivate async getPrimaryKeyColumns(pool: MssqlPool, tableName: string): Promise<string[]> {\n\t\tconst result = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT ku.COLUMN_NAME AS columnName\n\t\t\t\tFROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc\n\t\t\t\tJOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku\n\t\t\t\t ON tc.CONSTRAINT_NAME = ku.CONSTRAINT_NAME\n\t\t\t\t AND tc.TABLE_SCHEMA = ku.TABLE_SCHEMA\n\t\t\t\t AND tc.TABLE_NAME = ku.TABLE_NAME\n\t\t\t\tWHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY'\n\t\t\t\t AND tc.TABLE_NAME = @tableName\n\t\t\t\t AND tc.TABLE_SCHEMA = 'dbo'\n\t\t\t\tORDER BY ku.ORDINAL_POSITION\n\t\t\t`);\n\t\treturn (result.recordset as { columnName: string }[]).map((r) => r.columnName);\n\t}\n\n\tprivate async getBooleanColumnSet(tableName: string, db: string): Promise<Set<string>> {\n\t\tconst cols = await this.getTableColumns({ tableName, db });\n\t\treturn new Set(cols.filter((c) => c.dataTypeLabel === \"boolean\").map((c) => c.columnName));\n\t}\n\n\tprivate async assertTableExists(pool: MssqlPool, tableName: string): Promise<void> {\n\t\tconst result = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.query(`\n\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.TABLES\n\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND TABLE_SCHEMA = 'dbo'\n\t\t\t`);\n\t\tif (Number(result.recordset[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\t}\n\n\tprivate async assertColumnExists(\n\t\tpool: MssqlPool,\n\t\ttableName: string,\n\t\tcolumnName: string,\n\t): Promise<void> {\n\t\tconst result = await pool\n\t\t\t.request()\n\t\t\t.input(\"tableName\", tableName)\n\t\t\t.input(\"columnName\", columnName)\n\t\t\t.query(`\n\t\t\t\tSELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.COLUMNS\n\t\t\t\tWHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND COLUMN_NAME = @columnName AND TABLE_SCHEMA = 'dbo'\n\t\t\t`);\n\t\tif (Number(result.recordset[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate parseCheckConstraintValues(checkClause: string): string[] | null {\n\t\tconst matches = checkClause.match(/'([^']+)'/g);\n\t\tif (!matches || matches.length === 0) return null;\n\t\treturn matches.map((m) => m.slice(1, -1));\n\t}\n\n\tprivate makeCursor(offset: number): string {\n\t\treturn this.encodeCursor({ values: { _offset: offset }, sortColumns: [\"_offset\"] });\n\t}\n\n\tprivate decodeOffsetCursor(cursor: string): number {\n\t\tconst data = this.decodeCursor(cursor);\n\t\treturn Number(data?.values._offset ?? 0);\n\t}\n}\n","import type { CursorData, FilterType, SortDirection, SortType } from \"@db-studio/shared/types\";\n\nexport function buildWhereClause(filters: FilterType[]): {\n\tclause: string;\n\tvalues: unknown[];\n} {\n\tif (filters.length === 0) return { clause: \"\", values: [] };\n\n\tconst conditions: string[] = [];\n\tconst values: unknown[] = [];\n\n\tfor (const filter of filters) {\n\t\tconst col = `\\`${filter.columnName}\\``;\n\t\tswitch (filter.operator) {\n\t\t\tcase \"=\":\n\t\t\tcase \"!=\":\n\t\t\tcase \">\":\n\t\t\tcase \">=\":\n\t\t\tcase \"<\":\n\t\t\tcase \"<=\":\n\t\t\t\tconditions.push(`${col} ${filter.operator} ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"is\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${col} IS NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} = ?`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"is not\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${col} IS NOT NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} != ?`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"like\":\n\t\t\tcase \"ilike\":\n\t\t\t\tconditions.push(`${col} LIKE ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"not like\":\n\t\t\tcase \"not ilike\":\n\t\t\t\tconditions.push(`${col} NOT LIKE ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (conditions.length === 0) return { clause: \"\", values: [] };\n\treturn { clause: `WHERE ${conditions.join(\" AND \")}`, values };\n}\n\nexport function buildSortClause(sorts: SortType[] | string, order: SortDirection): string {\n\tif (Array.isArray(sorts)) {\n\t\tif (sorts.length === 0) return \"\";\n\t\treturn `ORDER BY ${sorts.map((s) => `\\`${s.columnName}\\` ${s.direction.toUpperCase()}`).join(\", \")}`;\n\t}\n\tif (sorts && typeof sorts === \"string\") {\n\t\treturn `ORDER BY \\`${sorts}\\` ${order?.toUpperCase() || \"ASC\"}`;\n\t}\n\treturn \"\";\n}\n\nexport function buildCursorWhereClause(\n\tcursorData: CursorData,\n\tdirection: SortDirection,\n\tsortDirection: SortDirection,\n): { clause: string; values: unknown[] } {\n\tconst { values, sortColumns } = cursorData;\n\tif (sortColumns.length === 0) return { clause: \"\", values: [] };\n\n\tconst isAscending = sortDirection === \"asc\";\n\tconst isForward = direction === \"asc\";\n\tconst useGreaterThan = isAscending === isForward;\n\tconst operator = useGreaterThan ? \">\" : \"<\";\n\n\tconst columnList = sortColumns.map((col) => `\\`${col}\\``).join(\", \");\n\tconst placeholders = sortColumns.map(() => \"?\").join(\", \");\n\tconst queryValues = sortColumns.map((col) => values[col]);\n\n\treturn {\n\t\tclause: `(${columnList}) ${operator} (${placeholders})`,\n\t\tvalues: queryValues,\n\t};\n}\n\ntype MysqlColumnDefinitionInput = {\n\tcolumnName: string;\n\tcolumnType: string;\n\tdefaultValue?: string | null;\n\tisPrimaryKey?: boolean;\n\tisNullable?: boolean;\n\tisUnique?: boolean;\n\tisIdentity?: boolean;\n\tisArray?: boolean;\n};\n\ntype BuildMysqlColumnDefinitionOptions = {\n\tincludePrimaryKey?: boolean;\n\tincludeUnique?: boolean;\n\tpreserveAutoIncrement?: boolean;\n};\n\nexport function mapColumnTypeToMysql(columnType: string, isArray: boolean): string {\n\tif (isArray) return \"JSON\";\n\tconst normalized = columnType.toLowerCase().trim();\n\tconst typeMap: Record<string, string> = {\n\t\tserial: \"INT AUTO_INCREMENT\",\n\t\tserial4: \"INT AUTO_INCREMENT\",\n\t\tbigserial: \"BIGINT AUTO_INCREMENT\",\n\t\tserial8: \"BIGINT AUTO_INCREMENT\",\n\t\tint: \"INT\",\n\t\tint4: \"INT\",\n\t\tinteger: \"INT\",\n\t\tbigint: \"BIGINT\",\n\t\tint8: \"BIGINT\",\n\t\tsmallint: \"SMALLINT\",\n\t\tint2: \"SMALLINT\",\n\t\tnumeric: \"DECIMAL\",\n\t\tdecimal: \"DECIMAL\",\n\t\treal: \"FLOAT\",\n\t\tfloat4: \"FLOAT\",\n\t\tfloat: \"FLOAT\",\n\t\t\"double precision\": \"DOUBLE\",\n\t\tfloat8: \"DOUBLE\",\n\t\tmoney: \"DECIMAL(19, 4)\",\n\t\tboolean: \"TINYINT(1)\",\n\t\tbool: \"TINYINT(1)\",\n\t\ttext: \"LONGTEXT\",\n\t\tvarchar: \"VARCHAR(255)\",\n\t\t\"character varying\": \"VARCHAR(255)\",\n\t\tchar: \"CHAR(1)\",\n\t\tcharacter: \"CHAR(1)\",\n\t\tbpchar: \"CHAR\",\n\t\tuuid: \"CHAR(36)\",\n\t\tjson: \"JSON\",\n\t\tjsonb: \"JSON\",\n\t\txml: \"LONGTEXT\",\n\t\tdate: \"DATE\",\n\t\ttime: \"TIME\",\n\t\t\"time without time zone\": \"TIME\",\n\t\ttimestamp: \"DATETIME\",\n\t\t\"timestamp without time zone\": \"DATETIME\",\n\t\t\"timestamp with time zone\": \"DATETIME\",\n\t\ttimestamptz: \"DATETIME\",\n\t\tinterval: \"VARCHAR(255)\",\n\t\tbytea: \"LONGBLOB\",\n\t\tinet: \"VARCHAR(45)\",\n\t\tcidr: \"VARCHAR(45)\",\n\t\tmacaddr: \"VARCHAR(17)\",\n\t\tmacaddr8: \"VARCHAR(23)\",\n\t\tpoint: \"POINT\",\n\t\tline: \"LINESTRING\",\n\t\tpolygon: \"POLYGON\",\n\t};\n\treturn typeMap[normalized] || columnType.toUpperCase();\n}\n\nexport function formatMysqlDefaultValue(\n\tdefaultValue: string | null | undefined,\n\tcolumnType: string,\n): string | null {\n\tif (!defaultValue?.trim()) return null;\n\tconst trimmed = defaultValue.trim().toLowerCase();\n\n\tif (trimmed.includes(\"(\") && trimmed.includes(\")\")) {\n\t\tif (trimmed.includes(\"uuid()\")) {\n\t\t\tif (\n\t\t\t\t!columnType.toUpperCase().includes(\"CHAR\") &&\n\t\t\t\t!columnType.toUpperCase().includes(\"TEXT\")\n\t\t\t) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn \"(UUID())\";\n\t\t}\n\t\tif (trimmed.includes(\"current_timestamp\") || trimmed.includes(\"now()\"))\n\t\t\treturn \"(CURRENT_TIMESTAMP)\";\n\t\tif (trimmed.includes(\"current_date\")) return \"(CURRENT_DATE)\";\n\t\treturn `(${defaultValue.trim()})`;\n\t}\n\n\tif (trimmed === \"null\") return \"NULL\";\n\tif (trimmed === \"true\") return \"1\";\n\tif (trimmed === \"false\") return \"0\";\n\treturn defaultValue.trim();\n}\n\nexport function buildMysqlColumnDefinition(\n\tfield: MysqlColumnDefinitionInput,\n\toptions: BuildMysqlColumnDefinitionOptions = {},\n): string {\n\tconst mappedType = mapColumnTypeToMysql(field.columnType, field.isArray ?? false);\n\tlet def = `\\`${field.columnName}\\` ${mappedType}`;\n\n\tif (!field.isNullable && !field.isPrimaryKey) def += \" NOT NULL\";\n\n\tif (field.defaultValue && !mappedType.includes(\"AUTO_INCREMENT\")) {\n\t\tconst dv = formatMysqlDefaultValue(field.defaultValue, mappedType);\n\t\tif (dv !== null) def += ` DEFAULT ${dv}`;\n\t}\n\n\tif (\n\t\t(field.isIdentity || options.preserveAutoIncrement) &&\n\t\t!mappedType.includes(\"AUTO_INCREMENT\")\n\t) {\n\t\tdef += \" AUTO_INCREMENT\";\n\t}\n\n\tif (options.includeUnique && field.isUnique && !field.isPrimaryKey) def += \" UNIQUE\";\n\tif (options.includePrimaryKey && field.isPrimaryKey) def += \" PRIMARY KEY\";\n\n\treturn def;\n}\n","import type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tCursorData,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteRecordSchemaType,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tFieldDataType,\n\tForeignKeyConstraint,\n\tForeignKeyConstraintRow,\n\tForeignKeyDataType,\n\tRelatedRecord,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tSortDirection,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { mapMysqlToDataType, standardizeMysqlDataTypeLabel } from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { FieldPacket, ResultSetHeader, RowDataPacket } from \"mysql2\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getMysqlPool } from \"@/adapters/connections.js\";\nimport { parseDatabaseUrl } from \"@/utils/parse-database-url.js\";\nimport {\n\tbuildCursorWhereClause,\n\tbuildMysqlColumnDefinition,\n\tbuildSortClause,\n\tbuildWhereClause,\n} from \"./mysql.query-builder.js\";\n\ntype MysqlPool = ReturnType<typeof getMysqlPool>;\n\nconst MYSQL_FK_VIOLATION = 1451;\nconst MYSQL_FK_DEPENDENCY = 1217;\n\nexport class MySqlAdapter extends BaseAdapter {\n\tprivate mariaDb?: Promise<boolean>;\n\n\t// =========================================================\n\t// Abstract method implementations\n\t// =========================================================\n\n\tprotected async runQuery<T>(db: string, sql: string, values: unknown[]): Promise<T> {\n\t\tconst pool = getMysqlPool(db);\n\t\t// biome-ignore lint/suspicious/noExplicitAny: mysql2 execute doesn't accept unknown[]\n\t\tconst [rows] = await pool.execute(sql, values as any);\n\t\treturn rows as T;\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn `\\`${name}\\``;\n\t}\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\treturn mapMysqlToDataType(nativeType);\n\t}\n\n\tmapFromUniversalType(universalType: string): string {\n\t\tconst map: Record<string, string> = {\n\t\t\ttext: \"LONGTEXT\",\n\t\t\tnumber: \"INT\",\n\t\t\tboolean: \"TINYINT(1)\",\n\t\t\tjson: \"JSON\",\n\t\t\tdate: \"DATETIME\",\n\t\t\tarray: \"JSON\",\n\t\t\tenum: \"TEXT\",\n\t\t};\n\t\treturn map[universalType] ?? \"LONGTEXT\";\n\t}\n\n\tprotected buildTableDataQuery(params: GetTableDataParams): QueryBundle {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tcursor = \"\",\n\t\t\tlimit = 50,\n\t\t\tdirection = \"asc\",\n\t\t\tsort = [],\n\t\t\torder = \"asc\",\n\t\t\tfilters = [],\n\t\t} = params;\n\n\t\tlet sortColumns: string[] = [];\n\t\tlet effectiveSortDirection: SortDirection = order;\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t\teffectiveSortDirection = sort[0].direction;\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\n\t\tconst { clause: filterWhere, values: filterValues } = buildWhereClause(filters);\n\n\t\tlet cursorWhere = \"\";\n\t\tlet cursorValues: unknown[] = [];\n\t\tif (cursor) {\n\t\t\tconst cursorData = this.decodeCursor(cursor);\n\t\t\tif (cursorData) {\n\t\t\t\tconst res = buildCursorWhereClause(cursorData, direction, effectiveSortDirection);\n\t\t\t\tcursorWhere = res.clause;\n\t\t\t\tcursorValues = res.values;\n\t\t\t}\n\t\t}\n\n\t\tlet combinedWhere = \"\";\n\t\tif (filterWhere && cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${filterWhere.replace(/^WHERE\\s+/i, \"\")} AND ${cursorWhere}`;\n\t\t} else if (filterWhere) {\n\t\t\tcombinedWhere = filterWhere;\n\t\t} else if (cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${cursorWhere}`;\n\t\t}\n\n\t\tconst sortClause = buildSortClause(Array.isArray(sort) ? sort : sort, order);\n\t\tlet effectiveSortClause = sortClause;\n\t\tif (direction === \"desc\") {\n\t\t\tif (sortClause) {\n\t\t\t\teffectiveSortClause = sortClause\n\t\t\t\t\t.replace(/\\bASC\\b/gi, \"TEMP_DESC\")\n\t\t\t\t\t.replace(/\\bDESC\\b/gi, \"ASC\")\n\t\t\t\t\t.replace(/TEMP_DESC/g, \"DESC\");\n\t\t\t} else if (sortColumns.length > 0) {\n\t\t\t\teffectiveSortClause = `ORDER BY ${sortColumns.map((col) => `\\`${col}\\` ${effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\"}`).join(\", \")}`;\n\t\t\t}\n\t\t} else if (!sortClause && sortColumns.length > 0) {\n\t\t\teffectiveSortClause = `ORDER BY ${sortColumns.map((col) => `\\`${col}\\` ${effectiveSortDirection.toUpperCase()}`).join(\", \")}`;\n\t\t}\n\n\t\tconst sql = `SELECT * FROM \\`${tableName}\\` ${combinedWhere} ${effectiveSortClause} LIMIT ${limit + 1}`;\n\t\tconst values = [...filterValues, ...cursorValues];\n\t\tconst countSql = `SELECT COUNT(*) as total FROM \\`${tableName}\\` ${filterWhere}`;\n\n\t\treturn { sql, values, countSql, countValues: filterValues };\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn (rawRows as Record<string, unknown>[]).map((row) => this.normalizeRow(row));\n\t}\n\n\tprotected buildCursors(\n\t\tparams: GetTableDataParams,\n\t\trows: NormalizedRow[],\n\t\thasMore: boolean,\n\t): { nextCursor: string | null; prevCursor: string | null } {\n\t\tif (rows.length === 0) return { nextCursor: null, prevCursor: null };\n\n\t\tconst { direction = \"asc\", sort = [], cursor } = params;\n\t\tlet sortColumns: string[] = [];\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\n\t\tconst createCursor = (row: NormalizedRow): string =>\n\t\t\tthis.encodeCursor({\n\t\t\t\tvalues: Object.fromEntries(sortColumns.map((col) => [col, row[col]])),\n\t\t\t\tsortColumns,\n\t\t\t} satisfies CursorData);\n\n\t\tconst firstRow = rows[0];\n\t\tconst lastRow = rows[rows.length - 1];\n\t\tlet nextCursor: string | null = null;\n\t\tlet prevCursor: string | null = null;\n\n\t\tif (direction === \"asc\") {\n\t\t\tif (hasMore) nextCursor = createCursor(lastRow);\n\t\t\tif (cursor) prevCursor = createCursor(firstRow);\n\t\t} else {\n\t\t\tif (cursor) nextCursor = createCursor(lastRow);\n\t\t\tif (hasMore) prevCursor = createCursor(firstRow);\n\t\t}\n\n\t\treturn { nextCursor, prevCursor };\n\t}\n\n\t// =========================================================\n\t// Override getTableData to incorporate primary-key cursor columns\n\t// =========================================================\n\n\toverride async getTableData(params: GetTableDataParams) {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tdb,\n\t\t\tlimit = 50,\n\t\t\tdirection = \"asc\",\n\t\t\tsort = [],\n\t\t\torder = \"asc\",\n\t\t\tcursor,\n\t\t\tfilters = [],\n\t\t} = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tconst pkColumns = await this.getPrimaryKeyColumns(pool, tableName);\n\n\t\tlet sortColumns: string[] = [];\n\t\tlet effectiveSortDirection: SortDirection = order;\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t\teffectiveSortDirection = sort[0].direction;\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\n\t\tconst cursorColumns = [\n\t\t\t...sortColumns,\n\t\t\t...pkColumns.filter((pk) => !sortColumns.includes(pk)),\n\t\t];\n\n\t\tconst { clause: filterWhere, values: filterValues } = buildWhereClause(filters);\n\n\t\tlet cursorWhere = \"\";\n\t\tlet cursorValues: unknown[] = [];\n\t\tif (cursor) {\n\t\t\tconst cursorData = this.decodeCursor(cursor);\n\t\t\tif (cursorData) {\n\t\t\t\tconst res = buildCursorWhereClause(cursorData, direction, effectiveSortDirection);\n\t\t\t\tcursorWhere = res.clause;\n\t\t\t\tcursorValues = res.values;\n\t\t\t}\n\t\t}\n\n\t\tlet combinedWhere = \"\";\n\t\tif (filterWhere && cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${filterWhere.replace(/^WHERE\\s+/i, \"\")} AND ${cursorWhere}`;\n\t\t} else if (filterWhere) {\n\t\t\tcombinedWhere = filterWhere;\n\t\t} else if (cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${cursorWhere}`;\n\t\t}\n\n\t\tconst sortClause = buildSortClause(Array.isArray(sort) ? sort : sort, order);\n\t\tconst pkTieBreakerCols = pkColumns.filter((pk) => !sortColumns.includes(pk));\n\t\tlet effectiveSortClause = sortClause;\n\t\tif (direction === \"desc\") {\n\t\t\tif (sortClause) {\n\t\t\t\teffectiveSortClause = sortClause\n\t\t\t\t\t.replace(/\\bASC\\b/gi, \"TEMP_DESC\")\n\t\t\t\t\t.replace(/\\bDESC\\b/gi, \"ASC\")\n\t\t\t\t\t.replace(/TEMP_DESC/g, \"DESC\");\n\t\t\t\tif (pkTieBreakerCols.length) {\n\t\t\t\t\tconst tbDir = effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\";\n\t\t\t\t\teffectiveSortClause += `, ${pkTieBreakerCols.map((col) => `\\`${col}\\` ${tbDir}`).join(\", \")}`;\n\t\t\t\t}\n\t\t\t} else if (cursorColumns.length > 0) {\n\t\t\t\teffectiveSortClause = `ORDER BY ${cursorColumns.map((col) => `\\`${col}\\` ${effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\"}`).join(\", \")}`;\n\t\t\t}\n\t\t} else if (!sortClause && cursorColumns.length > 0) {\n\t\t\teffectiveSortClause = `ORDER BY ${cursorColumns.map((col) => `\\`${col}\\` ${effectiveSortDirection.toUpperCase()}`).join(\", \")}`;\n\t\t} else if (pkTieBreakerCols.length) {\n\t\t\teffectiveSortClause += `, ${pkTieBreakerCols.map((col) => `\\`${col}\\` ${effectiveSortDirection.toUpperCase()}`).join(\", \")}`;\n\t\t}\n\n\t\tconst [countRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as total FROM \\`${tableName}\\` ${filterWhere}`,\n\t\t\tfilterValues as any,\n\t\t);\n\t\tconst total = Number((countRows as Array<{ total: number }>)[0]?.total ?? 0);\n\n\t\tconst [dataRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT * FROM \\`${tableName}\\` ${combinedWhere} ${effectiveSortClause} LIMIT ${Math.floor(limit) + 1}`,\n\t\t\t[...filterValues, ...cursorValues] as any,\n\t\t);\n\n\t\tlet rows = dataRows as Record<string, unknown>[];\n\t\tconst hasMore = rows.length > limit;\n\t\tif (hasMore) rows = rows.slice(0, limit);\n\t\tif (direction === \"desc\") rows = rows.reverse();\n\n\t\tlet nextCursor: string | null = null;\n\t\tlet prevCursor: string | null = null;\n\n\t\tif (rows.length > 0 && cursorColumns.length > 0) {\n\t\t\tconst firstRow = rows[0];\n\t\t\tconst lastRow = rows[rows.length - 1];\n\t\t\tconst makeCursor = (row: Record<string, unknown>): CursorData => ({\n\t\t\t\tvalues: Object.fromEntries(cursorColumns.map((col) => [col, row[col]])),\n\t\t\t\tsortColumns: cursorColumns,\n\t\t\t});\n\n\t\t\tif (direction === \"asc\") {\n\t\t\t\tif (hasMore) nextCursor = this.encodeCursor(makeCursor(lastRow));\n\t\t\t\tif (cursor) prevCursor = this.encodeCursor(makeCursor(firstRow));\n\t\t\t} else {\n\t\t\t\tif (cursor) nextCursor = this.encodeCursor(makeCursor(lastRow));\n\t\t\t\tif (hasMore) prevCursor = this.encodeCursor(makeCursor(firstRow));\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tdata: rows,\n\t\t\tmeta: {\n\t\t\t\tlimit,\n\t\t\t\ttotal,\n\t\t\t\thasNextPage: direction === \"asc\" ? hasMore : !!cursor,\n\t\t\t\thasPreviousPage: direction === \"asc\" ? !!cursor : hasMore,\n\t\t\t\tnextCursor,\n\t\t\t\tprevCursor,\n\t\t\t},\n\t\t};\n\t}\n\n\t// =========================================================\n\t// IDbAdapter implementations\n\t// =========================================================\n\n\t// --- Databases ---\n\n\tasync getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst pool = getMysqlPool();\n\t\t\tconst [rows] = await pool.execute<RowDataPacket[]>(`\n\t\t\t\tSELECT\n\t\t\t\t s.SCHEMA_NAME AS name,\n\t\t\t\t CONCAT(ROUND(COALESCE(SUM(t.data_length + t.index_length), 0) / 1024 / 1024, 2), ' MB') AS size,\n\t\t\t\t CURRENT_USER() AS owner,\n\t\t\t\t s.DEFAULT_CHARACTER_SET_NAME AS encoding\n\t\t\t\tFROM information_schema.SCHEMATA s\n\t\t\t\tLEFT JOIN information_schema.TABLES t ON t.TABLE_SCHEMA = s.SCHEMA_NAME\n\t\t\t\tWHERE (s.SCHEMA_NAME NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys') OR s.SCHEMA_NAME = DATABASE())\n\t\t\t\tGROUP BY s.SCHEMA_NAME, s.DEFAULT_CHARACTER_SET_NAME\n\t\t\t\tORDER BY s.SCHEMA_NAME\n\t\t\t`);\n\t\t\tif (!rows[0])\n\t\t\t\tthrow new HTTPException(500, { message: \"No databases returned from server\" });\n\t\t\treturn rows as DatabaseInfoSchemaType[];\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\tconst pool = getMysqlPool();\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\"SELECT DATABASE() AS db\");\n\t\tif (!rows[0])\n\t\t\tthrow new HTTPException(500, { message: \"No current database returned from server\" });\n\t\treturn (rows as Array<{ db: string }>)[0] as DatabaseSchemaType;\n\t}\n\n\tasync getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\tconst pool = getMysqlPool();\n\t\tconst [infoRows] = await pool.execute<RowDataPacket[]>(`\n\t\t\tSELECT\n\t\t\t VERSION() AS version,\n\t\t\t DATABASE() AS database_name,\n\t\t\t CURRENT_USER() AS user,\n\t\t\t @@hostname AS host,\n\t\t\t @@port AS port,\n\t\t\t @@max_connections AS max_connections\n\t\t`);\n\t\tconst [connRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t\"SELECT COUNT(*) AS cnt FROM information_schema.PROCESSLIST\",\n\t\t);\n\t\tif (!infoRows[0])\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: \"No connection information returned from server\",\n\t\t\t});\n\n\t\tconst info = (infoRows as Array<Record<string, string | number>>)[0];\n\t\tconst urlDefaults = parseDatabaseUrl();\n\n\t\treturn {\n\t\t\thost: String(info.host || urlDefaults.host),\n\t\t\tport: Number(info.port || urlDefaults.port),\n\t\t\tuser: String(info.user),\n\t\t\tdatabase: String(info.database_name ?? \"\"),\n\t\t\tversion: String(info.version),\n\t\t\tactive_connections: Number((connRows as Array<{ cnt: number }>)[0]?.cnt ?? 0),\n\t\t\tmax_connections: Number(info.max_connections),\n\t\t};\n\t}\n\n\t// --- Tables ---\n\n\tasync getTablesList(db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\tconst pool = getMysqlPool(db);\n\t\tconst [tables] = await pool.execute<RowDataPacket[]>(`\n\t\t\tSELECT table_name as tableName\n\t\t\tFROM information_schema.tables\n\t\t\tWHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'\n\t\t\tORDER BY table_name\n\t\t`);\n\t\tif (!tables || tables.length === 0) return [];\n\n\t\treturn Promise.all(\n\t\t\t(tables as Array<{ tableName: string }>).map(async (table) => {\n\t\t\t\tconst [countRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t\t\t`SELECT COUNT(*) as count FROM \\`${table.tableName}\\``,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\ttableName: table.tableName,\n\t\t\t\t\trowCount: (countRows as Array<{ count: number }>)[0]?.count ?? 0,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\t}\n\n\tasync createTable({\n\t\ttableData,\n\t\tdb,\n\t}: {\n\t\ttableData: CreateTableSchemaType;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<void> {\n\t\tconst { tableName, fields, foreignKeys } = tableData;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tconst columnDefs = fields.map((field: FieldDataType) => buildMysqlColumnDefinition(field));\n\n\t\tconst constraintDefs: string[] = [];\n\t\tconst primaryKeyFields = fields.filter((f: FieldDataType) => f.isPrimaryKey);\n\t\tif (primaryKeyFields.length > 0) {\n\t\t\tconstraintDefs.push(\n\t\t\t\t`PRIMARY KEY (${primaryKeyFields.map((f: FieldDataType) => `\\`${f.columnName}\\``).join(\", \")})`,\n\t\t\t);\n\t\t}\n\t\tfor (const field of fields as FieldDataType[]) {\n\t\t\tif (field.isUnique && !field.isPrimaryKey) {\n\t\t\t\tconstraintDefs.push(\n\t\t\t\t\t`UNIQUE KEY \\`uq_${tableName}_${field.columnName}\\` (\\`${field.columnName}\\`)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst fkDefs =\n\t\t\tforeignKeys?.map((fk: ForeignKeyDataType) => {\n\t\t\t\tconst name = `fk_${tableName}_${fk.columnName}_${fk.referencedTable}_${fk.referencedColumn}`;\n\t\t\t\treturn `CONSTRAINT \\`${name}\\` FOREIGN KEY (\\`${fk.columnName}\\`) REFERENCES \\`${fk.referencedTable}\\` (\\`${fk.referencedColumn}\\`) ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}`;\n\t\t\t}) ?? [];\n\n\t\tawait pool.execute<ResultSetHeader>(\n\t\t\t`CREATE TABLE \\`${tableName}\\` (\\n\\t\\t\\t\\t${[...columnDefs, ...constraintDefs, ...fkDefs].join(\",\\n\\t\\t\\t\\t\")}\\n\\t\\t\\t) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`,\n\t\t);\n\t}\n\n\tasync deleteTable(params: DeleteTableParams): Promise<DeleteTableResult> {\n\t\tconst { tableName, db, cascade } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tconst [tableRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (Number((tableRows as Array<{ cnt: number }>)[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\n\t\tconst rowCount = await this.getTableRowCount(pool, tableName);\n\n\t\tif (!cascade) {\n\t\t\tconst relatedRecords = await this.getRelatedRecordsForTable(tableName, db);\n\t\t\tif (relatedRecords.length > 0) {\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tif (cascade) {\n\t\t\t\tconst connection = await pool.getConnection();\n\t\t\t\ttry {\n\t\t\t\t\tawait connection.execute(\"SET FOREIGN_KEY_CHECKS = 0\");\n\t\t\t\t\tawait connection.execute(`DROP TABLE \\`${tableName}\\``);\n\t\t\t\t\tawait connection.execute(\"SET FOREIGN_KEY_CHECKS = 1\");\n\t\t\t\t} finally {\n\t\t\t\t\tconnection.release();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait pool.execute(`DROP TABLE \\`${tableName}\\``);\n\t\t\t}\n\t\t\treturn { deletedCount: rowCount, fkViolation: false, relatedRecords: [] };\n\t\t} catch (error) {\n\t\t\tawait pool.execute(\"SET FOREIGN_KEY_CHECKS = 1\").catch(() => {});\n\t\t\tconst mysqlError = error as { errno?: number };\n\t\t\tif (\n\t\t\t\tmysqlError.errno === MYSQL_FK_DEPENDENCY ||\n\t\t\t\tmysqlError.errno === MYSQL_FK_VIOLATION\n\t\t\t) {\n\t\t\t\tconst relatedRecords = await this.getRelatedRecordsForTable(tableName, db);\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to delete table \"${tableName}\"` });\n\t\t}\n\t}\n\n\tasync renameTable(params: RenameTableParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, newTableName, db } = params;\n\t\t\tthis.assertDifferentTableName(tableName, newTableName);\n\t\t\tconst pool = getMysqlPool(db);\n\n\t\t\tawait this.assertTableExists(pool, tableName);\n\n\t\t\tconst [targetRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?`,\n\t\t\t\t[newTableName],\n\t\t\t);\n\t\t\tif (Number((targetRows as Array<{ cnt: number }>)[0]?.cnt ?? 0) > 0) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Table \"${newTableName}\" already exists`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait pool.execute<ResultSetHeader>(\n\t\t\t\t`RENAME TABLE \\`${tableName.replaceAll(\"`\", \"``\")}\\` TO \\`${newTableName.replaceAll(\"`\", \"``\")}\\``,\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getTableSchema({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\tconst pool = getMysqlPool(db);\n\t\tconst [tableRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (Number((tableRows as Array<{ cnt: number }>)[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(`SHOW CREATE TABLE \\`${tableName}\\``);\n\t\tconst row = (rows as Array<Record<string, string>>)[0];\n\t\tconst createTableSql = row?.[\"Create Table\"] ?? row?.create_table ?? \"\";\n\t\tif (!createTableSql) {\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to retrieve schema for table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t\treturn createTableSql;\n\t}\n\n\t// --- Columns ---\n\n\tasync getTableColumns({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\tconst pool = getMysqlPool(db);\n\t\t// MariaDB stores JSON as LONGTEXT guarded by a json_valid() column check.\n\t\tconst isJsonCheckedText = (await this.isMariaDb(pool))\n\t\t\t? `EXISTS (\n\t\t\t SELECT 1 FROM information_schema.CHECK_CONSTRAINTS cc\n\t\t\t WHERE cc.CONSTRAINT_SCHEMA = c.TABLE_SCHEMA\n\t\t\t AND cc.TABLE_NAME = c.TABLE_NAME\n\t\t\t AND cc.CHECK_CLAUSE = CONCAT('json_valid(\\`', c.COLUMN_NAME, '\\`)')\n\t\t\t )`\n\t\t\t: \"FALSE\";\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT\n\t\t\t c.COLUMN_NAME AS columnName,\n\t\t\t c.DATA_TYPE AS dataType,\n\t\t\t c.COLUMN_TYPE AS columnType,\n\t\t\t ${isJsonCheckedText} AS isJsonText,\n\t\t\t (c.IS_NULLABLE = 'YES') AS isNullable,\n\t\t\t c.COLUMN_DEFAULT AS columnDefault,\n\t\t\t (c.COLUMN_KEY = 'PRI') AS isPrimaryKey,\n\t\t\t (kcu.REFERENCED_TABLE_NAME IS NOT NULL) AS isForeignKey,\n\t\t\t kcu.REFERENCED_TABLE_NAME AS referencedTable,\n\t\t\t kcu.REFERENCED_COLUMN_NAME AS referencedColumn\n\t\t\tFROM information_schema.COLUMNS c\n\t\t\tLEFT JOIN information_schema.KEY_COLUMN_USAGE kcu\n\t\t\t ON c.TABLE_SCHEMA = kcu.TABLE_SCHEMA\n\t\t\t AND c.TABLE_NAME = kcu.TABLE_NAME\n\t\t\t AND c.COLUMN_NAME = kcu.COLUMN_NAME\n\t\t\t AND kcu.REFERENCED_TABLE_NAME IS NOT NULL\n\t\t\tWHERE c.TABLE_SCHEMA = DATABASE()\n\t\t\t AND c.TABLE_NAME = ?\n\t\t\tORDER BY c.ORDINAL_POSITION`,\n\t\t\t[tableName],\n\t\t);\n\n\t\tif (!rows || rows.length === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\n\t\treturn (\n\t\t\trows as Array<{\n\t\t\t\tcolumnName: string;\n\t\t\t\tdataType: string;\n\t\t\t\tcolumnType: string;\n\t\t\t\tisJsonText: number | boolean;\n\t\t\t\tisNullable: number | boolean;\n\t\t\t\tcolumnDefault: string | null;\n\t\t\t\tisPrimaryKey: number | boolean;\n\t\t\t\tisForeignKey: number | boolean;\n\t\t\t\treferencedTable: string | null;\n\t\t\t\treferencedColumn: string | null;\n\t\t\t}>\n\t\t).map((r) => {\n\t\t\tconst isEnum = r.dataType === \"enum\" || r.dataType === \"set\";\n\t\t\tconst [dataType, columnType] = r.isJsonText\n\t\t\t\t? [\"json\", \"json\"]\n\t\t\t\t: [r.dataType, r.columnType];\n\t\t\treturn {\n\t\t\t\tcolumnName: r.columnName,\n\t\t\t\tdataType: mapMysqlToDataType(dataType, columnType),\n\t\t\t\tdataTypeLabel: standardizeMysqlDataTypeLabel(dataType, columnType),\n\t\t\t\tisNullable: Boolean(r.isNullable),\n\t\t\t\tcolumnDefault: r.columnDefault ?? null,\n\t\t\t\tisPrimaryKey: Boolean(r.isPrimaryKey),\n\t\t\t\tisForeignKey: Boolean(r.isForeignKey),\n\t\t\t\treferencedTable: r.referencedTable ?? null,\n\t\t\t\treferencedColumn: r.referencedColumn ?? null,\n\t\t\t\tenumValues: isEnum ? this.parseMysqlEnumValues(r.columnType) : null,\n\t\t\t};\n\t\t});\n\t}\n\n\tasync addColumn(params: AddColumnParamsSchemaType): Promise<void> {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tcolumnName,\n\t\t\tcolumnType,\n\t\t\tdefaultValue,\n\t\t\tisPrimaryKey,\n\t\t\tisNullable,\n\t\t\tisUnique,\n\t\t\tisIdentity,\n\t\t\tisArray,\n\t\t\tdb,\n\t\t} = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\n\t\tconst [colRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?`,\n\t\t\t[tableName, columnName],\n\t\t);\n\t\tif (Number((colRows as Array<{ cnt: number }>)[0]?.cnt ?? 0) > 0) {\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${columnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\tconst colDef = buildMysqlColumnDefinition(\n\t\t\t{\n\t\t\t\tcolumnName,\n\t\t\t\tcolumnType,\n\t\t\t\tdefaultValue,\n\t\t\t\tisPrimaryKey,\n\t\t\t\tisNullable,\n\t\t\t\tisUnique,\n\t\t\t\tisIdentity,\n\t\t\t\tisArray,\n\t\t\t},\n\t\t\t{ includePrimaryKey: true, includeUnique: true },\n\t\t);\n\t\tawait pool.execute<ResultSetHeader>(`ALTER TABLE \\`${tableName}\\` ADD COLUMN ${colDef}`);\n\t}\n\n\tasync deleteColumn(params: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\tconst { tableName, columnName, db } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\t\tawait this.assertColumnExists(pool, tableName, columnName);\n\n\t\tconst [result] = await pool.execute<ResultSetHeader>(\n\t\t\t`ALTER TABLE \\`${tableName}\\` DROP COLUMN \\`${columnName}\\``,\n\t\t);\n\t\treturn { deletedCount: result.affectedRows };\n\t}\n\n\tasync alterColumn(params: AlterColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, columnType, isNullable, defaultValue, db } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\n\t\tconst [colRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ? LIMIT 1`,\n\t\t\t[tableName, columnName],\n\t\t);\n\t\tconst colRow = (colRows as Array<{ EXTRA?: string | null }>)[0];\n\t\tif (!colRow) {\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\tconst colDef = buildMysqlColumnDefinition(\n\t\t\t{ columnName, columnType, defaultValue, isNullable },\n\t\t\t{ preserveAutoIncrement: colRow.EXTRA?.toLowerCase().includes(\"auto_increment\") },\n\t\t);\n\t\tawait pool.execute<ResultSetHeader>(\n\t\t\t`ALTER TABLE \\`${tableName}\\` MODIFY COLUMN ${colDef}`,\n\t\t);\n\t}\n\n\tasync renameColumn(params: RenameColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, newColumnName, db } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tawait this.assertTableExists(pool, tableName);\n\t\tawait this.assertColumnExists(pool, tableName, columnName);\n\n\t\tconst [newColRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?`,\n\t\t\t[tableName, newColumnName],\n\t\t);\n\t\tif (Number((newColRows as Array<{ cnt: number }>)[0]?.cnt ?? 0) > 0) {\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${newColumnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\n\t\tawait pool.execute<ResultSetHeader>(\n\t\t\t`ALTER TABLE \\`${tableName}\\` RENAME COLUMN \\`${columnName}\\` TO \\`${newColumnName}\\``,\n\t\t);\n\t}\n\n\t// --- Records ---\n\n\tasync addRecord({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\tconst { tableName, data } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\t\tconst columns = Object.keys(data);\n\t\tconst values = Object.values(data).map((value, i) => {\n\t\t\tif (booleanColumns.has(columns[i]) && typeof value === \"string\") {\n\t\t\t\treturn value === \"true\" ? 1 : 0;\n\t\t\t}\n\t\t\treturn value;\n\t\t});\n\n\t\tconst [result] = await pool.execute<ResultSetHeader>(\n\t\t\t`INSERT INTO \\`${tableName}\\` (${columns.map((c) => `\\`${c}\\``).join(\", \")}) VALUES (${columns.map(() => \"?\").join(\", \")})`,\n\t\t\tvalues as any,\n\t\t);\n\t\tif (result.affectedRows === 0) {\n\t\t\tthrow new HTTPException(500, { message: `Failed to insert record into \"${tableName}\"` });\n\t\t}\n\t\treturn { insertedCount: result.affectedRows };\n\t}\n\n\tasync updateRecords({\n\t\tparams,\n\t\tdb,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\tconst { tableName } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\tconst keyColumns = this.resolveKeyColumns(params);\n\t\tthis.assertWholeKey(await this.getPrimaryKeyColumns(pool, tableName), keyColumns);\n\t\tconst groups = this.groupUpdatesByKey(params, keyColumns);\n\n\t\tconst connection = await pool.getConnection();\n\t\tawait connection.beginTransaction();\n\n\t\ttry {\n\t\t\tlet total = 0;\n\t\t\tfor (const { keyValues, rowUpdates } of groups) {\n\t\t\t\tconst setClauses = rowUpdates.map((u) => `\\`${u.columnName}\\` = ?`);\n\t\t\t\tconst values: unknown[] = rowUpdates.map((u) => {\n\t\t\t\t\tif (u.value !== null && typeof u.value === \"object\") return JSON.stringify(u.value);\n\t\t\t\t\tif (booleanColumns.has(u.columnName) && typeof u.value === \"string\") {\n\t\t\t\t\t\treturn u.value === \"true\" ? 1 : 0;\n\t\t\t\t\t}\n\t\t\t\t\treturn u.value;\n\t\t\t\t});\n\t\t\t\tvalues.push(...keyValues);\n\t\t\t\tconst whereClauses = keyColumns.map((column) => `\\`${column}\\` = ?`);\n\n\t\t\t\tconst [result] = await connection.execute<ResultSetHeader>(\n\t\t\t\t\t`UPDATE \\`${tableName}\\` SET ${setClauses.join(\", \")} WHERE ${whereClauses.join(\" AND \")}`,\n\t\t\t\t\tvalues as any,\n\t\t\t\t);\n\t\t\t\tif (result.affectedRows === 0) {\n\t\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\t\tmessage: `Record with ${this.describeKey(keyColumns, keyValues)} not found in table \"${tableName}\"`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\ttotal += result.affectedRows;\n\t\t\t}\n\t\t\tawait connection.commit();\n\t\t\treturn { updatedCount: total };\n\t\t} catch (error) {\n\t\t\tawait connection.rollback();\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to update records in \"${tableName}\"` });\n\t\t} finally {\n\t\t\tconnection.release();\n\t\t}\n\t}\n\n\tasync deleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\tconst pool = getMysqlPool(db);\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\t\tthis.assertDeletableKey(await this.getPrimaryKeyColumns(pool, tableName));\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst placeholders = pkValues.map(() => \"?\").join(\", \");\n\t\tconst connection = await pool.getConnection();\n\t\tawait connection.beginTransaction();\n\n\t\ttry {\n\t\t\tconst [result] = await connection.execute<ResultSetHeader>(\n\t\t\t\t`DELETE FROM \\`${tableName}\\` WHERE \\`${pkColumn}\\` IN (${placeholders})`,\n\t\t\t\tpkValues as any,\n\t\t\t);\n\t\t\tawait connection.commit();\n\t\t\treturn { deletedCount: result.affectedRows, fkViolation: false, relatedRecords: [] };\n\t\t} catch (error) {\n\t\t\tawait connection.rollback();\n\t\t\tconst mysqlError = error as { errno?: number };\n\t\t\tif (mysqlError.errno === MYSQL_FK_VIOLATION) {\n\t\t\t\tconst relatedRecords = await this.getRelatedRecords(tableName, primaryKeys, db);\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to delete records from \"${tableName}\"`,\n\t\t\t});\n\t\t} finally {\n\t\t\tconnection.release();\n\t\t}\n\t}\n\n\tasync forceDeleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<{ deletedCount: number }> {\n\t\tconst pool = getMysqlPool(db);\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\t\tthis.assertDeletableKey(await this.getPrimaryKeyColumns(pool, tableName));\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst connection = await pool.getConnection();\n\t\tawait connection.beginTransaction();\n\n\t\ttry {\n\t\t\tawait connection.execute(\"SET FOREIGN_KEY_CHECKS = 0\");\n\n\t\t\tconst fkConstraints = await this.getForeignKeyReferences(tableName, db);\n\t\t\tlet totalRelated = 0;\n\t\t\tconst deletedTables = new Set<string>();\n\t\t\tconst visited = new Set<string>();\n\n\t\t\tconst deleteRelatedRecursively = async (\n\t\t\t\ttargetTable: string,\n\t\t\t\ttargetColumn: string,\n\t\t\t\tvalues: unknown[],\n\t\t\t\tvisitedSet: Set<string>,\n\t\t\t) => {\n\t\t\t\tconst key = `${targetTable}.${targetColumn}`;\n\t\t\t\tif (visitedSet.has(key)) return;\n\t\t\t\tvisitedSet.add(key);\n\n\t\t\t\tconst nestedFks = await this.getForeignKeyReferences(targetTable, db);\n\t\t\t\tfor (const nestedFk of nestedFks) {\n\t\t\t\t\tconst nestedPh = values.map(() => \"?\").join(\", \");\n\t\t\t\t\tconst [selectRows] = await connection.execute<RowDataPacket[]>(\n\t\t\t\t\t\t`SELECT \\`${nestedFk.referencedColumn}\\` FROM \\`${targetTable}\\` WHERE \\`${targetColumn}\\` IN (${nestedPh})`,\n\t\t\t\t\t\tvalues as any[],\n\t\t\t\t\t);\n\t\t\t\t\tconst nestedValues = (selectRows as Record<string, unknown>[]).map(\n\t\t\t\t\t\t(row) => row[nestedFk.referencedColumn],\n\t\t\t\t\t);\n\t\t\t\t\tif (nestedValues.length > 0) {\n\t\t\t\t\t\tawait deleteRelatedRecursively(\n\t\t\t\t\t\t\tnestedFk.referencingTable,\n\t\t\t\t\t\t\tnestedFk.referencingColumn,\n\t\t\t\t\t\t\tnestedValues,\n\t\t\t\t\t\t\tvisitedSet,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst ph = values.map(() => \"?\").join(\", \");\n\t\t\t\tconst [deleteResult] = await connection.execute<ResultSetHeader>(\n\t\t\t\t\t`DELETE FROM \\`${targetTable}\\` WHERE \\`${targetColumn}\\` IN (${ph})`,\n\t\t\t\t\tvalues as any[],\n\t\t\t\t);\n\t\t\t\ttotalRelated += deleteResult.affectedRows;\n\t\t\t\tdeletedTables.add(targetTable);\n\t\t\t};\n\n\t\t\tfor (const constraint of fkConstraints) {\n\t\t\t\tif (!deletedTables.has(constraint.referencingTable)) {\n\t\t\t\t\tawait deleteRelatedRecursively(\n\t\t\t\t\t\tconstraint.referencingTable,\n\t\t\t\t\t\tconstraint.referencingColumn,\n\t\t\t\t\t\tpkValues,\n\t\t\t\t\t\tvisited,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst mainPh = pkValues.map(() => \"?\").join(\", \");\n\t\t\tconst [result] = await connection.execute<ResultSetHeader>(\n\t\t\t\t`DELETE FROM \\`${tableName}\\` WHERE \\`${pkColumn}\\` IN (${mainPh})`,\n\t\t\t\tpkValues as any,\n\t\t\t);\n\n\t\t\tawait connection.execute(\"SET FOREIGN_KEY_CHECKS = 1\");\n\t\t\tawait connection.commit();\n\t\t\treturn { deletedCount: result.affectedRows + totalRelated };\n\t\t} catch (error) {\n\t\t\tawait connection.execute(\"SET FOREIGN_KEY_CHECKS = 1\").catch(() => {});\n\t\t\tawait connection.rollback();\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to force delete records from \"${tableName}\"`,\n\t\t\t});\n\t\t} finally {\n\t\t\tconnection.release();\n\t\t}\n\t}\n\n\tasync bulkInsertRecords({\n\t\ttableName,\n\t\trecords,\n\t\tdb,\n\t}: BulkInsertRecordsParams): Promise<BulkInsertResult> {\n\t\tif (!records || records.length === 0) {\n\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\t\t}\n\n\t\tconst pool = getMysqlPool(db);\n\t\tconst connection = await pool.getConnection();\n\n\t\ttry {\n\t\t\tconst columns = Object.keys(records[0]);\n\t\t\tconst colNames = columns.map((c) => `\\`${c}\\``).join(\", \");\n\t\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\t\tawait connection.beginTransaction();\n\n\t\t\tfor (let i = 0; i < records.length; i++) {\n\t\t\t\tconst record = records[i];\n\t\t\t\tconst values = columns.map((col) => {\n\t\t\t\t\tconst value = record[col];\n\t\t\t\t\tif (booleanColumns.has(col) && typeof value === \"string\")\n\t\t\t\t\t\treturn value === \"true\" ? 1 : 0;\n\t\t\t\t\treturn value;\n\t\t\t\t});\n\n\t\t\t\ttry {\n\t\t\t\t\tawait connection.execute<ResultSetHeader>(\n\t\t\t\t\t\t`INSERT INTO \\`${tableName}\\` (${colNames}) VALUES (${columns.map(() => \"?\").join(\", \")})`,\n\t\t\t\t\t\tvalues as any,\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new HTTPException(500, {\n\t\t\t\t\t\tmessage: `Failed to insert record ${i + 1}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait connection.commit();\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `Successfully inserted ${records.length} record${records.length !== 1 ? \"s\" : \"\"}`,\n\t\t\t\tsuccessCount: records.length,\n\t\t\t\tfailureCount: 0,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tawait connection.rollback();\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to bulk insert records into \"${tableName}\"`,\n\t\t\t});\n\t\t} finally {\n\t\t\tconnection.release();\n\t\t}\n\t}\n\n\t// --- Query ---\n\n\tasync executeQuery({\n\t\tquery,\n\t\tdb,\n\t}: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\tconst pool = getMysqlPool(db);\n\t\tif (!query?.trim()) throw new HTTPException(400, { message: \"Query is required\" });\n\n\t\tconst cleaned = query.trim().replace(/;+$/, \"\");\n\t\tconst start = performance.now();\n\t\tconst [result, fields] = (await pool.execute(cleaned)) as [\n\t\t\tRowDataPacket[] | ResultSetHeader,\n\t\t\tFieldPacket[],\n\t\t];\n\t\tconst duration = performance.now() - start;\n\n\t\tif (Array.isArray(result)) {\n\t\t\tconst rows = result as RowDataPacket[];\n\t\t\tconst columns = fields ? fields.map((f) => f.name) : Object.keys(rows[0] ?? {});\n\t\t\treturn {\n\t\t\t\tcolumns,\n\t\t\t\trows: rows as Record<string, unknown>[],\n\t\t\t\trowCount: rows.length,\n\t\t\t\tduration,\n\t\t\t\tmessage: rows.length === 0 ? \"OK\" : undefined,\n\t\t\t};\n\t\t}\n\n\t\tconst dmlResult = result as ResultSetHeader;\n\t\treturn {\n\t\t\tcolumns: [],\n\t\t\trows: [],\n\t\t\trowCount: dmlResult.affectedRows,\n\t\t\tduration,\n\t\t\tmessage: `OK — ${dmlResult.affectedRows} row(s) affected`,\n\t\t};\n\t}\n\n\t// =========================================================\n\t// Private helpers\n\t// =========================================================\n\n\tprivate isMariaDb(pool: MysqlPool): Promise<boolean> {\n\t\tthis.mariaDb ??= pool\n\t\t\t.query<RowDataPacket[]>(\"SELECT VERSION() LIKE '%MariaDB%' AS mariadb\")\n\t\t\t.then(([rows]) => Number(rows[0]?.mariadb) === 1)\n\t\t\t.catch((e) => {\n\t\t\t\tthis.mariaDb = undefined;\n\t\t\t\tthrow e;\n\t\t\t});\n\t\treturn this.mariaDb;\n\t}\n\n\tprivate async getPrimaryKeyColumns(pool: MysqlPool, tableName: string): Promise<string[]> {\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COLUMN_NAME as column_name\n\t\t\t FROM information_schema.COLUMNS\n\t\t\t WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_KEY = 'PRI'\n\t\t\t ORDER BY ORDINAL_POSITION`,\n\t\t\t[tableName],\n\t\t);\n\t\treturn (rows as Array<{ column_name: string }>).map((r) => r.column_name);\n\t}\n\n\tprivate async getForeignKeyReferences(\n\t\ttableName: string,\n\t\tdb: string,\n\t): Promise<ForeignKeyConstraint[]> {\n\t\tconst pool = getMysqlPool(db);\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT\n\t\t\t\tkcu.CONSTRAINT_NAME AS constraint_name,\n\t\t\t\tkcu.TABLE_NAME AS referencing_table,\n\t\t\t\tkcu.COLUMN_NAME AS referencing_column,\n\t\t\t\tkcu.REFERENCED_TABLE_NAME AS referenced_table,\n\t\t\t\tkcu.REFERENCED_COLUMN_NAME AS referenced_column\n\t\t\tFROM information_schema.KEY_COLUMN_USAGE kcu\n\t\t\tJOIN information_schema.TABLE_CONSTRAINTS tc\n\t\t\t ON kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME\n\t\t\t AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA\n\t\t\t AND kcu.TABLE_NAME = tc.TABLE_NAME\n\t\t\tWHERE tc.CONSTRAINT_TYPE = 'FOREIGN KEY'\n\t\t\t AND kcu.TABLE_SCHEMA = DATABASE()\n\t\t\t AND kcu.REFERENCED_TABLE_NAME = ?`,\n\t\t\t[tableName],\n\t\t);\n\t\treturn (rows as ForeignKeyConstraintRow[]).map((row) => ({\n\t\t\tconstraintName: row.constraint_name,\n\t\t\treferencingTable: row.referencing_table,\n\t\t\treferencingColumn: row.referencing_column,\n\t\t\treferencedTable: row.referenced_table,\n\t\t\treferencedColumn: row.referenced_column,\n\t\t}));\n\t}\n\n\tprivate async getRelatedRecordsForTable(\n\t\ttableName: string,\n\t\tdb: string,\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getForeignKeyReferences(tableName, db);\n\t\tif (fks.length === 0) return [];\n\n\t\tconst pool = getMysqlPool(db);\n\t\tconst results: RelatedRecord[] = [];\n\t\tfor (const fk of fks) {\n\t\t\tconst [relatedRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t\t`SELECT * FROM \\`${fk.referencingTable}\\` LIMIT 100`,\n\t\t\t);\n\t\t\tif (relatedRows.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: relatedRows as Record<string, unknown>[],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate async getRelatedRecords(\n\t\ttableName: string,\n\t\tprimaryKeys: DeleteRecordSchemaType[\"primaryKeys\"],\n\t\tdb: string,\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getForeignKeyReferences(tableName, db);\n\t\tif (fks.length === 0) return [];\n\n\t\tconst pool = getMysqlPool(db);\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst results: RelatedRecord[] = [];\n\n\t\tconst constraintsByTable = new Map<string, ForeignKeyConstraint[]>();\n\t\tfor (const fk of fks) {\n\t\t\tconst key = `${fk.referencingTable}.${fk.referencingColumn}`;\n\t\t\tif (!constraintsByTable.has(key)) constraintsByTable.set(key, []);\n\t\t\tconstraintsByTable.get(key)?.push(fk);\n\t\t}\n\n\t\tfor (const [, constraints] of constraintsByTable) {\n\t\t\tconst fk = constraints[0];\n\t\t\tif (!fk) continue;\n\t\t\tconst matchingPk = primaryKeys.find((pk) => pk.columnName === fk.referencedColumn);\n\t\t\tif (!matchingPk) continue;\n\n\t\t\tconst placeholders = pkValues.map(() => \"?\").join(\", \");\n\t\t\tconst [relatedRows] = await pool.execute<RowDataPacket[]>(\n\t\t\t\t`SELECT * FROM \\`${fk.referencingTable}\\` WHERE \\`${fk.referencingColumn}\\` IN (${placeholders}) LIMIT 100`,\n\t\t\t\tpkValues as any,\n\t\t\t);\n\t\t\tif (relatedRows.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: relatedRows as Record<string, unknown>[],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate async getTableRowCount(pool: MysqlPool, tableName: string): Promise<number> {\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as count FROM \\`${tableName}\\``,\n\t\t);\n\t\treturn Number((rows as Array<{ count: number }>)[0]?.count ?? 0);\n\t}\n\n\tprivate async getBooleanColumnSet(tableName: string, db: string): Promise<Set<string>> {\n\t\tconst cols = await this.getTableColumns({ tableName, db });\n\t\treturn new Set(cols.filter((c) => c.dataTypeLabel === \"boolean\").map((c) => c.columnName));\n\t}\n\n\tprivate async assertTableExists(pool: MysqlPool, tableName: string): Promise<void> {\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (Number((rows as Array<{ cnt: number }>)[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t}\n\t}\n\n\tprivate async assertColumnExists(\n\t\tpool: MysqlPool,\n\t\ttableName: string,\n\t\tcolumnName: string,\n\t): Promise<void> {\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(\n\t\t\t`SELECT COUNT(*) as cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?`,\n\t\t\t[tableName, columnName],\n\t\t);\n\t\tif (Number((rows as Array<{ cnt: number }>)[0]?.cnt ?? 0) === 0) {\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate parseMysqlEnumValues(columnType: string): string[] | null {\n\t\tconst match = columnType.match(/^(?:enum|set)\\((.+)\\)$/i);\n\t\tif (!match?.[1]) return null;\n\t\treturn match[1].split(\",\").map((v) => v.trim().replace(/^'|'$/g, \"\"));\n\t}\n}\n","import type { FilterType, SortDirection } from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\n\n/**\n * Quote an identifier exactly as stored. Oracle folds unquoted names to uppercase, so every\n * name is quoted. Quoted Oracle identifiers cannot contain `\"` at all (there is no escape),\n * so such a name is rejected instead of escaped.\n */\nexport const quoteOracleIdent = (name: string) => {\n\tif (name.includes('\"') || name.includes(\"\\0\"))\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: `Oracle identifiers cannot contain double quotes: ${name}`,\n\t\t});\n\treturn `\"${name}\"`;\n};\n\n/** Collects positional binds and returns the `:n` placeholder for each value. */\nexport const createBinds = () => {\n\tconst values: unknown[] = [];\n\tconst bind = (value: unknown) => {\n\t\tvalues.push(value);\n\t\treturn `:${values.length}`;\n\t};\n\treturn { values, bind };\n};\n\ntype OracleTemporalType = \"date\" | \"timestamp\" | \"timestampTz\" | \"timestampLtz\";\n\nconst ORACLE_DATE_FORMAT = 'YYYY-MM-DD\"T\"HH24:MI:SS';\nconst ORACLE_TIMESTAMP_FORMAT = `${ORACLE_DATE_FORMAT}.FF9`;\nconst ORACLE_TIMESTAMP_TZ_FORMAT = `${ORACLE_TIMESTAMP_FORMAT}TZH:TZM`;\nconst ISO_DATE =\n\t/^(\\d{4})-(\\d{2})-(\\d{2})(?:[T ](\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{1,9}))?)?)?\\s*(Z|[+-]\\d{2}(?::?\\d{2})?)?$/i;\n\nconst temporalTypeOf = (columnType: string): OracleTemporalType | null => {\n\tconst type = columnType.toUpperCase();\n\tif (type === \"DATE\") return \"date\";\n\tif (!type.startsWith(\"TIMESTAMP\")) return null;\n\tif (type.includes(\"WITH LOCAL TIME ZONE\")) return \"timestampLtz\";\n\tif (type.includes(\"WITH TIME ZONE\")) return \"timestampTz\";\n\treturn \"timestamp\";\n};\n\nconst temporalFormatOf = (columnType: string | undefined) => {\n\tconst temporalType = columnType ? temporalTypeOf(columnType) : null;\n\tif (temporalType === \"date\") return ORACLE_DATE_FORMAT;\n\tif (temporalType === \"timestampTz\") return ORACLE_TIMESTAMP_TZ_FORMAT;\n\tif (temporalType) return ORACLE_TIMESTAMP_FORMAT;\n\treturn null;\n};\n\nconst formatTemporalColumn = (column: string, columnType: string | undefined) => {\n\tconst format = temporalFormatOf(columnType);\n\treturn format ? `TO_CHAR(${column}, '${format}')` : column;\n};\n\nconst normalizeTemporalValue = (value: unknown, temporalType: OracleTemporalType) => {\n\tconst input = value instanceof Date ? value.toISOString() : value;\n\tif (typeof input !== \"string\")\n\t\tthrow new HTTPException(400, { message: `Invalid Oracle ${temporalType} value` });\n\tconst match = input.trim().match(ISO_DATE);\n\tif (!match)\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: `Invalid Oracle date or timestamp value: ${input}`,\n\t\t});\n\tconst [, year, month, day, hour = \"00\", minute = \"00\", second = \"00\", fraction = \"\", zone] =\n\t\tmatch;\n\tconst wallClock = `${year}-${month}-${day}T${hour}:${minute}:${second}`;\n\tif (temporalType === \"date\") return wallClock;\n\tconst timestamp = `${wallClock}.${fraction.padEnd(9, \"0\")}`;\n\tif (temporalType === \"timestamp\") return timestamp;\n\tif (!zone || zone.toUpperCase() === \"Z\") return `${timestamp}+00:00`;\n\tconst compactZone = zone.replace(\":\", \"\");\n\treturn `${timestamp}${compactZone.slice(0, 3)}:${compactZone.slice(3).padEnd(2, \"0\")}`;\n};\n\nexport const bindOracleValue = (\n\tvalue: unknown,\n\tcolumnType: string | undefined,\n\tbind: (boundValue: unknown) => string,\n) => {\n\tconst temporalType = columnType ? temporalTypeOf(columnType) : null;\n\tif (!temporalType) return bind(value);\n\tconst placeholder = bind(\n\t\tvalue === null || value === undefined ? null : normalizeTemporalValue(value, temporalType),\n\t);\n\tif (temporalType === \"date\") return `TO_DATE(${placeholder}, '${ORACLE_DATE_FORMAT}')`;\n\tif (temporalType === \"timestamp\")\n\t\treturn `TO_TIMESTAMP(${placeholder}, '${ORACLE_TIMESTAMP_FORMAT}')`;\n\treturn `TO_TIMESTAMP_TZ(${placeholder}, '${ORACLE_TIMESTAMP_TZ_FORMAT}')`;\n};\n\nexport const buildOracleSelectList = (\n\tcolumns: Array<{ COLUMN_NAME: string; DATA_TYPE: string }>,\n\ttableAlias?: string,\n) =>\n\tcolumns\n\t\t.map(({ COLUMN_NAME: name, DATA_TYPE: dataType }) => {\n\t\t\tconst column = `${tableAlias ? `${tableAlias}.` : \"\"}${quoteOracleIdent(name)}`;\n\t\t\tconst projected = formatTemporalColumn(column, dataType);\n\t\t\treturn projected === column ? column : `${projected} AS ${quoteOracleIdent(name)}`;\n\t\t})\n\t\t.join(\", \");\n\nexport type OracleForeignKeyRow = {\n\tCONSTRAINT_NAME: string;\n\tREFERENCING_TABLE: string;\n\tREFERENCING_COLUMN: string;\n\tREFERENCED_TABLE: string;\n\tREFERENCED_COLUMN: string;\n};\n\nexport type OracleForeignKey = {\n\tconstraintName: string;\n\treferencingTable: string;\n\tcolumns: string[];\n\treferencedTable: string;\n\treferencedColumns: string[];\n};\n\nexport const groupOracleForeignKeys = (rows: OracleForeignKeyRow[]): OracleForeignKey[] => {\n\tconst constraints = new Map<string, OracleForeignKey>();\n\tfor (const row of rows) {\n\t\tconst existing = constraints.get(row.CONSTRAINT_NAME);\n\t\tif (existing) {\n\t\t\texisting.columns.push(row.REFERENCING_COLUMN);\n\t\t\texisting.referencedColumns.push(row.REFERENCED_COLUMN);\n\t\t\tcontinue;\n\t\t}\n\t\tconstraints.set(row.CONSTRAINT_NAME, {\n\t\t\tconstraintName: row.CONSTRAINT_NAME,\n\t\t\treferencingTable: row.REFERENCING_TABLE,\n\t\t\tcolumns: [row.REFERENCING_COLUMN],\n\t\t\treferencedTable: row.REFERENCED_TABLE,\n\t\t\treferencedColumns: [row.REFERENCED_COLUMN],\n\t\t});\n\t}\n\treturn [...constraints.values()];\n};\n\nexport const whereSql = (conditions: string[]) =>\n\tconditions.length ? `WHERE ${conditions.join(\" AND \")}` : \"\";\n\nexport function buildFilterConditions(\n\tfilters: FilterType[],\n\tbind: (value: unknown) => string,\n\tcolumnTypes: ReadonlyMap<string, string>,\n): string[] {\n\tconst conditions: string[] = [];\n\n\tfor (const filter of filters) {\n\t\tconst col = quoteOracleIdent(filter.columnName);\n\t\tconst columnType = columnTypes.get(filter.columnName);\n\t\tconst isNull = filter.value.toLowerCase() === \"null\";\n\t\tswitch (filter.operator) {\n\t\t\tcase \"=\":\n\t\t\tcase \"!=\":\n\t\t\tcase \">\":\n\t\t\tcase \">=\":\n\t\t\tcase \"<\":\n\t\t\tcase \"<=\":\n\t\t\t\tconditions.push(\n\t\t\t\t\t`${col} ${filter.operator} ${bindOracleValue(filter.value, columnType, bind)}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"is\":\n\t\t\t\tconditions.push(\n\t\t\t\t\tisNull\n\t\t\t\t\t\t? `${col} IS NULL`\n\t\t\t\t\t\t: `${col} = ${bindOracleValue(filter.value, columnType, bind)}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"is not\":\n\t\t\t\tconditions.push(\n\t\t\t\t\tisNull\n\t\t\t\t\t\t? `${col} IS NOT NULL`\n\t\t\t\t\t\t: `${col} != ${bindOracleValue(filter.value, columnType, bind)}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"like\":\n\t\t\t\tconditions.push(`${formatTemporalColumn(col, columnType)} LIKE ${bind(filter.value)}`);\n\t\t\t\tbreak;\n\t\t\tcase \"not like\":\n\t\t\t\tconditions.push(\n\t\t\t\t\t`${formatTemporalColumn(col, columnType)} NOT LIKE ${bind(filter.value)}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"ilike\":\n\t\t\t\tconditions.push(\n\t\t\t\t\t`UPPER(${formatTemporalColumn(col, columnType)}) LIKE UPPER(${bind(filter.value)})`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"not ilike\":\n\t\t\t\tconditions.push(\n\t\t\t\t\t`UPPER(${formatTemporalColumn(col, columnType)}) NOT LIKE UPPER(${bind(filter.value)})`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn conditions;\n}\n\n/** One ORDER BY term; `column: null` orders by ROWID, the tie-breaker for tables without a key. */\nexport interface OrderTerm {\n\tcolumn: string | null;\n\tdirection: SortDirection;\n}\n\nexport const buildOrderBy = (terms: OrderTerm[], tableAlias?: string) =>\n\t`ORDER BY ${terms\n\t\t.map(\n\t\t\t(t) =>\n\t\t\t\t`${tableAlias ? `${tableAlias}.` : \"\"}${t.column === null ? \"ROWID\" : quoteOracleIdent(t.column)} ${t.direction.toUpperCase()}`,\n\t\t)\n\t\t.join(\", \")}`;\n\nconst SERIAL_TYPES = new Set([\n\t\"serial\",\n\t\"serial4\",\n\t\"bigserial\",\n\t\"serial8\",\n\t\"smallserial\",\n\t\"serial2\",\n]);\n\nexport const isSerialType = (columnType: string) =>\n\tSERIAL_TYPES.has(columnType.toLowerCase().trim());\n\n/**\n * Translate a PostgreSQL type name from the web form into an Oracle column type.\n * `text` becomes VARCHAR2(4000), not CLOB: a CLOB column cannot be compared with `=`, sorted,\n * indexed, made UNIQUE or later altered from VARCHAR2, which the grid does with every text\n * column. Values over 4000 bytes are rejected (ORA-12899) instead.\n * `native` is true on Oracle 23ai and later, which have SQL BOOLEAN and JSON types.\n */\nexport function mapColumnTypeToOracle(\n\tcolumnType: string,\n\tisArray: boolean,\n\tnative: boolean,\n): string {\n\tif (isArray)\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage:\n\t\t\t\t\"Oracle has no array column type. Use a json column (JSON on Oracle 23ai) instead.\",\n\t\t});\n\n\tconst normalized = columnType.toLowerCase().trim();\n\tconst typeMap: Record<string, string> = {\n\t\tserial: \"NUMBER(10)\",\n\t\tserial4: \"NUMBER(10)\",\n\t\tbigserial: \"NUMBER(19)\",\n\t\tserial8: \"NUMBER(19)\",\n\t\tsmallserial: \"NUMBER(5)\",\n\t\tserial2: \"NUMBER(5)\",\n\t\tint: \"NUMBER(10)\",\n\t\tint4: \"NUMBER(10)\",\n\t\tinteger: \"NUMBER(10)\",\n\t\tbigint: \"NUMBER(19)\",\n\t\tint8: \"NUMBER(19)\",\n\t\tsmallint: \"NUMBER(5)\",\n\t\tint2: \"NUMBER(5)\",\n\t\ttinyint: \"NUMBER(3)\",\n\t\tnumeric: \"NUMBER\",\n\t\tdecimal: \"NUMBER\",\n\t\treal: \"BINARY_FLOAT\",\n\t\tfloat4: \"BINARY_FLOAT\",\n\t\tfloat: \"BINARY_DOUBLE\",\n\t\t\"double precision\": \"BINARY_DOUBLE\",\n\t\tfloat8: \"BINARY_DOUBLE\",\n\t\tmoney: \"NUMBER(19,4)\",\n\t\tboolean: native ? \"BOOLEAN\" : \"NUMBER(1)\",\n\t\tbool: native ? \"BOOLEAN\" : \"NUMBER(1)\",\n\t\ttext: \"VARCHAR2(4000)\",\n\t\tvarchar: \"VARCHAR2(255)\",\n\t\t\"character varying\": \"VARCHAR2(255)\",\n\t\tchar: \"CHAR(1)\",\n\t\tcharacter: \"CHAR(1)\",\n\t\tbpchar: \"CHAR(1)\",\n\t\tuuid: \"VARCHAR2(36)\",\n\t\tjson: native ? \"JSON\" : \"CLOB\",\n\t\tjsonb: native ? \"JSON\" : \"CLOB\",\n\t\txml: \"CLOB\",\n\t\tdate: \"DATE\",\n\t\ttime: \"VARCHAR2(18)\",\n\t\t\"time without time zone\": \"VARCHAR2(18)\",\n\t\ttimestamp: \"TIMESTAMP\",\n\t\t\"timestamp without time zone\": \"TIMESTAMP\",\n\t\t\"timestamp with time zone\": \"TIMESTAMP WITH TIME ZONE\",\n\t\ttimestamptz: \"TIMESTAMP WITH TIME ZONE\",\n\t\tinterval: \"INTERVAL DAY TO SECOND\",\n\t\tbytea: \"BLOB\",\n\t\tinet: \"VARCHAR2(45)\",\n\t\tcidr: \"VARCHAR2(45)\",\n\t\tmacaddr: \"VARCHAR2(17)\",\n\t\tmacaddr8: \"VARCHAR2(23)\",\n\t\tpoint: \"VARCHAR2(4000)\",\n\t\tline: \"VARCHAR2(4000)\",\n\t\tpolygon: \"VARCHAR2(4000)\",\n\t};\n\treturn typeMap[normalized] ?? columnType.toUpperCase();\n}\n\n/** Translate the common PostgreSQL default expressions the web form offers. */\nexport function formatOracleDefault(defaultValue: string, native: boolean): string {\n\tconst trimmed = defaultValue.trim();\n\tconst lower = trimmed.toLowerCase();\n\tif (lower === \"now()\" || lower === \"current_timestamp\") return \"CURRENT_TIMESTAMP\";\n\tif (lower === \"current_date\") return \"CURRENT_DATE\";\n\tif (lower === \"true\" || lower === \"false\") {\n\t\tif (native) return lower.toUpperCase();\n\t\treturn lower === \"true\" ? \"1\" : \"0\";\n\t}\n\treturn trimmed;\n}\n\nexport const IDENTITY_CLAUSE = \"GENERATED BY DEFAULT ON NULL AS IDENTITY\";\n","/** Keep NUMBER text exact unless it is an integer within JavaScript's safe range. */\nexport const toJsonNumber = (value: unknown) => {\n\tif (typeof value !== \"string\" || !/^[+-]?\\d+$/.test(value)) return value;\n\tconst number = Number(value);\n\treturn Number.isSafeInteger(number) ? number : value;\n};\n","import type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tRelatedRecord,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tTableDataResultSchemaType,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { mapOracleToDataType, standardizeOracleDataTypeLabel } from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport oracledb, { type Connection, type Metadata } from \"oracledb\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getOraclePool } from \"@/adapters/connections.js\";\nimport { parseDatabaseUrl } from \"@/utils/parse-database-url.js\";\nimport {\n\tbindOracleValue,\n\tbuildFilterConditions,\n\tbuildOracleSelectList,\n\tbuildOrderBy,\n\tcreateBinds,\n\tformatOracleDefault,\n\tgroupOracleForeignKeys,\n\tIDENTITY_CLAUSE,\n\tquoteOracleIdent as ident,\n\tisSerialType,\n\tmapColumnTypeToOracle,\n\ttype OracleForeignKey,\n\ttype OracleForeignKeyRow,\n\ttype OrderTerm,\n\twhereSql,\n} from \"./oracle.query-builder.js\";\nimport { toJsonNumber } from \"./oracle.values.js\";\n\ntype Row = Record<string, unknown>;\n\ntype ColumnRow = {\n\tCOLUMN_NAME: string;\n\tDATA_TYPE: string;\n\tDATA_LENGTH: number;\n\tDATA_PRECISION: number | null;\n\tDATA_SCALE: number | null;\n\tCHAR_LENGTH: number;\n\tNULLABLE: \"Y\" | \"N\";\n\tDATA_DEFAULT: string | null;\n\tDEFAULT_ON_NULL: \"YES\" | \"NO\";\n\tGENERATION_TYPE: \"ALWAYS\" | \"BY DEFAULT\" | null;\n};\n\n/** Oracle 23ai is the first release with SQL BOOLEAN and the native JSON type. */\nconst supportsNativeTypes = (conn: Connection) => conn.oracleServerVersion >= 2300000000;\n\nconst toHex = (value: unknown) => (Buffer.isBuffer(value) ? value.toString(\"hex\") : value);\n\n/** Thin mode converts native timestamps to millisecond-only Date, so adapter reads use TO_CHAR. */\nconst fetchTypeHandler = (meta: Metadata<unknown>) => {\n\tswitch (meta.dbType) {\n\t\tcase oracledb.DB_TYPE_NUMBER:\n\t\t\treturn { type: oracledb.STRING, converter: toJsonNumber };\n\t\tcase oracledb.DB_TYPE_CLOB:\n\t\tcase oracledb.DB_TYPE_NCLOB:\n\t\t\treturn { type: oracledb.STRING };\n\t\tcase oracledb.DB_TYPE_BLOB:\n\t\t\treturn { type: oracledb.BUFFER, converter: toHex };\n\t\tcase oracledb.DB_TYPE_RAW:\n\t\tcase oracledb.DB_TYPE_LONG_RAW:\n\t\t\treturn { converter: toHex };\n\t}\n\treturn undefined;\n};\n\nconst toOracleValue = (value: unknown, columnType?: string): unknown => {\n\tif (value === null || value === undefined) return null;\n\tif (typeof value === \"boolean\") return columnType === \"BOOLEAN\" ? value : Number(value);\n\tif (typeof value === \"bigint\") return value.toString();\n\tif (value instanceof Date || typeof value !== \"object\") return value;\n\treturn JSON.stringify(value);\n};\n\n/** `DEFAULT NULL` is how Oracle clears a default, and it stays visible as the text \"NULL\". */\nconst defaultOf = (c: ColumnRow) => {\n\tconst value = c.DATA_DEFAULT?.trim();\n\treturn value && value.toUpperCase() !== \"NULL\" ? value : null;\n};\n\nconst formatColumnType = (c: ColumnRow) => {\n\tswitch (c.DATA_TYPE) {\n\t\tcase \"NUMBER\":\n\t\t\tif (c.DATA_PRECISION === null) return c.DATA_SCALE === 0 ? \"INTEGER\" : \"NUMBER\";\n\t\t\treturn c.DATA_SCALE\n\t\t\t\t? `NUMBER(${c.DATA_PRECISION},${c.DATA_SCALE})`\n\t\t\t\t: `NUMBER(${c.DATA_PRECISION})`;\n\t\tcase \"FLOAT\":\n\t\t\treturn `FLOAT(${c.DATA_PRECISION})`;\n\t\tcase \"VARCHAR2\":\n\t\tcase \"NVARCHAR2\":\n\t\tcase \"CHAR\":\n\t\tcase \"NCHAR\":\n\t\t\treturn `${c.DATA_TYPE}(${c.CHAR_LENGTH})`;\n\t\tcase \"RAW\":\n\t\t\treturn `RAW(${c.DATA_LENGTH})`;\n\t\tdefault:\n\t\t\treturn c.DATA_TYPE;\n\t}\n};\n\ntype RowSelection = { columns: string[]; keys: unknown[][] };\n\nconst columnRef = (column: string, alias?: string) =>\n\t`${alias ? `${alias}.` : \"\"}${column === \"ROWID\" ? \"ROWID\" : ident(column)}`;\n\nconst joinOn = (fk: OracleForeignKey) =>\n\tfk.columns\n\t\t.map((column, index) => `c.${ident(column)} = p.${ident(fk.referencedColumns[index])}`)\n\t\t.join(\" AND \");\n\nconst matchesAny = (\n\tselection: RowSelection,\n\talias: string | undefined,\n\tbind: (value: unknown, column: string) => string,\n) =>\n\t`(${selection.keys\n\t\t.map(\n\t\t\t(key) =>\n\t\t\t\t`(${selection.columns\n\t\t\t\t\t.map((column, index) => `${columnRef(column, alias)} = ${bind(key[index], column)}`)\n\t\t\t\t\t.join(\" AND \")})`,\n\t\t)\n\t\t.join(\" OR \")})`;\n\nconst isTemporalMetadata = <T>(meta: Metadata<T>) =>\n\tmeta.dbType === oracledb.DB_TYPE_DATE ||\n\tmeta.dbType === oracledb.DB_TYPE_TIMESTAMP ||\n\tmeta.dbType === oracledb.DB_TYPE_TIMESTAMP_TZ ||\n\tmeta.dbType === oracledb.DB_TYPE_TIMESTAMP_LTZ;\n\n/** Oracle errors that are the user's to fix; each maps to a 400 with a readable reason. */\nconst LIMITATIONS: Array<[code: string, reason: string]> = [\n\t[\"ORA-01758\", \"A NOT NULL column added to a table with rows needs a default value.\"],\n\t[\n\t\t\"ORA-01439\",\n\t\t\"Oracle can only change a column to an unrelated type while the column is empty.\",\n\t],\n\t[\"ORA-22858\", \"Oracle cannot convert this column to or from a LOB (CLOB/BLOB) type.\"],\n\t[\"ORA-00932\", \"Oracle cannot compare, sort or filter CLOB, BLOB or JSON values this way.\"],\n\t[\"ORA-22848\", \"Oracle cannot sort or compare CLOB, BLOB or JSON values.\"],\n\t[\"ORA-12899\", \"The value is too long for the column.\"],\n\t[\"ORA-01441\", \"The column holds values longer than the new type allows.\"],\n\t[\"ORA-30675\", \"Oracle identity columns must have a numeric type.\"],\n\t[\"ORA-01861\", \"Dates must be written as YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS.\"],\n\t[\"ORA-01830\", \"Dates must be written as YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS.\"],\n\t[\"ORA-01843\", \"Dates must be written as YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS.\"],\n];\n\n/** ON UPDATE actions do not exist in Oracle, and ON DELETE has no SET DEFAULT. */\nconst FK_DELETE_ACTIONS: Record<string, string> = {\n\tCASCADE: \" ON DELETE CASCADE\",\n\t\"SET NULL\": \" ON DELETE SET NULL\",\n\tRESTRICT: \"\",\n\t\"NO ACTION\": \"\",\n};\n\nexport class OracleAdapter extends BaseAdapter {\n\t// =========================================================\n\t// Abstract method implementations\n\t// =========================================================\n\n\tprotected async runQuery<T>(_db: string, sql: string, values: unknown[]): Promise<T> {\n\t\treturn this.withConnection((conn) => this.query(conn, sql, values)) as Promise<T>;\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn ident(name);\n\t}\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\treturn mapOracleToDataType(nativeType);\n\t}\n\n\tmapFromUniversalType(universalType: string): string {\n\t\tconst map: Record<string, string> = {\n\t\t\ttext: \"VARCHAR2(4000)\",\n\t\t\tnumber: \"NUMBER\",\n\t\t\tboolean: \"BOOLEAN\",\n\t\t\tjson: \"JSON\",\n\t\t\tdate: \"TIMESTAMP\",\n\t\t\tarray: \"JSON\",\n\t\t\tenum: \"VARCHAR2(255)\",\n\t\t};\n\t\treturn map[universalType] ?? \"VARCHAR2(4000)\";\n\t}\n\n\t// getTableData is overridden: the ORDER BY needs the table's primary key, which the\n\t// synchronous template hooks cannot look up.\n\tprotected buildTableDataQuery(_params: GetTableDataParams): QueryBundle {\n\t\tthrow new Error(\"OracleAdapter.getTableData builds its own query\");\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn (rawRows as Row[]).map((row) => this.normalizeRow(row));\n\t}\n\n\tprotected buildCursors(): { nextCursor: string | null; prevCursor: string | null } {\n\t\tthrow new Error(\"OracleAdapter.getTableData builds its own cursors\");\n\t}\n\n\tprotected override wrapError(e: unknown): HTTPException {\n\t\tif (e instanceof Error && !(e instanceof HTTPException)) {\n\t\t\tconst limitation = LIMITATIONS.find(([code]) => e.message.startsWith(code));\n\t\t\tif (limitation)\n\t\t\t\treturn new HTTPException(400, {\n\t\t\t\t\tmessage: `${limitation[1]} (${e.message.split(\"\\n\")[0]})`,\n\t\t\t\t\tcause: e,\n\t\t\t\t});\n\t\t\tif (e.message.startsWith(\"ORA-00955\"))\n\t\t\t\treturn new HTTPException(409, { message: e.message.split(\"\\n\")[0], cause: e });\n\t\t}\n\t\treturn super.wrapError(e);\n\t}\n\n\tprivate async withConnection<T>(fn: (conn: Connection) => Promise<T>): Promise<T> {\n\t\ttry {\n\t\t\tconst conn = await (await getOraclePool()).getConnection();\n\t\t\ttry {\n\t\t\t\treturn await fn(conn);\n\t\t\t} finally {\n\t\t\t\tawait conn.close();\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t/** Run DML on one connection as a single transaction. */\n\tprivate inTransaction<T>(fn: (conn: Connection) => Promise<T>): Promise<T> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\ttry {\n\t\t\t\tconst result = await fn(conn);\n\t\t\t\tawait conn.commit();\n\t\t\t\treturn result;\n\t\t\t} catch (e) {\n\t\t\t\tawait conn.rollback().catch(() => {});\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate async query<T = Row>(conn: Connection, sql: string, values: unknown[] = []) {\n\t\tconst result = await conn.execute<T>(sql, values, {\n\t\t\toutFormat: oracledb.OUT_FORMAT_OBJECT,\n\t\t\tfetchTypeHandler,\n\t\t});\n\t\treturn result.rows ?? [];\n\t}\n\n\tprivate async execute(conn: Connection, sql: string, values: unknown[] = []) {\n\t\treturn (await conn.execute(sql, values)).rowsAffected ?? 0;\n\t}\n\n\t// =========================================================\n\t// Records — paginated read\n\t// =========================================================\n\n\toverride async getTableData(params: GetTableDataParams): Promise<TableDataResultSchemaType> {\n\t\tconst { tableName, limit = 50, sort = [], order = \"asc\", cursor, filters = [] } = params;\n\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst columns = await this.requireColumns(conn, tableName);\n\t\t\tconst columnTypes = new Map(\n\t\t\t\tcolumns.map((column) => [column.COLUMN_NAME, column.DATA_TYPE]),\n\t\t\t);\n\t\t\tconst primaryKey = await this.primaryKey(conn, tableName);\n\n\t\t\tconst terms: OrderTerm[] = this.orderTerms<string | null>(\n\t\t\t\tsort,\n\t\t\t\torder,\n\t\t\t\tprimaryKey.length ? primaryKey : [null],\n\t\t\t);\n\n\t\t\tconst offset = cursor ? Number(this.decodeCursor(cursor)?.values._offset ?? 0) : 0;\n\t\t\tconst { values, bind } = createBinds();\n\t\t\tconst where = whereSql(buildFilterConditions(filters, bind, columnTypes));\n\t\t\tconst filterValues = [...values];\n\n\t\t\tconst [countRow] = await this.query<{ total: number }>(\n\t\t\t\tconn,\n\t\t\t\t`SELECT COUNT(*) AS \"total\" FROM ${ident(tableName)} ${where}`,\n\t\t\t\tfilterValues,\n\t\t\t);\n\t\t\tconst tableAlias = \"t\";\n\t\t\tconst fetched = await this.query(\n\t\t\t\tconn,\n\t\t\t\t`SELECT ${buildOracleSelectList(columns, tableAlias)} FROM ${ident(tableName)} ${tableAlias} ${where} ${buildOrderBy(terms, tableAlias)} OFFSET ${bind(offset)} ROWS FETCH NEXT ${bind(limit + 1)} ROWS ONLY`,\n\t\t\t\tvalues,\n\t\t\t);\n\n\t\t\tconst hasMore = fetched.length > limit;\n\t\t\tconst offsetCursor = (at: number) =>\n\t\t\t\tthis.encodeCursor({ values: { _offset: at }, sortColumns: [\"_offset\"] });\n\n\t\t\treturn {\n\t\t\t\tdata: fetched.slice(0, limit).map((row) => this.normalizeRow(row)),\n\t\t\t\tmeta: {\n\t\t\t\t\tlimit,\n\t\t\t\t\ttotal: Number(countRow?.total ?? 0),\n\t\t\t\t\thasNextPage: hasMore,\n\t\t\t\t\thasPreviousPage: offset > 0,\n\t\t\t\t\tnextCursor: hasMore ? offsetCursor(offset + limit) : null,\n\t\t\t\t\tprevCursor: offset > 0 ? offsetCursor(Math.max(0, offset - limit)) : null,\n\t\t\t\t},\n\t\t\t};\n\t\t});\n\t}\n\n\toverride async exportTableData({\n\t\ttableName,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<{ cols: string[]; rows: Row[] }> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst columns = await this.requireColumns(conn, tableName);\n\t\t\tconst rows = await this.query(\n\t\t\t\tconn,\n\t\t\t\t`SELECT ${buildOracleSelectList(columns)} FROM ${ident(tableName)}`,\n\t\t\t);\n\t\t\tif (!rows.length)\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Table \"${tableName}\" does not exist or has no data`,\n\t\t\t\t});\n\t\t\treturn { cols: columns.map((column) => column.COLUMN_NAME), rows };\n\t\t});\n\t}\n\n\t// =========================================================\n\t// Databases\n\t// =========================================================\n\n\t/**\n\t * An Oracle service is one database, so the list holds only the connected container\n\t * (CON_NAME). Tables are the connected user's own schema.\n\t */\n\tasync getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst [row] = await this.query<{\n\t\t\t\tNAME: string;\n\t\t\t\tOWNER: string;\n\t\t\t\tBYTES: number;\n\t\t\t\tENCODING: string;\n\t\t\t}>(\n\t\t\t\tconn,\n\t\t\t\t`SELECT SYS_CONTEXT('USERENV', 'CON_NAME') AS name, USER AS owner,\n\t\t\t\t\t(SELECT NVL(SUM(bytes), 0) FROM user_segments) AS bytes,\n\t\t\t\t\t(SELECT value FROM nls_database_parameters WHERE parameter = 'NLS_CHARACTERSET') AS encoding\n\t\t\t\tFROM dual`,\n\t\t\t);\n\t\t\tif (!row) return [];\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tname: row.NAME,\n\t\t\t\t\tsize: this.formatBytes(Number(row.BYTES)),\n\t\t\t\t\towner: row.OWNER,\n\t\t\t\t\tencoding: row.ENCODING,\n\t\t\t\t},\n\t\t\t];\n\t\t});\n\t}\n\n\tasync getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\treturn this.withConnection(async (conn) => ({ db: await this.containerName(conn) }));\n\t}\n\n\tasync getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\tconst pool = await getOraclePool().catch((e) => {\n\t\t\tthrow this.wrapError(e);\n\t\t});\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst [row] = await this.query<{ U: string }>(conn, \"SELECT USER AS u FROM dual\");\n\t\t\tconst { host, port } = parseDatabaseUrl();\n\t\t\treturn {\n\t\t\t\thost,\n\t\t\t\tport,\n\t\t\t\tuser: row?.U ?? \"\",\n\t\t\t\tdatabase: await this.containerName(conn),\n\t\t\t\tversion: `Oracle ${conn.oracleServerVersionString}`,\n\t\t\t\tactive_connections: pool.connectionsInUse,\n\t\t\t\tmax_connections: pool.poolMax,\n\t\t\t};\n\t\t});\n\t}\n\n\t// =========================================================\n\t// Tables\n\t// =========================================================\n\n\t/**\n\t * Row counts are exact (COUNT(*)) for tables whose optimizer statistics are missing or\n\t * under 100,000 rows; larger tables report USER_TABLES.NUM_ROWS, which is an estimate as\n\t * of the last statistics gathering.\n\t */\n\tasync getTablesList(_db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst tables = await this.query<{ TABLE_NAME: string; NUM_ROWS: number | null }>(\n\t\t\t\tconn,\n\t\t\t\t`SELECT table_name, num_rows FROM user_tables\n\t\t\t\tWHERE dropped = 'NO' AND nested = 'NO' AND secondary = 'N' AND (iot_type IS NULL OR iot_type = 'IOT')\n\t\t\t\tORDER BY table_name`,\n\t\t\t);\n\t\t\tconst toCount = tables.filter((t) => t.NUM_ROWS === null || t.NUM_ROWS < 100_000);\n\t\t\tconst counts = new Map<string, number>();\n\t\t\tif (toCount.length) {\n\t\t\t\tconst rows = await this.query<{ N: number; C: number }>(\n\t\t\t\t\tconn,\n\t\t\t\t\ttoCount\n\t\t\t\t\t\t.map((t, i) => `SELECT ${i} AS n, COUNT(*) AS c FROM ${ident(t.TABLE_NAME)}`)\n\t\t\t\t\t\t.join(\" UNION ALL \"),\n\t\t\t\t);\n\t\t\t\tfor (const row of rows) counts.set(toCount[row.N].TABLE_NAME, Number(row.C));\n\t\t\t}\n\t\t\treturn tables.map((t) => ({\n\t\t\t\ttableName: t.TABLE_NAME,\n\t\t\t\trowCount: counts.get(t.TABLE_NAME) ?? Number(t.NUM_ROWS ?? 0),\n\t\t\t}));\n\t\t});\n\t}\n\n\t/** One CREATE TABLE statement: identity, keys and foreign keys succeed or fail together. */\n\tasync createTable({ tableData }: { tableData: CreateTableSchemaType }): Promise<void> {\n\t\tconst { tableName, fields, foreignKeys = [] } = tableData;\n\n\t\tfor (const fk of foreignKeys) {\n\t\t\tif (fk.onUpdate !== \"NO ACTION\" && fk.onUpdate !== \"RESTRICT\")\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Oracle foreign keys have no ON UPDATE actions (${fk.onUpdate} on \"${fk.columnName}\"). Use NO ACTION.`,\n\t\t\t\t});\n\t\t\tif (!(fk.onDelete in FK_DELETE_ACTIONS))\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Oracle foreign keys do not support ON DELETE ${fk.onDelete} (on \"${fk.columnName}\"). Use CASCADE, SET NULL or NO ACTION.`,\n\t\t\t\t});\n\t\t}\n\n\t\tawait this.withConnection(async (conn) => {\n\t\t\tconst native = supportsNativeTypes(conn);\n\t\t\tconst primaryKey = fields.filter((f) => f.isPrimaryKey).map((f) => f.columnName);\n\t\t\tconst definitions = fields.map((field) =>\n\t\t\t\tthis.columnDefinition(field, { withConstraints: false, native }),\n\t\t\t);\n\t\t\tif (primaryKey.length)\n\t\t\t\tdefinitions.push(`PRIMARY KEY (${primaryKey.map(ident).join(\", \")})`);\n\t\t\tfor (const field of fields) {\n\t\t\t\tif (field.isUnique && !field.isPrimaryKey)\n\t\t\t\t\tdefinitions.push(`UNIQUE (${ident(field.columnName)})`);\n\t\t\t}\n\t\t\tfor (const fk of foreignKeys) {\n\t\t\t\tdefinitions.push(\n\t\t\t\t\t`FOREIGN KEY (${ident(fk.columnName)}) REFERENCES ${ident(fk.referencedTable)} (${ident(fk.referencedColumn)})${FK_DELETE_ACTIONS[fk.onDelete]}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait conn.execute(`CREATE TABLE ${ident(tableName)} (${definitions.join(\", \")})`);\n\t\t});\n\t}\n\n\tasync deleteTable({ tableName, cascade }: DeleteTableParams): Promise<DeleteTableResult> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tawait this.requireColumns(conn, tableName);\n\t\t\tconst referencing = (await this.foreignKeys(conn, \"referenced\", tableName)).filter(\n\t\t\t\t(fk) => fk.referencingTable !== tableName,\n\t\t\t);\n\t\t\tif (referencing.length && !cascade)\n\t\t\t\treturn {\n\t\t\t\t\tdeletedCount: 0,\n\t\t\t\t\tfkViolation: true,\n\t\t\t\t\trelatedRecords: await this.sampleReferencingRows(conn, referencing),\n\t\t\t\t};\n\n\t\t\tconst [row] = await this.query<{ C: number }>(\n\t\t\t\tconn,\n\t\t\t\t`SELECT COUNT(*) AS c FROM ${ident(tableName)}`,\n\t\t\t);\n\t\t\t// CASCADE CONSTRAINTS drops the foreign keys of referencing tables, not their rows.\n\t\t\tawait conn.execute(\n\t\t\t\t`DROP TABLE ${ident(tableName)}${cascade ? \" CASCADE CONSTRAINTS\" : \"\"}`,\n\t\t\t);\n\t\t\treturn { deletedCount: Number(row?.C ?? 0), fkViolation: false, relatedRecords: [] };\n\t\t});\n\t}\n\n\tasync renameTable({ tableName, newTableName }: RenameTableParamsSchemaType): Promise<void> {\n\t\tthis.assertDifferentTableName(tableName, newTableName);\n\t\tawait this.withConnection(async (conn) => {\n\t\t\tawait this.requireColumns(conn, tableName);\n\t\t\tif ((await this.columns(conn, newTableName)).length)\n\t\t\t\tthrow new HTTPException(409, { message: `Table \"${newTableName}\" already exists` });\n\t\t\tawait conn.execute(`ALTER TABLE ${ident(tableName)} RENAME TO ${ident(newTableName)}`);\n\t\t});\n\t}\n\n\tasync getTableSchema({ tableName }: { tableName: string }): Promise<string> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tawait this.requireColumns(conn, tableName);\n\t\t\tawait conn.execute(\n\t\t\t\t`BEGIN\n\t\t\t\t\tDBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE);\n\t\t\t\t\tDBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SQLTERMINATOR', TRUE);\n\t\t\t\tEND;`,\n\t\t\t);\n\t\t\tconst [row] = await this.query<{ DDL: string }>(\n\t\t\t\tconn,\n\t\t\t\t\"SELECT DBMS_METADATA.GET_DDL('TABLE', :1) AS ddl FROM dual\",\n\t\t\t\t[tableName],\n\t\t\t);\n\t\t\treturn row?.DDL.trim() ?? \"\";\n\t\t});\n\t}\n\n\t// =========================================================\n\t// Columns\n\t// =========================================================\n\n\tasync getTableColumns({\n\t\ttableName,\n\t}: {\n\t\ttableName: string;\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst columns = await this.requireColumns(conn, tableName);\n\t\t\tconst primaryKey = new Set(await this.primaryKey(conn, tableName));\n\t\t\tconst references = new Map(\n\t\t\t\t(await this.foreignKeys(conn, \"referencing\", tableName)).flatMap((fk) =>\n\t\t\t\t\tfk.columns.map(\n\t\t\t\t\t\t(column, index) =>\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\tcolumn,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\treferencedTable: fk.referencedTable,\n\t\t\t\t\t\t\t\t\treferencedColumn: fk.referencedColumns[index],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t] as const,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\n\t\t\treturn columns.map((col) => {\n\t\t\t\tconst fk = references.get(col.COLUMN_NAME);\n\t\t\t\tconst type = formatColumnType(col);\n\t\t\t\treturn {\n\t\t\t\t\tcolumnName: col.COLUMN_NAME,\n\t\t\t\t\tdataType: mapOracleToDataType(type),\n\t\t\t\t\tdataTypeLabel: standardizeOracleDataTypeLabel(type),\n\t\t\t\t\tisNullable: col.NULLABLE === \"Y\",\n\t\t\t\t\t// An identity's DATA_DEFAULT names its system sequence (ISEQ$$_n); show the clause instead.\n\t\t\t\t\tcolumnDefault: col.GENERATION_TYPE\n\t\t\t\t\t\t? `GENERATED ${col.GENERATION_TYPE}${col.DEFAULT_ON_NULL === \"YES\" ? \" ON NULL\" : \"\"} AS IDENTITY`\n\t\t\t\t\t\t: defaultOf(col),\n\t\t\t\t\tisPrimaryKey: primaryKey.has(col.COLUMN_NAME),\n\t\t\t\t\tisForeignKey: !!fk,\n\t\t\t\t\treferencedTable: fk?.referencedTable ?? null,\n\t\t\t\t\treferencedColumn: fk?.referencedColumn ?? null,\n\t\t\t\t\tenumValues: null,\n\t\t\t\t};\n\t\t\t});\n\t\t});\n\t}\n\n\t/** One ALTER TABLE ... ADD, constraints inline, so it applies fully or not at all. */\n\tasync addColumn(params: AddColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName } = params;\n\t\tawait this.withConnection(async (conn) => {\n\t\t\tconst columns = await this.requireColumns(conn, tableName);\n\t\t\tif (columns.some((c) => c.COLUMN_NAME === columnName))\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Column \"${columnName}\" already exists in table \"${tableName}\"`,\n\t\t\t\t});\n\t\t\tconst definition = this.columnDefinition(params, {\n\t\t\t\twithConstraints: true,\n\t\t\t\tnative: supportsNativeTypes(conn),\n\t\t\t});\n\t\t\tawait conn.execute(`ALTER TABLE ${ident(tableName)} ADD (${definition})`);\n\t\t});\n\t}\n\n\tasync deleteColumn({\n\t\ttableName,\n\t\tcolumnName,\n\t}: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\tawait this.withConnection(async (conn) => {\n\t\t\tawait this.requireColumn(conn, tableName, columnName);\n\t\t\tawait conn.execute(`ALTER TABLE ${ident(tableName)} DROP COLUMN ${ident(columnName)}`);\n\t\t});\n\t\treturn { deletedCount: 1 };\n\t}\n\n\t/**\n\t * One ALTER TABLE ... MODIFY. Oracle rejects restating the current nullability\n\t * (ORA-01451/ORA-01442), so NULL/NOT NULL is only written when it changes, and it has no\n\t * DROP DEFAULT: `DEFAULT NULL` clears an existing default.\n\t */\n\tasync alterColumn(params: AlterColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, columnType, isNullable, defaultValue } = params;\n\t\tawait this.withConnection(async (conn) => {\n\t\t\tconst native = supportsNativeTypes(conn);\n\t\t\tconst column = (await this.requireColumn(conn, tableName, columnName)).find(\n\t\t\t\t(c) => c.COLUMN_NAME === columnName,\n\t\t\t);\n\t\t\tlet definition = `${ident(columnName)} ${mapColumnTypeToOracle(columnType, false, native)}`;\n\t\t\tif (defaultValue?.trim())\n\t\t\t\tdefinition += ` DEFAULT ${formatOracleDefault(defaultValue, native)}`;\n\t\t\telse if (column && !column.GENERATION_TYPE && defaultOf(column))\n\t\t\t\tdefinition += \" DEFAULT NULL\";\n\t\t\tif ((column?.NULLABLE === \"Y\") !== isNullable)\n\t\t\t\tdefinition += isNullable ? \" NULL\" : \" NOT NULL\";\n\t\t\tawait conn.execute(`ALTER TABLE ${ident(tableName)} MODIFY (${definition})`);\n\t\t});\n\t}\n\n\tasync renameColumn({\n\t\ttableName,\n\t\tcolumnName,\n\t\tnewColumnName,\n\t}: RenameColumnParamsSchemaType): Promise<void> {\n\t\tawait this.withConnection(async (conn) => {\n\t\t\tconst columns = await this.requireColumn(conn, tableName, columnName);\n\t\t\tif (columns.some((c) => c.COLUMN_NAME === newColumnName))\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Column \"${newColumnName}\" already exists in table \"${tableName}\"`,\n\t\t\t\t});\n\t\t\tawait conn.execute(\n\t\t\t\t`ALTER TABLE ${ident(tableName)} RENAME COLUMN ${ident(columnName)} TO ${ident(newColumnName)}`,\n\t\t\t);\n\t\t});\n\t}\n\n\t// =========================================================\n\t// Records\n\t// =========================================================\n\n\tasync addRecord({\n\t\tparams,\n\t}: {\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\tconst { tableName, data } = params;\n\t\tconst columns = Object.keys(data);\n\t\tif (!columns.length)\n\t\t\tthrow new HTTPException(400, { message: \"No data provided for insert\" });\n\n\t\tconst insertedCount = await this.inTransaction(async (conn) => {\n\t\t\tconst types = await this.columnTypes(conn, tableName);\n\t\t\tconst { values, bind } = createBinds();\n\t\t\tconst expressions = columns.map((column) =>\n\t\t\t\tbindOracleValue(\n\t\t\t\t\ttoOracleValue(data[column], types.get(column)),\n\t\t\t\t\ttypes.get(column),\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn this.execute(\n\t\t\t\tconn,\n\t\t\t\t`INSERT INTO ${ident(tableName)} (${columns.map(ident).join(\", \")}) VALUES (${expressions.join(\", \")})`,\n\t\t\t\tvalues,\n\t\t\t);\n\t\t});\n\t\treturn { insertedCount };\n\t}\n\n\tasync updateRecords({\n\t\tparams,\n\t}: {\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\tconst { tableName } = params;\n\t\tconst keyColumns = this.resolveKeyColumns(params);\n\t\tconst groups = this.groupUpdatesByKey(params, keyColumns);\n\n\t\tconst updatedCount = await this.inTransaction(async (conn) => {\n\t\t\tthis.assertWholeKey(await this.primaryKey(conn, tableName), keyColumns);\n\t\t\tconst types = await this.columnTypes(conn, tableName);\n\t\t\tlet total = 0;\n\t\t\tfor (const { keyValues, rowUpdates } of groups) {\n\t\t\t\tconst { values, bind } = createBinds();\n\t\t\t\tconst set = rowUpdates\n\t\t\t\t\t.map(\n\t\t\t\t\t\t(u) =>\n\t\t\t\t\t\t\t`${ident(u.columnName)} = ${bindOracleValue(\n\t\t\t\t\t\t\t\ttoOracleValue(u.value, types.get(u.columnName)),\n\t\t\t\t\t\t\t\ttypes.get(u.columnName),\n\t\t\t\t\t\t\t\tbind,\n\t\t\t\t\t\t\t)}`,\n\t\t\t\t\t)\n\t\t\t\t\t.join(\", \");\n\t\t\t\tconst where = keyColumns\n\t\t\t\t\t.map(\n\t\t\t\t\t\t(c, i) =>\n\t\t\t\t\t\t\t`${ident(c)} = ${bindOracleValue(\n\t\t\t\t\t\t\t\ttoOracleValue(keyValues[i], types.get(c)),\n\t\t\t\t\t\t\t\ttypes.get(c),\n\t\t\t\t\t\t\t\tbind,\n\t\t\t\t\t\t\t)}`,\n\t\t\t\t\t)\n\t\t\t\t\t.join(\" AND \");\n\t\t\t\tconst changed = await this.execute(\n\t\t\t\t\tconn,\n\t\t\t\t\t`UPDATE ${ident(tableName)} SET ${set} WHERE ${where}`,\n\t\t\t\t\tvalues,\n\t\t\t\t);\n\t\t\t\tif (changed === 0)\n\t\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\t\tmessage: `Record with ${this.describeKey(keyColumns, keyValues)} not found in table \"${tableName}\"`,\n\t\t\t\t\t});\n\t\t\t\ttotal += changed;\n\t\t\t}\n\t\t\treturn total;\n\t\t});\n\t\treturn { updatedCount };\n\t}\n\n\tasync deleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t}: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\t\tconst selection: RowSelection = {\n\t\t\tcolumns: [pkColumn],\n\t\t\tkeys: primaryKeys.map((key) => [key.value]),\n\t\t};\n\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tthis.assertDeletableKey(await this.primaryKey(conn, tableName));\n\t\t\tconst types = await this.columnTypes(conn, tableName);\n\t\t\ttry {\n\t\t\t\tconst { values, bind } = createBinds();\n\t\t\t\tconst where = matchesAny(selection, undefined, (value, column) =>\n\t\t\t\t\tbindOracleValue(toOracleValue(value, types.get(column)), types.get(column), bind),\n\t\t\t\t);\n\t\t\t\tconst deletedCount = await this.execute(\n\t\t\t\t\tconn,\n\t\t\t\t\t`DELETE FROM ${ident(tableName)} WHERE ${where}`,\n\t\t\t\t\tvalues,\n\t\t\t\t);\n\t\t\t\tawait conn.commit();\n\t\t\t\treturn { deletedCount, fkViolation: false, relatedRecords: [] };\n\t\t\t} catch (e) {\n\t\t\t\tawait conn.rollback().catch(() => {});\n\t\t\t\tif (!(e instanceof Error) || !e.message.startsWith(\"ORA-02292\")) throw e;\n\t\t\t\tconst relatedRecords: RelatedRecord[] = [];\n\t\t\t\tfor (const fk of await this.foreignKeys(conn, \"referenced\", tableName)) {\n\t\t\t\t\tconst childColumns = await this.requireColumns(conn, fk.referencingTable);\n\t\t\t\t\tconst { values, bind } = createBinds();\n\t\t\t\t\tconst where = matchesAny(selection, \"p\", (value, column) =>\n\t\t\t\t\t\tbindOracleValue(toOracleValue(value, types.get(column)), types.get(column), bind),\n\t\t\t\t\t);\n\t\t\t\t\tconst records = await this.query(\n\t\t\t\t\t\tconn,\n\t\t\t\t\t\t`SELECT ${buildOracleSelectList(childColumns, \"c\")} FROM ${ident(fk.referencingTable)} c JOIN ${ident(tableName)} p ON ${joinOn(fk)} WHERE ${where} FETCH FIRST 100 ROWS ONLY`,\n\t\t\t\t\t\tvalues,\n\t\t\t\t\t);\n\t\t\t\t\tif (records.length)\n\t\t\t\t\t\trelatedRecords.push({\n\t\t\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\t\t\tcolumnName: fk.columns.join(\", \"),\n\t\t\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\t\t\trecords,\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t});\n\t}\n\n\t/** Deletes referencing rows children-first, then the rows themselves, in one transaction. */\n\tasync forceDeleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t}: DeleteRecordParams): Promise<{ deletedCount: number }> {\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\n\t\tconst purge = async (\n\t\t\tconn: Connection,\n\t\t\ttable: string,\n\t\t\tselection: RowSelection,\n\t\t\tpath: string[],\n\t\t): Promise<number> => {\n\t\t\tif (!selection.keys.length) return 0;\n\t\t\tif (path.includes(table))\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Cannot force delete: the foreign keys ${[...path, table].map((t) => `\"${t}\"`).join(\" -> \")} form a cycle.`,\n\t\t\t\t});\n\t\t\tconst types = await this.columnTypes(conn, table);\n\t\t\tlet deleted = 0;\n\t\t\tfor (const fk of await this.foreignKeys(conn, \"referenced\", table)) {\n\t\t\t\tconst { values, bind } = createBinds();\n\t\t\t\tconst where = matchesAny(selection, \"p\", (value, column) =>\n\t\t\t\t\tcolumn === \"ROWID\"\n\t\t\t\t\t\t? `CHARTOROWID(${bind(value)})`\n\t\t\t\t\t\t: bindOracleValue(\n\t\t\t\t\t\t\t\ttoOracleValue(value, types.get(column)),\n\t\t\t\t\t\t\t\ttypes.get(column),\n\t\t\t\t\t\t\t\tbind,\n\t\t\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tconst referenced = await this.query<{ __rowid: string }>(\n\t\t\t\t\tconn,\n\t\t\t\t\t`SELECT DISTINCT ROWIDTOCHAR(c.ROWID) AS \"__rowid\" FROM ${ident(fk.referencingTable)} c JOIN ${ident(table)} p ON ${joinOn(fk)} WHERE ${where}`,\n\t\t\t\t\tvalues,\n\t\t\t\t);\n\t\t\t\tdeleted += await purge(\n\t\t\t\t\tconn,\n\t\t\t\t\tfk.referencingTable,\n\t\t\t\t\t{ columns: [\"ROWID\"], keys: referenced.map((row) => [row.__rowid]) },\n\t\t\t\t\t[...path, table],\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { values, bind } = createBinds();\n\t\t\tconst where = matchesAny(selection, undefined, (value, column) =>\n\t\t\t\tcolumn === \"ROWID\"\n\t\t\t\t\t? `CHARTOROWID(${bind(value)})`\n\t\t\t\t\t: bindOracleValue(toOracleValue(value, types.get(column)), types.get(column), bind),\n\t\t\t);\n\t\t\treturn (\n\t\t\t\tdeleted +\n\t\t\t\t(await this.execute(conn, `DELETE FROM ${ident(table)} WHERE ${where}`, values))\n\t\t\t);\n\t\t};\n\n\t\tconst deletedCount = await this.inTransaction(async (conn) => {\n\t\t\tthis.assertDeletableKey(await this.primaryKey(conn, tableName));\n\t\t\treturn purge(\n\t\t\t\tconn,\n\t\t\t\ttableName,\n\t\t\t\t{ columns: [pkColumn], keys: primaryKeys.map((key) => [key.value]) },\n\t\t\t\t[],\n\t\t\t);\n\t\t});\n\t\treturn { deletedCount };\n\t}\n\n\tasync bulkInsertRecords({\n\t\ttableName,\n\t\trecords,\n\t}: BulkInsertRecordsParams): Promise<BulkInsertResult> {\n\t\tif (!records?.length)\n\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\n\t\tconst columns = Object.keys(records[0]);\n\t\tconst successCount = await this.inTransaction(async (conn) => {\n\t\t\tconst types = await this.columnTypes(conn, tableName);\n\t\t\tlet expressions: string[] = [];\n\t\t\tconst rows = records.map((record, index) => {\n\t\t\t\tconst { values, bind } = createBinds();\n\t\t\t\tconst rowExpressions = columns.map((column) =>\n\t\t\t\t\tbindOracleValue(\n\t\t\t\t\t\ttoOracleValue(record[column], types.get(column)),\n\t\t\t\t\t\ttypes.get(column),\n\t\t\t\t\t\tbind,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tif (index === 0) expressions = rowExpressions;\n\t\t\t\treturn values;\n\t\t\t});\n\t\t\tconst result = await conn.executeMany(\n\t\t\t\t`INSERT INTO ${ident(tableName)} (${columns.map(ident).join(\", \")}) VALUES (${expressions.join(\", \")})`,\n\t\t\t\trows,\n\t\t\t);\n\t\t\treturn result.rowsAffected ?? records.length;\n\t\t});\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tmessage: `Bulk insert completed: ${successCount} records inserted`,\n\t\t\tsuccessCount,\n\t\t\tfailureCount: 0,\n\t\t};\n\t}\n\n\t// =========================================================\n\t// Query\n\t// =========================================================\n\n\t/**\n\t * Runs one statement with autocommit. A trailing `;` is stripped from SQL (Oracle rejects\n\t * it) but kept on PL/SQL blocks, where it ends the last statement; a SQL*Plus `/` line is\n\t * dropped. Native DATE and TIMESTAMP result columns are refused because Thin mode converts\n\t * them to millisecond-only Date objects; callers can select them with an explicit TO_CHAR.\n\t */\n\tasync executeQuery({ query: sql }: { query: string }): Promise<ExecuteQueryResult> {\n\t\tif (!sql?.trim()) throw new HTTPException(400, { message: \"Query is required\" });\n\n\t\tconst trimmed = sql\n\t\t\t.trim()\n\t\t\t.replace(/\\n\\s*\\/$/, \"\")\n\t\t\t.trim();\n\t\tconst isPlsql =\n\t\t\t/^(BEGIN|DECLARE|CREATE\\s+(OR\\s+REPLACE\\s+)?((NON)?EDITIONABLE\\s+)?(PROCEDURE|FUNCTION|PACKAGE|TRIGGER|TYPE))\\b/i.test(\n\t\t\t\ttrimmed,\n\t\t\t);\n\t\tconst statement = isPlsql ? trimmed : trimmed.replace(/;\\s*$/, \"\");\n\n\t\treturn this.withConnection(async (conn) => {\n\t\t\tconst start = performance.now();\n\t\t\tconst result = await conn.execute<Row>(statement, [], {\n\t\t\t\toutFormat: oracledb.OUT_FORMAT_OBJECT,\n\t\t\t\tfetchTypeHandler,\n\t\t\t\tautoCommit: true,\n\t\t\t\tresultSet: true,\n\t\t\t});\n\t\t\tconst duration = performance.now() - start;\n\n\t\t\tif (result.resultSet) {\n\t\t\t\tif (result.metaData?.some(isTemporalMetadata)) {\n\t\t\t\t\tawait result.resultSet.close();\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\"Oracle query results with native DATE or TIMESTAMP columns must use TO_CHAR with an explicit format so fractional seconds are not lost.\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tlet rows: Row[];\n\t\t\t\ttry {\n\t\t\t\t\trows = await result.resultSet.getRows();\n\t\t\t\t} finally {\n\t\t\t\t\tawait result.resultSet.close();\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tcolumns: result.metaData?.map((meta) => meta.name) ?? [],\n\t\t\t\t\trows,\n\t\t\t\t\trowCount: rows.length,\n\t\t\t\t\tduration,\n\t\t\t\t\tmessage: rows.length === 0 ? \"OK\" : undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst affected = result.rowsAffected ?? 0;\n\t\t\treturn {\n\t\t\t\tcolumns: [],\n\t\t\t\trows: [],\n\t\t\t\trowCount: affected,\n\t\t\t\tduration,\n\t\t\t\tmessage: result.rowsAffected === undefined ? \"OK\" : `OK (${affected} rows affected)`,\n\t\t\t};\n\t\t});\n\t}\n\n\t// =========================================================\n\t// Private helpers\n\t// =========================================================\n\n\tprivate columnDefinition(\n\t\tfield: {\n\t\t\tcolumnName: string;\n\t\t\tcolumnType: string;\n\t\t\tdefaultValue?: string | null;\n\t\t\tisPrimaryKey?: boolean;\n\t\t\tisNullable?: boolean;\n\t\t\tisUnique?: boolean;\n\t\t\tisIdentity?: boolean;\n\t\t\tisArray?: boolean;\n\t\t},\n\t\t{ withConstraints, native }: { withConstraints: boolean; native: boolean },\n\t): string {\n\t\tlet def = `${ident(field.columnName)} ${mapColumnTypeToOracle(field.columnType, field.isArray ?? false, native)}`;\n\t\tif (field.isIdentity || isSerialType(field.columnType)) def += ` ${IDENTITY_CLAUSE}`;\n\t\telse if (field.defaultValue?.trim())\n\t\t\tdef += ` DEFAULT ${formatOracleDefault(field.defaultValue, native)}`;\n\t\tif (!field.isNullable && !field.isPrimaryKey) def += \" NOT NULL\";\n\t\tif (withConstraints) {\n\t\t\tif (field.isPrimaryKey) def += \" PRIMARY KEY\";\n\t\t\telse if (field.isUnique) def += \" UNIQUE\";\n\t\t}\n\t\treturn def;\n\t}\n\n\tprivate formatBytes(bytes: number): string {\n\t\tif (bytes < 1024) return `${bytes} B`;\n\t\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n\t}\n\n\tprivate async containerName(conn: Connection): Promise<string> {\n\t\tconst [row] = await this.query<{ DB: string }>(\n\t\t\tconn,\n\t\t\t\"SELECT SYS_CONTEXT('USERENV', 'CON_NAME') AS db FROM dual\",\n\t\t);\n\t\treturn row?.DB ?? \"\";\n\t}\n\n\tprivate columns(conn: Connection, tableName: string): Promise<ColumnRow[]> {\n\t\treturn this.query<ColumnRow>(\n\t\t\tconn,\n\t\t\t`SELECT c.column_name, c.data_type, c.data_length, c.data_precision, c.data_scale, c.char_length,\n\t\t\t\tc.nullable, c.data_default, c.default_on_null, i.generation_type\n\t\t\tFROM user_tab_columns c\n\t\t\tLEFT JOIN user_tab_identity_cols i ON i.table_name = c.table_name AND i.column_name = c.column_name\n\t\t\tWHERE c.table_name = :1 ORDER BY c.column_id`,\n\t\t\t[tableName],\n\t\t);\n\t}\n\n\tprivate async columnTypes(conn: Connection, tableName: string) {\n\t\tconst columns = await this.requireColumns(conn, tableName);\n\t\treturn new Map(columns.map((c) => [c.COLUMN_NAME, c.DATA_TYPE]));\n\t}\n\n\tprivate async requireColumns(conn: Connection, tableName: string): Promise<ColumnRow[]> {\n\t\tconst columns = await this.columns(conn, tableName);\n\t\tif (!columns.length)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\treturn columns;\n\t}\n\n\tprivate async requireColumn(\n\t\tconn: Connection,\n\t\ttableName: string,\n\t\tcolumnName: string,\n\t): Promise<ColumnRow[]> {\n\t\tconst columns = await this.requireColumns(conn, tableName);\n\t\tif (!columns.some((c) => c.COLUMN_NAME === columnName))\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\t\treturn columns;\n\t}\n\n\tprivate async primaryKey(conn: Connection, tableName: string): Promise<string[]> {\n\t\tconst rows = await this.query<{ COLUMN_NAME: string }>(\n\t\t\tconn,\n\t\t\t`SELECT cc.column_name FROM user_constraints c\n\t\t\tJOIN user_cons_columns cc ON cc.constraint_name = c.constraint_name\n\t\t\tWHERE c.constraint_type = 'P' AND c.table_name = :1\n\t\t\tORDER BY cc.position`,\n\t\t\t[tableName],\n\t\t);\n\t\treturn rows.map((r) => r.COLUMN_NAME);\n\t}\n\n\t/** Foreign keys declared on `tableName` (\"referencing\") or pointing at it (\"referenced\"). */\n\tprivate async foreignKeys(\n\t\tconn: Connection,\n\t\tside: \"referencing\" | \"referenced\",\n\t\ttableName: string,\n\t): Promise<OracleForeignKey[]> {\n\t\tconst rows = await this.query<OracleForeignKeyRow>(\n\t\t\tconn,\n\t\t\t`SELECT c.constraint_name, c.table_name AS referencing_table, cc.column_name AS referencing_column,\n\t\t\t\tr.table_name AS referenced_table, rc.column_name AS referenced_column\n\t\t\tFROM user_constraints c\n\t\t\tJOIN user_cons_columns cc ON cc.constraint_name = c.constraint_name\n\t\t\tJOIN user_constraints r ON r.constraint_name = c.r_constraint_name AND r.owner = c.r_owner\n\t\t\tJOIN user_cons_columns rc ON rc.constraint_name = r.constraint_name AND rc.position = cc.position\n\t\t\tWHERE c.constraint_type = 'R' AND ${side === \"referencing\" ? \"c\" : \"r\"}.table_name = :1\n\t\t\tORDER BY c.constraint_name, cc.position`,\n\t\t\t[tableName],\n\t\t);\n\t\treturn groupOracleForeignKeys(rows);\n\t}\n\n\tprivate async sampleReferencingRows(\n\t\tconn: Connection,\n\t\treferences: OracleForeignKey[],\n\t): Promise<RelatedRecord[]> {\n\t\tconst related: RelatedRecord[] = [];\n\t\tfor (const fk of references) {\n\t\t\tconst columns = await this.requireColumns(conn, fk.referencingTable);\n\t\t\tconst records = await this.query(\n\t\t\t\tconn,\n\t\t\t\t`SELECT ${buildOracleSelectList(columns)} FROM ${ident(fk.referencingTable)} WHERE ${fk.columns.map((column) => `${ident(column)} IS NOT NULL`).join(\" AND \")} FETCH FIRST 100 ROWS ONLY`,\n\t\t\t);\n\t\t\tif (records.length)\n\t\t\t\trelated.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.columns.join(\", \"),\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords,\n\t\t\t\t});\n\t\t}\n\t\treturn related;\n\t}\n}\n","import type { CursorData, FilterType, SortDirection, SortType } from \"@db-studio/shared/types\";\n\nexport function buildWhereClause(filters: FilterType[]): {\n\tclause: string;\n\tvalues: unknown[];\n} {\n\tif (filters.length === 0) {\n\t\treturn { clause: \"\", values: [] };\n\t}\n\n\tconst conditions: string[] = [];\n\tconst values: unknown[] = [];\n\n\tfor (const filter of filters) {\n\t\tconst paramIndex = values.length + 1;\n\t\tconst columnName = `\"${filter.columnName}\"`;\n\n\t\tswitch (filter.operator) {\n\t\t\tcase \"=\":\n\t\t\tcase \"!=\":\n\t\t\tcase \">\":\n\t\t\tcase \">=\":\n\t\t\tcase \"<\":\n\t\t\tcase \"<=\":\n\t\t\t\tconditions.push(`${columnName} ${filter.operator} $${paramIndex}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"is\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${columnName} IS NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${columnName} = $${paramIndex}`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"is not\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${columnName} IS NOT NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${columnName} != $${paramIndex}`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"like\":\n\t\t\t\tconditions.push(`${columnName}::text LIKE $${paramIndex}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"not like\":\n\t\t\t\tconditions.push(`${columnName}::text NOT LIKE $${paramIndex}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"ilike\":\n\t\t\t\tconditions.push(`${columnName}::text ILIKE $${paramIndex}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"not ilike\":\n\t\t\t\tconditions.push(`${columnName}::text NOT ILIKE $${paramIndex}`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (conditions.length === 0) {\n\t\treturn { clause: \"\", values: [] };\n\t}\n\n\treturn { clause: `WHERE ${conditions.join(\" AND \")}`, values };\n}\n\nexport function buildSortClause(sorts: SortType[] | string, order: SortDirection): string {\n\tif (Array.isArray(sorts)) {\n\t\tif (sorts.length === 0) return \"\";\n\t\tconst parts = sorts.map((s) => `\"${s.columnName}\" ${s.direction.toUpperCase()}`);\n\t\treturn `ORDER BY ${parts.join(\", \")}`;\n\t}\n\tif (sorts && typeof sorts === \"string\") {\n\t\treturn `ORDER BY \"${sorts}\" ${order?.toUpperCase() || \"ASC\"}`;\n\t}\n\treturn \"\";\n}\n\nexport function buildCursorWhereClause(\n\tcursorData: CursorData,\n\tdirection: SortDirection,\n\tsortDirection: SortDirection,\n\tstartParamIndex: number,\n): { clause: string; values: unknown[] } {\n\tconst { values, sortColumns } = cursorData;\n\tconst conditions: string[] = [];\n\tconst queryValues: unknown[] = [];\n\n\tconst isAscending = sortDirection === \"asc\";\n\tconst isForward = direction === \"asc\";\n\tconst useGreaterThan = isAscending === isForward;\n\n\tif (sortColumns.length > 0) {\n\t\tconst columnList = sortColumns.map((col) => `\"${col}\"`).join(\", \");\n\t\tconst placeholders = sortColumns.map((_, i) => `$${startParamIndex + i}`).join(\", \");\n\t\tconst operator = useGreaterThan ? \">\" : \"<\";\n\t\tconditions.push(`(${columnList}) ${operator} (${placeholders})`);\n\t\tfor (const col of sortColumns) {\n\t\t\tqueryValues.push(values[col]);\n\t\t}\n\t}\n\n\treturn {\n\t\tclause: conditions.length > 0 ? `(${conditions.join(\" AND \")})` : \"\",\n\t\tvalues: queryValues,\n\t};\n}\n\n/**\n * Postgres resolves a bare table name through search_path, but catalog queries\n * filter on a literal schema and would otherwise disagree with the data queries\n * — the reason a table outside \"public\" used to list yet 404 on its columns.\n * Both helpers below mirror Postgres' own resolution.\n */\n\n/** Every schema on the current search_path. Use for EXISTS-style checks. */\nexport const SEARCH_PATH_SCHEMAS = \"ANY(current_schemas(false))\";\n\n/**\n * The single schema a bare table name resolves to, honouring search_path order\n * so a name present in several schemas picks the same one Postgres would.\n */\nexport const resolvedSchemaFor = (tableParam: string): string =>\n\t`(SELECT sp.schema_name FROM unnest(current_schemas(false)) WITH ORDINALITY AS sp(schema_name, position)\n\t JOIN information_schema.tables it\n\t ON it.table_schema = sp.schema_name AND it.table_name = ${tableParam}\n\t ORDER BY sp.position LIMIT 1)`;\n","import type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tCursorData,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteRecordSchemaType,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tFieldDataType,\n\tForeignKeyConstraint,\n\tForeignKeyConstraintRow,\n\tForeignKeyDataType,\n\tRelatedRecord,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tSortDirection,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { mapPostgresToDataType, standardizeDataTypeLabel } from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getDbPool } from \"@/adapters/connections.js\";\nimport { parseDatabaseUrl } from \"@/utils/parse-database-url.js\";\nimport {\n\tbuildCursorWhereClause,\n\tbuildSortClause,\n\tbuildWhereClause,\n\tresolvedSchemaFor,\n} from \"./pg.query-builder.js\";\n\ntype PgPool = ReturnType<typeof getDbPool>;\n\nexport class PgAdapter extends BaseAdapter {\n\tprivate databaseSizeSupport?: Promise<boolean>;\n\n\t// =========================================================\n\t// Abstract method implementations\n\t// =========================================================\n\n\tprotected async runQuery<T>(db: string, sql: string, values: unknown[]): Promise<T> {\n\t\tconst pool = getDbPool(db);\n\t\tconst result = await pool.query(sql, values);\n\t\treturn result.rows as T;\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn `\"${name}\"`;\n\t}\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\treturn mapPostgresToDataType(nativeType);\n\t}\n\n\tmapFromUniversalType(universalType: string): string {\n\t\tconst map: Record<string, string> = {\n\t\t\ttext: \"TEXT\",\n\t\t\tnumber: \"INTEGER\",\n\t\t\tboolean: \"BOOLEAN\",\n\t\t\tjson: \"JSONB\",\n\t\t\tdate: \"TIMESTAMP WITH TIME ZONE\",\n\t\t\tarray: \"TEXT[]\",\n\t\t\tenum: \"TEXT\",\n\t\t};\n\t\treturn map[universalType] ?? \"TEXT\";\n\t}\n\n\tprotected buildTableDataQuery(params: GetTableDataParams): QueryBundle {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tcursor = \"\",\n\t\t\tlimit = 50,\n\t\t\tdirection = \"asc\",\n\t\t\tsort = [],\n\t\t\torder = \"asc\",\n\t\t\tfilters = [],\n\t\t\tdb,\n\t\t} = params;\n\n\t\tconst pool = getDbPool(db);\n\t\tvoid pool; // just to keep reference — actual pool used in runQuery\n\n\t\tlet sortColumns: string[] = [];\n\t\tlet effectiveSortDirection: SortDirection = order;\n\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t\teffectiveSortDirection = sort[0].direction;\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\n\t\t// We can't synchronously get primary key columns here (it's async).\n\t\t// The adapter overrides getTableData() to handle that step instead.\n\t\t// For cursor columns we use whatever sort columns are provided, or ctid as fallback.\n\t\tconst cursorColumns = sortColumns.length > 0 ? [...sortColumns] : [\"ctid\"];\n\n\t\tconst { clause: filterWhere, values: filterValues } = buildWhereClause(filters);\n\n\t\tlet cursorWhere = \"\";\n\t\tlet cursorValues: unknown[] = [];\n\n\t\tif (cursor) {\n\t\t\tconst cursorData = this.decodeCursor(cursor);\n\t\t\tif (cursorData) {\n\t\t\t\tconst res = buildCursorWhereClause(\n\t\t\t\t\tcursorData,\n\t\t\t\t\tdirection,\n\t\t\t\t\teffectiveSortDirection,\n\t\t\t\t\tfilterValues.length + 1,\n\t\t\t\t);\n\t\t\t\tcursorWhere = res.clause;\n\t\t\t\tcursorValues = res.values;\n\t\t\t}\n\t\t}\n\n\t\tlet combinedWhere = \"\";\n\t\tif (filterWhere && cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${filterWhere.replace(/^WHERE\\s+/i, \"\")} AND ${cursorWhere}`;\n\t\t} else if (filterWhere) {\n\t\t\tcombinedWhere = filterWhere;\n\t\t} else if (cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${cursorWhere}`;\n\t\t}\n\n\t\tconst sortClause = buildSortClause(Array.isArray(sort) ? sort : sort, order);\n\t\tlet effectiveSortClause = sortClause;\n\n\t\tif (direction === \"desc\") {\n\t\t\tif (sortClause) {\n\t\t\t\teffectiveSortClause = sortClause\n\t\t\t\t\t.replace(/\\bASC\\b/gi, \"TEMP_DESC\")\n\t\t\t\t\t.replace(/\\bDESC\\b/gi, \"ASC\")\n\t\t\t\t\t.replace(/TEMP_DESC/g, \"DESC\");\n\t\t\t} else {\n\t\t\t\tconst parts = cursorColumns.map(\n\t\t\t\t\t(col) => `\"${col}\" ${effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\"}`,\n\t\t\t\t);\n\t\t\t\teffectiveSortClause = `ORDER BY ${parts.join(\", \")}`;\n\t\t\t}\n\t\t} else if (!sortClause && cursorColumns.length > 0) {\n\t\t\tconst parts = cursorColumns.map(\n\t\t\t\t(col) => `\"${col}\" ${effectiveSortDirection.toUpperCase()}`,\n\t\t\t);\n\t\t\teffectiveSortClause = `ORDER BY ${parts.join(\", \")}`;\n\t\t}\n\n\t\tconst limitParamIndex = filterValues.length + cursorValues.length + 1;\n\t\tconst sql = `SELECT * FROM \"${tableName}\" ${combinedWhere} ${effectiveSortClause} LIMIT $${limitParamIndex}`;\n\t\tconst values = [...filterValues, ...cursorValues, limit + 1];\n\n\t\tconst countSql = `SELECT COUNT(*) as total FROM \"${tableName}\" ${filterWhere}`;\n\t\tconst countValues = filterValues;\n\n\t\treturn { sql, values, countSql, countValues };\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn (rawRows as Record<string, unknown>[]).map((row) => this.normalizeRow(row));\n\t}\n\n\tprotected buildCursors(\n\t\tparams: GetTableDataParams,\n\t\trows: NormalizedRow[],\n\t\thasMore: boolean,\n\t): { nextCursor: string | null; prevCursor: string | null } {\n\t\tif (rows.length === 0) return { nextCursor: null, prevCursor: null };\n\n\t\tconst { direction = \"asc\", sort = [], cursor } = params;\n\t\tlet sortColumns: string[] = [];\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\t\tif (sortColumns.length === 0) sortColumns = [\"ctid\"];\n\n\t\tconst createCursor = (row: NormalizedRow): string => {\n\t\t\tconst data: CursorData = {\n\t\t\t\tvalues: Object.fromEntries(sortColumns.map((col) => [col, row[col]])),\n\t\t\t\tsortColumns,\n\t\t\t};\n\t\t\treturn this.encodeCursor(data);\n\t\t};\n\n\t\tconst firstRow = rows[0];\n\t\tconst lastRow = rows[rows.length - 1];\n\n\t\tlet nextCursor: string | null = null;\n\t\tlet prevCursor: string | null = null;\n\n\t\tif (direction === \"asc\") {\n\t\t\tif (hasMore) nextCursor = createCursor(lastRow);\n\t\t\tif (cursor) prevCursor = createCursor(firstRow);\n\t\t} else {\n\t\t\tif (cursor) nextCursor = createCursor(lastRow);\n\t\t\tif (hasMore) prevCursor = createCursor(firstRow);\n\t\t}\n\n\t\treturn { nextCursor, prevCursor };\n\t}\n\n\t// =========================================================\n\t// Override getTableData to incorporate primary-key cursor columns\n\t// =========================================================\n\n\toverride async getTableData(params: GetTableDataParams) {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tdb,\n\t\t\tlimit = 50,\n\t\t\tdirection = \"asc\",\n\t\t\tsort = [],\n\t\t\torder = \"asc\",\n\t\t\tcursor,\n\t\t\tfilters = [],\n\t\t} = params;\n\t\tconst pool = getDbPool(db);\n\n\t\t// Primary key columns for stable cursor pagination\n\t\tconst pkColumns = await this.getPrimaryKeyColumns(pool, tableName);\n\n\t\tlet sortColumns: string[] = [];\n\t\tlet effectiveSortDirection: SortDirection = order;\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t\teffectiveSortDirection = sort[0].direction;\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\n\t\tconst keyColumns = pkColumns.length ? pkColumns : [\"ctid\"];\n\t\tconst cursorColumns = [\n\t\t\t...sortColumns,\n\t\t\t...keyColumns.filter((key) => !sortColumns.includes(key)),\n\t\t];\n\n\t\tconst { clause: filterWhere, values: filterValues } = buildWhereClause(filters);\n\n\t\tlet cursorWhere = \"\";\n\t\tlet cursorValues: unknown[] = [];\n\t\tif (cursor) {\n\t\t\tconst cursorData = this.decodeCursor(cursor);\n\t\t\tif (cursorData) {\n\t\t\t\tconst res = buildCursorWhereClause(\n\t\t\t\t\tcursorData,\n\t\t\t\t\tdirection,\n\t\t\t\t\teffectiveSortDirection,\n\t\t\t\t\tfilterValues.length + 1,\n\t\t\t\t);\n\t\t\t\tcursorWhere = res.clause;\n\t\t\t\tcursorValues = res.values;\n\t\t\t}\n\t\t}\n\n\t\tlet combinedWhere = \"\";\n\t\tif (filterWhere && cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${filterWhere.replace(/^WHERE\\s+/i, \"\")} AND ${cursorWhere}`;\n\t\t} else if (filterWhere) {\n\t\t\tcombinedWhere = filterWhere;\n\t\t} else if (cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${cursorWhere}`;\n\t\t}\n\n\t\tconst sortClause = buildSortClause(Array.isArray(sort) ? sort : sort, order);\n\t\tlet effectiveSortClause = sortClause;\n\n\t\tif (direction === \"desc\") {\n\t\t\tif (sortClause) {\n\t\t\t\teffectiveSortClause = sortClause\n\t\t\t\t\t.replace(/\\bASC\\b/gi, \"TEMP_DESC\")\n\t\t\t\t\t.replace(/\\bDESC\\b/gi, \"ASC\")\n\t\t\t\t\t.replace(/TEMP_DESC/g, \"DESC\");\n\t\t\t} else {\n\t\t\t\tconst parts = cursorColumns.map(\n\t\t\t\t\t(col) => `\"${col}\" ${effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\"}`,\n\t\t\t\t);\n\t\t\t\teffectiveSortClause = `ORDER BY ${parts.join(\", \")}`;\n\t\t\t}\n\t\t} else if (!sortClause && cursorColumns.length > 0) {\n\t\t\tconst parts = cursorColumns.map(\n\t\t\t\t(col) => `\"${col}\" ${effectiveSortDirection.toUpperCase()}`,\n\t\t\t);\n\t\t\teffectiveSortClause = `ORDER BY ${parts.join(\", \")}`;\n\t\t}\n\n\t\tif (sortClause) {\n\t\t\tconst tieBreakers = keyColumns.filter((key) => !sortColumns.includes(key));\n\t\t\tconst tieDirection =\n\t\t\t\t(effectiveSortDirection === \"desc\") !== (direction === \"desc\") ? \"DESC\" : \"ASC\";\n\t\t\tif (tieBreakers.length) {\n\t\t\t\teffectiveSortClause += `, ${tieBreakers.map((key) => `${this.quoteIdentifier(key)} ${tieDirection}`).join(\", \")}`;\n\t\t\t}\n\t\t}\n\n\t\tconst countRes = await pool.query(\n\t\t\t`SELECT COUNT(*) as total FROM \"${tableName}\" ${filterWhere}`,\n\t\t\tfilterValues,\n\t\t);\n\t\tconst total = Number(countRes.rows[0].total);\n\n\t\t// SELECT * omits ctid and CockroachDB's hidden rowid primary key. Primary key columns are\n\t\t// selected explicitly; ctid is a reserved system column name, so selecting it by name\n\t\t// cannot shadow a user column.\n\t\tconst usesCtid = cursorColumns.includes(\"ctid\");\n\t\tconst extraSelect = [...pkColumns.map((col) => `\"${col}\"`), ...(usesCtid ? [\"ctid\"] : [])];\n\n\t\tconst limitParamIndex = filterValues.length + cursorValues.length + 1;\n\t\tconst dataRes = await pool.query(\n\t\t\t`SELECT ${[\"*\", ...extraSelect].join(\", \")} FROM \"${tableName}\" ${combinedWhere} ${effectiveSortClause} LIMIT $${limitParamIndex}`,\n\t\t\t[...filterValues, ...cursorValues, limit + 1],\n\t\t);\n\n\t\tlet rawRows: Record<string, unknown>[] = dataRes.rows;\n\t\tconst hasMore = rawRows.length > limit;\n\t\tif (hasMore) rawRows = rawRows.slice(0, limit);\n\t\tif (direction === \"desc\") rawRows = rawRows.reverse();\n\n\t\tconst rows = rawRows\n\t\t\t.map((row) => {\n\t\t\t\tif (!usesCtid) return row;\n\t\t\t\tconst { ctid: _ctid, ...rest } = row;\n\t\t\t\treturn rest;\n\t\t\t})\n\t\t\t.filter((row) => Object.keys(row).length > 0);\n\n\t\tconst createCursor = (row: Record<string, unknown>): CursorData => ({\n\t\t\tvalues: Object.fromEntries(cursorColumns.map((col) => [col, row[col]])),\n\t\t\tsortColumns: cursorColumns,\n\t\t});\n\n\t\tlet nextCursor: string | null = null;\n\t\tlet prevCursor: string | null = null;\n\n\t\tif (rawRows.length > 0) {\n\t\t\tconst firstRow = rawRows[0];\n\t\t\tconst lastRow = rawRows[rawRows.length - 1];\n\t\t\tif (direction === \"asc\") {\n\t\t\t\tif (hasMore) nextCursor = this.encodeCursor(createCursor(lastRow));\n\t\t\t\tif (cursor) prevCursor = this.encodeCursor(createCursor(firstRow));\n\t\t\t} else {\n\t\t\t\tif (cursor) nextCursor = this.encodeCursor(createCursor(lastRow));\n\t\t\t\tif (hasMore) prevCursor = this.encodeCursor(createCursor(firstRow));\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tdata: rows,\n\t\t\tmeta: {\n\t\t\t\tlimit,\n\t\t\t\ttotal,\n\t\t\t\thasNextPage: direction === \"asc\" ? hasMore : !!cursor,\n\t\t\t\thasPreviousPage: direction === \"asc\" ? !!cursor : hasMore,\n\t\t\t\tnextCursor,\n\t\t\t\tprevCursor,\n\t\t\t},\n\t\t};\n\t}\n\n\t// =========================================================\n\t// IDbAdapter implementations\n\t// =========================================================\n\n\t// --- Databases ---\n\n\tasync getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst pool = getDbPool();\n\t\t\tconst size = (await this.supportsDatabaseSize(pool))\n\t\t\t\t? \"pg_size_pretty(pg_database_size(d.datname))\"\n\t\t\t\t: \"'unknown'\";\n\t\t\tconst { rows } = await pool.query(`\n\t\t\t\tSELECT\n\t\t\t\t\td.datname as name,\n\t\t\t\t\t${size} as size,\n\t\t\t\t\tpg_catalog.pg_get_userbyid(d.datdba) as owner,\n\t\t\t\t\tpg_encoding_to_char(d.encoding) as encoding\n\t\t\t\tFROM pg_catalog.pg_database d\n\t\t\t\tWHERE d.datistemplate = false\n\t\t\t\t\tAND (d.datname NOT IN ('postgres', 'rdsadmin') OR d.datname = current_database())\n\t\t\t\tORDER BY d.datname;\n\t\t\t`);\n\t\t\tif (!rows[0])\n\t\t\t\tthrow new HTTPException(500, { message: \"No databases returned from database\" });\n\t\t\treturn rows;\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\tconst pool = getDbPool();\n\t\tconst { rows } = await pool.query<DatabaseSchemaType>(\"SELECT current_database() AS db;\");\n\t\tif (!rows[0])\n\t\t\tthrow new HTTPException(500, { message: \"No current database returned from database\" });\n\t\treturn rows[0];\n\t}\n\n\tasync getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\tconst pool = getDbPool();\n\t\tconst { rows } = await pool.query(`\n\t\t\tSELECT\n\t\t\t\tversion() as version,\n\t\t\t\tcurrent_database() as database,\n\t\t\t\tcurrent_user as user,\n\t\t\t\tinet_server_addr() as host,\n\t\t\t\tinet_server_port()::int4 as port,\n\t\t\t\t(SELECT count(*) FROM pg_stat_activity WHERE datname = current_database()) as active_connections,\n\t\t\t\t(SELECT setting::int FROM pg_settings WHERE name = 'max_connections') as max_connections;\n\t\t`);\n\t\tif (!rows[0])\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: \"No connection information returned from database\",\n\t\t\t});\n\n\t\tconst { connectionInfoSchema } = await import(\"@db-studio/shared/types\");\n\t\tconst result = connectionInfoSchema.parse(rows[0]);\n\t\tconst urlDefaults = parseDatabaseUrl();\n\n\t\treturn {\n\t\t\thost: result.host || urlDefaults.host,\n\t\t\tport: result.port || urlDefaults.port,\n\t\t\tuser: result.user,\n\t\t\tdatabase: result.database,\n\t\t\tversion: result.version.toString(),\n\t\t\tactive_connections: result.active_connections,\n\t\t\tmax_connections: result.max_connections,\n\t\t};\n\t}\n\n\t// --- Tables ---\n\n\tasync getTablesList(db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\tconst pool = getDbPool(db);\n\t\tconst escapeChar = (s: string) => s.replaceAll('\"', '\"\"');\n\n\t\tconst { rows: tables } = await pool.query(`\n\t\t\tSELECT table_schema as \"schemaName\", table_name as \"tableName\"\n\t\t\tFROM information_schema.tables\n\t\t\tWHERE table_type = 'BASE TABLE'\n\t\t\t\tAND table_schema NOT IN ('pg_catalog', 'information_schema')\n\t\t\t\tAND table_schema NOT LIKE 'pg_toast%'\n\t\t\tORDER BY table_schema, table_name;\n\t\t`);\n\t\tif (!tables[0]) return [];\n\n\t\treturn Promise.all(\n\t\t\ttables.map(async (t: { schemaName: string; tableName: string }) => {\n\t\t\t\tconst { rows } = await pool.query(\n\t\t\t\t\t`SELECT COUNT(*)::integer as count FROM \"${escapeChar(t.schemaName)}\".\"${escapeChar(t.tableName)}\"`,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tschemaName: t.schemaName,\n\t\t\t\t\ttableName: t.tableName,\n\t\t\t\t\trowCount: rows[0]?.count ?? 0,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\t}\n\n\tasync createTable({\n\t\ttableData,\n\t\tdb,\n\t}: {\n\t\ttableData: CreateTableSchemaType;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<void> {\n\t\tconst { tableName, fields, foreignKeys } = tableData;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst primaryKey = fields.filter((f) => f.isPrimaryKey).map((f) => f.columnName);\n\t\tconst columnDefs = fields.map((field: FieldDataType) => {\n\t\t\tlet def = `\"${field.columnName}\" ${field.columnType}`;\n\t\t\tif (field.isArray) def += \"[]\";\n\t\t\tif (primaryKey.length === 1 && field.isPrimaryKey) def += \" PRIMARY KEY\";\n\t\t\tif (field.isUnique && !field.isPrimaryKey) def += \" UNIQUE\";\n\t\t\tif (!field.isNullable) def += \" NOT NULL\";\n\t\t\tif (field.isIdentity) def += \" GENERATED ALWAYS AS IDENTITY\";\n\t\t\tif (field.defaultValue && !field.isIdentity) def += ` DEFAULT ${field.defaultValue}`;\n\t\t\treturn def;\n\t\t});\n\t\tif (primaryKey.length > 1)\n\t\t\tcolumnDefs.push(`PRIMARY KEY (${primaryKey.map((c) => `\"${c}\"`).join(\", \")})`);\n\n\t\tconst fkDefs =\n\t\t\tforeignKeys?.map((fk: ForeignKeyDataType) => {\n\t\t\t\tconst name = `fk_${tableName}_${fk.columnName}_${fk.referencedTable}_${fk.referencedColumn}`;\n\t\t\t\treturn `CONSTRAINT \"${name}\" FOREIGN KEY (\"${fk.columnName}\") REFERENCES \"${fk.referencedTable}\" (\"${fk.referencedColumn}\") ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}`;\n\t\t\t}) ?? [];\n\n\t\tawait pool.query(\n\t\t\t`CREATE TABLE \"${tableName}\" (\\n\\t\\t\\t\\t${[...columnDefs, ...fkDefs].join(\",\\n\\t\\t\\t\\t\")}\\n\\t\\t\\t);`,\n\t\t);\n\t}\n\n\tasync deleteTable(params: DeleteTableParams): Promise<DeleteTableResult> {\n\t\tconst { tableName, db, cascade } = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst { rows: tableRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = ANY(current_schemas(false))) as exists;`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (!tableRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst rowCount = await this.getTableRowCount(pool, tableName);\n\n\t\tif (!cascade) {\n\t\t\tconst related = await this.getFkReferencesForTable(pool, tableName);\n\t\t\tif (related.length > 0)\n\t\t\t\treturn {\n\t\t\t\t\tdeletedCount: 0,\n\t\t\t\t\tfkViolation: true,\n\t\t\t\t\trelatedRecords: await this.getRelatedRecordsForTable(pool, tableName),\n\t\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tawait pool.query(`DROP TABLE \"${tableName}\" ${cascade ? \"CASCADE\" : \"RESTRICT\"}`);\n\t\t\treturn { deletedCount: rowCount, fkViolation: false, relatedRecords: [] };\n\t\t} catch (error) {\n\t\t\tconst pgErr = error as { code?: string };\n\t\t\tif (pgErr.code === \"2BP01\") {\n\t\t\t\treturn {\n\t\t\t\t\tdeletedCount: 0,\n\t\t\t\t\tfkViolation: true,\n\t\t\t\t\trelatedRecords: await this.getRelatedRecordsForTable(pool, tableName),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to delete table \"${tableName}\"` });\n\t\t}\n\t}\n\n\tasync renameTable(params: RenameTableParamsSchemaType): Promise<void> {\n\t\ttry {\n\t\t\tconst { tableName, newTableName, schemaName: requestedSchema, db } = params;\n\t\t\tthis.assertDifferentTableName(tableName, newTableName);\n\t\t\tconst pool = getDbPool(db);\n\n\t\t\t// Tables are listed from every user schema, so resolve the actual schema\n\t\t\t// instead of assuming \"public\".\n\t\t\tconst { rows: schemaRows } = await pool.query(\n\t\t\t\t`SELECT table_schema as \"schemaName\" FROM information_schema.tables WHERE table_name = $1 AND table_schema NOT IN ('pg_catalog', 'information_schema') AND table_schema NOT LIKE 'pg_toast%';`,\n\t\t\t\t[tableName],\n\t\t\t);\n\t\t\tconst schemas = (schemaRows as Array<{ schemaName: string }>).map((r) => r.schemaName);\n\t\t\tif (schemas.length === 0)\n\t\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t\tif (requestedSchema && !schemas.includes(requestedSchema)) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Table \"${requestedSchema}\".\"${tableName}\" does not exist`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!requestedSchema && schemas.length > 1)\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Table \"${tableName}\" exists in multiple schemas (${schemas.join(\", \")}); rename is ambiguous`,\n\t\t\t\t});\n\t\t\tconst schemaName = requestedSchema ?? (schemas[0] as string);\n\n\t\t\tconst { rows: targetRows } = await pool.query(\n\t\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = $2) as exists;`,\n\t\t\t\t[newTableName, schemaName],\n\t\t\t);\n\t\t\tif (targetRows[0]?.exists)\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Table \"${newTableName}\" already exists`,\n\t\t\t\t});\n\n\t\t\tawait pool.query(\n\t\t\t\t`ALTER TABLE \"${schemaName.replaceAll('\"', '\"\"')}\".\"${tableName.replaceAll('\"', '\"\"')}\" RENAME TO \"${newTableName.replaceAll('\"', '\"\"')}\"`,\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getTableSchema({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\tconst pool = getDbPool(db);\n\n\t\tconst { rows: existsRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = ANY(current_schemas(false)) AND table_name = $1) as exists`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (!existsRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tinterface ColumnInfo {\n\t\t\tcolumn_name: string;\n\t\t\tdata_type: string;\n\t\t\tudt_name: string;\n\t\t\tis_nullable: string;\n\t\t\tcolumn_default: string | null;\n\t\t\tcharacter_maximum_length: number | null;\n\t\t\tnumeric_precision: number | null;\n\t\t\tnumeric_scale: number | null;\n\t\t}\n\t\tinterface ConstraintInfo {\n\t\t\tconstraint_name: string;\n\t\t\tconstraint_type: string;\n\t\t\tcolumn_name: string;\n\t\t\tforeign_table_name: string | null;\n\t\t\tforeign_column_name: string | null;\n\t\t}\n\t\tinterface IndexInfo {\n\t\t\tindexname: string;\n\t\t\tindexdef: string;\n\t\t}\n\n\t\tconst { rows: columns } = await pool.query<ColumnInfo>(\n\t\t\t`SELECT column_name, data_type, udt_name, is_nullable, column_default, character_maximum_length, numeric_precision, numeric_scale\n\t\t\t FROM information_schema.columns WHERE table_schema = ${resolvedSchemaFor(\"$1\")} AND table_name = $1 ORDER BY ordinal_position`,\n\t\t\t[tableName],\n\t\t);\n\n\t\tconst { rows: constraints } = await pool.query<ConstraintInfo>(\n\t\t\t`SELECT tc.constraint_name, tc.constraint_type, kcu.column_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name\n\t\t\t FROM information_schema.table_constraints tc\n\t\t\t JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema\n\t\t\t LEFT JOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name AND tc.table_schema = ccu.table_schema AND tc.constraint_type = 'FOREIGN KEY'\n\t\t\t WHERE tc.table_schema = ${resolvedSchemaFor(\"$1\")} AND tc.table_name = $1 ORDER BY tc.constraint_type, tc.constraint_name`,\n\t\t\t[tableName],\n\t\t);\n\n\t\tconst { rows: indexes } = await pool.query<IndexInfo>(\n\t\t\t`SELECT indexname, indexdef FROM pg_indexes WHERE schemaname = ${resolvedSchemaFor(\"$1\")} AND tablename = $1\n\t\t\t AND indexname NOT IN (SELECT constraint_name FROM information_schema.table_constraints WHERE table_schema = ${resolvedSchemaFor(\"$1\")} AND table_name = $1 AND constraint_type = 'PRIMARY KEY')`,\n\t\t\t[tableName],\n\t\t);\n\n\t\tconst formatType = (col: ColumnInfo): string => {\n\t\t\tconst {\n\t\t\t\tdata_type,\n\t\t\t\tudt_name,\n\t\t\t\tcharacter_maximum_length,\n\t\t\t\tnumeric_precision,\n\t\t\t\tnumeric_scale,\n\t\t\t} = col;\n\t\t\tif (data_type === \"USER-DEFINED\") return udt_name;\n\t\t\tif (data_type === \"ARRAY\") return `${udt_name.replace(/^_/, \"\")}[]`;\n\t\t\tif (\n\t\t\t\t(data_type === \"character varying\" || data_type === \"varchar\") &&\n\t\t\t\tcharacter_maximum_length\n\t\t\t)\n\t\t\t\treturn `varchar(${character_maximum_length})`;\n\t\t\tif (data_type === \"character\" && character_maximum_length)\n\t\t\t\treturn `char(${character_maximum_length})`;\n\t\t\tif (data_type === \"numeric\" && numeric_precision !== null) {\n\t\t\t\treturn numeric_scale !== null && numeric_scale > 0\n\t\t\t\t\t? `numeric(${numeric_precision}, ${numeric_scale})`\n\t\t\t\t\t: `numeric(${numeric_precision})`;\n\t\t\t}\n\t\t\tif (data_type === \"timestamp with time zone\") return \"timestamp with time zone\";\n\t\t\tif (data_type === \"timestamp without time zone\") return \"timestamp\";\n\t\t\tconst typeMap: Record<string, string> = {\n\t\t\t\t\"character varying\": \"varchar\",\n\t\t\t\tcharacter: \"char\",\n\t\t\t\t\"double precision\": \"float8\",\n\t\t\t\tinteger: \"integer\",\n\t\t\t\tbigint: \"bigint\",\n\t\t\t\tsmallint: \"smallint\",\n\t\t\t\tboolean: \"boolean\",\n\t\t\t\ttext: \"text\",\n\t\t\t\tuuid: \"uuid\",\n\t\t\t\tjson: \"json\",\n\t\t\t\tjsonb: \"jsonb\",\n\t\t\t\tdate: \"date\",\n\t\t\t\ttime: \"time\",\n\t\t\t\tbytea: \"bytea\",\n\t\t\t};\n\t\t\treturn typeMap[data_type] || data_type;\n\t\t};\n\n\t\tconst lines: string[] = [`create table public.${tableName} (`];\n\t\tconst colDefs = columns.map((col) => {\n\t\t\tlet def = ` ${col.column_name} ${formatType(col)}`;\n\t\t\tif (col.is_nullable === \"NO\") def += \" not null\";\n\t\t\tif (col.column_default !== null) def += ` default ${col.column_default}`;\n\t\t\treturn def;\n\t\t});\n\n\t\tconst constraintMap = new Map<string, ConstraintInfo[]>();\n\t\tfor (const c of constraints) {\n\t\t\tconst arr = constraintMap.get(c.constraint_name) ?? [];\n\t\t\tarr.push(c);\n\t\t\tconstraintMap.set(c.constraint_name, arr);\n\t\t}\n\n\t\tconst constraintDefs: string[] = [];\n\t\tfor (const [name, cols] of constraintMap) {\n\t\t\tconst first = cols[0];\n\t\t\tconst colNames = cols.map((c) => c.column_name).join(\", \");\n\t\t\tif (first.constraint_type === \"PRIMARY KEY\") {\n\t\t\t\tconstraintDefs.push(` constraint ${name} primary key (${colNames})`);\n\t\t\t} else if (first.constraint_type === \"FOREIGN KEY\") {\n\t\t\t\tconstraintDefs.push(\n\t\t\t\t\t` constraint ${name} foreign key (${colNames}) references ${first.foreign_table_name} (${first.foreign_column_name})`,\n\t\t\t\t);\n\t\t\t} else if (first.constraint_type === \"UNIQUE\") {\n\t\t\t\tconstraintDefs.push(` constraint ${name} unique (${colNames})`);\n\t\t\t}\n\t\t}\n\n\t\tlines.push([...colDefs, ...constraintDefs].join(\",\\n\"));\n\t\tlines.push(\") tablespace pg_default;\");\n\n\t\tfor (const idx of indexes) {\n\t\t\tconst isUnique = [...constraintMap.values()].some(\n\t\t\t\t(c) => c[0].constraint_type === \"UNIQUE\" && c[0].constraint_name === idx.indexname,\n\t\t\t);\n\t\t\tif (!isUnique) {\n\t\t\t\tlines.push(\"\");\n\t\t\t\tlines.push(`${idx.indexdef};`);\n\t\t\t}\n\t\t}\n\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\t// --- Columns ---\n\n\tasync getTableColumns({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\tconst pool = getDbPool(db);\n\t\tconst { rows } = await pool.query(\n\t\t\t`SELECT\n\t\t\t\tc.column_name as \"columnName\", c.data_type as \"dataType\", c.udt_name as \"udtName\",\n\t\t\t\tc.is_nullable = 'YES' as \"isNullable\", c.column_default as \"columnDefault\",\n\t\t\t\tCASE WHEN pk.column_name IS NOT NULL THEN true ELSE false END as \"isPrimaryKey\",\n\t\t\t\tCASE WHEN fk.column_name IS NOT NULL THEN true ELSE false END as \"isForeignKey\",\n\t\t\t\tfk.referenced_table as \"referencedTable\", fk.referenced_column as \"referencedColumn\",\n\t\t\t\tCASE WHEN c.data_type = 'USER-DEFINED' THEN\n\t\t\t\t\t(SELECT array_agg(e.enumlabel ORDER BY e.enumsortorder) FROM pg_type t JOIN pg_enum e ON t.oid = e.enumtypid WHERE t.typname = c.udt_name)\n\t\t\t\tELSE NULL END as \"enumValues\"\n\t\t\tFROM information_schema.columns c\n\t\t\tLEFT JOIN (\n\t\t\t\tSELECT ku.column_name FROM information_schema.table_constraints tc\n\t\t\t\tJOIN information_schema.key_column_usage ku ON tc.constraint_name = ku.constraint_name AND tc.table_schema = ku.table_schema\n\t\t\t\tWHERE tc.constraint_type = 'PRIMARY KEY' AND tc.table_schema = ${resolvedSchemaFor(\"$1\")} AND tc.table_name = $1\n\t\t\t) pk ON c.column_name = pk.column_name\n\t\t\tLEFT JOIN (\n\t\t\t\tSELECT kcu.column_name, ccu.table_name AS referenced_table, ccu.column_name AS referenced_column\n\t\t\t\tFROM information_schema.table_constraints tc\n\t\t\t\tJOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema\n\t\t\t\tJOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name AND tc.table_schema = ccu.table_schema\n\t\t\t\tWHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_schema = ${resolvedSchemaFor(\"$1\")} AND tc.table_name = $1\n\t\t\t) fk ON c.column_name = fk.column_name\n\t\t\tWHERE c.table_schema = ${resolvedSchemaFor(\"$1\")} AND c.table_name = $1 ORDER BY c.ordinal_position;`,\n\t\t\t[tableName],\n\t\t);\n\n\t\tif (!rows || rows.length === 0)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\treturn rows.map((r) => {\n\t\t\tlet parsedEnumValues: string[] | null = null;\n\t\t\tif (r.enumValues) {\n\t\t\t\tif (Array.isArray(r.enumValues)) {\n\t\t\t\t\tparsedEnumValues = r.enumValues;\n\t\t\t\t} else if (typeof r.enumValues === \"string\") {\n\t\t\t\t\tparsedEnumValues = r.enumValues.replace(/[{}]/g, \"\").split(\",\").filter(Boolean);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcolumnName: r.columnName,\n\t\t\t\tdataType: mapPostgresToDataType(r.dataType),\n\t\t\t\tdataTypeLabel: standardizeDataTypeLabel(r.dataType),\n\t\t\t\tisNullable: r.isNullable,\n\t\t\t\tcolumnDefault: r.columnDefault,\n\t\t\t\tisPrimaryKey: r.isPrimaryKey,\n\t\t\t\tisForeignKey: r.isForeignKey,\n\t\t\t\treferencedTable: r.referencedTable,\n\t\t\t\treferencedColumn: r.referencedColumn,\n\t\t\t\tenumValues: parsedEnumValues,\n\t\t\t};\n\t\t});\n\t}\n\n\tasync addColumn(params: AddColumnParamsSchemaType): Promise<void> {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tcolumnName,\n\t\t\tcolumnType,\n\t\t\tdefaultValue,\n\t\t\tisPrimaryKey,\n\t\t\tisNullable,\n\t\t\tisUnique,\n\t\t\tisIdentity,\n\t\t\tisArray,\n\t\t\tdb,\n\t\t} = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst { rows: tableRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = ANY(current_schemas(false))) as exists;`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (!tableRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst { rows: colRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = $1 AND column_name = $2 AND table_schema = ${resolvedSchemaFor(\"$1\")}) as exists;`,\n\t\t\t[tableName, columnName],\n\t\t);\n\t\tif (colRows[0]?.exists)\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${columnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\n\t\tlet def = `\"${columnName}\" ${columnType}`;\n\t\tif (isArray) def += \"[]\";\n\t\tif (isPrimaryKey) def += \" PRIMARY KEY\";\n\t\tif (isUnique && !isPrimaryKey) def += \" UNIQUE\";\n\t\tif (!isNullable) def += \" NOT NULL\";\n\t\tif (isIdentity) def += \" GENERATED ALWAYS AS IDENTITY\";\n\t\tif (defaultValue?.trim() && !isIdentity) def += ` DEFAULT ${defaultValue.trim()}`;\n\n\t\tawait pool.query(`ALTER TABLE \"${tableName}\" ADD COLUMN ${def}`);\n\t}\n\n\tasync deleteColumn(params: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\tconst { tableName, columnName, cascade, db } = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst { rows: tableRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = ANY(current_schemas(false))) as exists;`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (!tableRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst { rows: colRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = $1 AND column_name = $2 AND table_schema = ${resolvedSchemaFor(\"$1\")}) as exists;`,\n\t\t\t[tableName, columnName],\n\t\t);\n\t\tif (!colRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\n\t\tconst { rowCount } = await pool.query(\n\t\t\t`ALTER TABLE \"${tableName}\" DROP COLUMN \"${columnName}\" ${cascade ? \"CASCADE\" : \"RESTRICT\"}`,\n\t\t);\n\t\treturn { deletedCount: rowCount ?? 0 };\n\t}\n\n\tasync alterColumn(params: AlterColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, columnType, isNullable, defaultValue, db } = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst { rows: tableRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = ANY(current_schemas(false))) as exists;`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (!tableRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst { rows: colRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = $1 AND column_name = $2 AND table_schema = ${resolvedSchemaFor(\"$1\")}) as exists;`,\n\t\t\t[tableName, columnName],\n\t\t);\n\t\tif (!colRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\n\t\tconst client = await pool.connect();\n\t\ttry {\n\t\t\tawait client.query(\"BEGIN\");\n\t\t\tawait client.query(\n\t\t\t\t`ALTER TABLE \"${tableName}\" ALTER COLUMN \"${columnName}\" TYPE ${columnType}`,\n\t\t\t);\n\t\t\tawait client.query(\n\t\t\t\t`ALTER TABLE \"${tableName}\" ALTER COLUMN \"${columnName}\" ${isNullable ? \"DROP\" : \"SET\"} NOT NULL`,\n\t\t\t);\n\t\t\tif (defaultValue?.trim()) {\n\t\t\t\tawait client.query(\n\t\t\t\t\t`ALTER TABLE \"${tableName}\" ALTER COLUMN \"${columnName}\" SET DEFAULT ${defaultValue.trim()}`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tawait client.query(\n\t\t\t\t\t`ALTER TABLE \"${tableName}\" ALTER COLUMN \"${columnName}\" DROP DEFAULT`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait client.query(\"COMMIT\");\n\t\t} catch (error) {\n\t\t\tawait client.query(\"ROLLBACK\");\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tclient.release();\n\t\t}\n\t}\n\n\tasync renameColumn(params: RenameColumnParamsSchemaType): Promise<void> {\n\t\tconst { tableName, columnName, newColumnName, db } = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst colExistsQuery = `SELECT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = $1 AND column_name = $2 AND table_schema = ${resolvedSchemaFor(\"$1\")}) as exists;`;\n\n\t\tconst { rows: tableRows } = await pool.query(\n\t\t\t`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = ANY(current_schemas(false))) as exists;`,\n\t\t\t[tableName],\n\t\t);\n\t\tif (!tableRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst { rows: curRows } = await pool.query(colExistsQuery, [tableName, columnName]);\n\t\tif (!curRows[0]?.exists)\n\t\t\tthrow new HTTPException(404, {\n\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t});\n\n\t\tconst { rows: nextRows } = await pool.query(colExistsQuery, [tableName, newColumnName]);\n\t\tif (nextRows[0]?.exists)\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Column \"${newColumnName}\" already exists in table \"${tableName}\"`,\n\t\t\t});\n\n\t\tawait pool.query(\n\t\t\t`ALTER TABLE \"${tableName}\" RENAME COLUMN \"${columnName}\" TO \"${newColumnName}\"`,\n\t\t);\n\t}\n\n\t// --- Records ---\n\n\tasync addRecord({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\tconst { tableName, data } = params;\n\t\tconst pool = getDbPool(db);\n\t\tconst columns = Object.keys(data);\n\t\tconst values = Object.values(data);\n\t\tconst placeholders = columns.map((_, i) => `$${i + 1}`).join(\", \");\n\t\tconst colNames = columns.map((c) => `\"${c}\"`).join(\", \");\n\t\tconst result = await pool.query(\n\t\t\t`INSERT INTO \"${tableName}\" (${colNames}) VALUES (${placeholders}) RETURNING *`,\n\t\t\tvalues,\n\t\t);\n\t\tif (result.rowCount === 0)\n\t\t\tthrow new HTTPException(500, { message: `Failed to insert record into \"${tableName}\"` });\n\t\treturn { insertedCount: result.rowCount ?? 0 };\n\t}\n\n\tasync updateRecords({\n\t\tparams,\n\t\tdb,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\tconst { tableName } = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst keyColumns = this.resolveKeyColumns(params);\n\t\tthis.assertWholeKey(await this.getPrimaryKeyColumns(pool, tableName), keyColumns);\n\t\tconst groups = this.groupUpdatesByKey(params, keyColumns);\n\n\t\tawait pool.query(\"BEGIN\");\n\t\ttry {\n\t\t\tlet total = 0;\n\t\t\tfor (const { keyValues, rowUpdates } of groups) {\n\t\t\t\tconst setClauses = rowUpdates.map((u, i) => `\"${u.columnName}\" = $${i + 1}`);\n\t\t\t\tconst values = rowUpdates.map((u) =>\n\t\t\t\t\tu.value !== null && typeof u.value === \"object\" ? JSON.stringify(u.value) : u.value,\n\t\t\t\t);\n\t\t\t\tconst whereClauses = keyColumns.map(\n\t\t\t\t\t(column, i) => `\"${column}\" = $${values.length + i + 1}`,\n\t\t\t\t);\n\t\t\t\tvalues.push(...keyValues);\n\t\t\t\tconst result = await pool.query(\n\t\t\t\t\t`UPDATE \"${tableName}\" SET ${setClauses.join(\", \")} WHERE ${whereClauses.join(\" AND \")} RETURNING *`,\n\t\t\t\t\tvalues,\n\t\t\t\t);\n\t\t\t\tif (result.rowCount === 0)\n\t\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\t\tmessage: `Record with ${this.describeKey(keyColumns, keyValues)} not found in table \"${tableName}\"`,\n\t\t\t\t\t});\n\t\t\t\ttotal += result.rowCount ?? 0;\n\t\t\t}\n\t\t\tawait pool.query(\"COMMIT\");\n\t\t\treturn { updatedCount: total };\n\t\t} catch (error) {\n\t\t\tawait pool.query(\"ROLLBACK\");\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to update records in \"${tableName}\"` });\n\t\t}\n\t}\n\n\tasync deleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\tconst pool = getDbPool(db);\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\t\tthis.assertDeletableKey(await this.getPrimaryKeyColumns(pool, tableName));\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst placeholders = pkValues.map((_, i) => `$${i + 1}`).join(\", \");\n\n\t\ttry {\n\t\t\tawait pool.query(\"BEGIN\");\n\t\t\tconst result = await pool.query(\n\t\t\t\t`DELETE FROM \"${tableName}\" WHERE \"${pkColumn}\" IN (${placeholders}) RETURNING *`,\n\t\t\t\tpkValues,\n\t\t\t);\n\t\t\tawait pool.query(\"COMMIT\");\n\t\t\treturn { deletedCount: result.rowCount ?? 0, fkViolation: false, relatedRecords: [] };\n\t\t} catch (error) {\n\t\t\tawait pool.query(\"ROLLBACK\");\n\t\t\tconst pgErr = error as { code?: string };\n\t\t\tif (pgErr.code === \"23503\") {\n\t\t\t\tconst relatedRecords = await this.getRelatedRecords(pool, tableName, primaryKeys, db);\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to delete records from \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\tasync forceDeleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<{ deletedCount: number }> {\n\t\tconst pool = getDbPool(db);\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\t\tthis.assertDeletableKey(await this.getPrimaryKeyColumns(pool, tableName));\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tawait pool.query(\"BEGIN\");\n\n\t\ttry {\n\t\t\tconst fkConstraints = await this.getFkConstraints(pool, tableName);\n\t\t\tlet totalRelated = 0;\n\t\t\tconst deletedTables = new Set<string>();\n\n\t\t\tconst deleteRelated = async (\n\t\t\t\ttargetTable: string,\n\t\t\t\ttargetColumn: string,\n\t\t\t\tvalues: unknown[],\n\t\t\t) => {\n\t\t\t\tconst nested = await this.getFkConstraints(pool, targetTable);\n\t\t\t\tfor (const nfk of nested) {\n\t\t\t\t\tconst placeholders = values.map((_, i) => `$${i + 1}`).join(\", \");\n\t\t\t\t\tconst { rows } = await pool.query(\n\t\t\t\t\t\t`SELECT \"${nfk.referencedColumn}\" FROM \"${targetTable}\" WHERE \"${targetColumn}\" IN (${placeholders})`,\n\t\t\t\t\t\tvalues,\n\t\t\t\t\t);\n\t\t\t\t\tconst nestedVals = rows.map((r: Record<string, unknown>) => r[nfk.referencedColumn]);\n\t\t\t\t\tif (nestedVals.length > 0)\n\t\t\t\t\t\tawait deleteRelated(nfk.referencingTable, nfk.referencingColumn, nestedVals);\n\t\t\t\t}\n\t\t\t\tconst ph = values.map((_, i) => `$${i + 1}`).join(\", \");\n\t\t\t\tconst res = await pool.query(\n\t\t\t\t\t`DELETE FROM \"${targetTable}\" WHERE \"${targetColumn}\" IN (${ph})`,\n\t\t\t\t\tvalues,\n\t\t\t\t);\n\t\t\t\ttotalRelated += res.rowCount ?? 0;\n\t\t\t\tdeletedTables.add(targetTable);\n\t\t\t};\n\n\t\t\tfor (const c of fkConstraints) {\n\t\t\t\tif (!deletedTables.has(c.referencingTable))\n\t\t\t\t\tawait deleteRelated(c.referencingTable, c.referencingColumn, pkValues);\n\t\t\t}\n\n\t\t\tconst ph = pkValues.map((_, i) => `$${i + 1}`).join(\", \");\n\t\t\tconst result = await pool.query(\n\t\t\t\t`DELETE FROM \"${tableName}\" WHERE \"${pkColumn}\" IN (${ph}) RETURNING *`,\n\t\t\t\tpkValues,\n\t\t\t);\n\t\t\tawait pool.query(\"COMMIT\");\n\t\t\treturn { deletedCount: (result.rowCount ?? 0) + totalRelated };\n\t\t} catch (error) {\n\t\t\tawait pool.query(\"ROLLBACK\");\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to force delete records from \"${tableName}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\tasync bulkInsertRecords({\n\t\ttableName,\n\t\trecords,\n\t\tdb,\n\t}: BulkInsertRecordsParams): Promise<BulkInsertResult> {\n\t\tif (!records || records.length === 0)\n\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\n\t\tconst pool = getDbPool(db);\n\t\tconst client = await pool.connect();\n\n\t\ttry {\n\t\t\tconst columns = Object.keys(records[0]);\n\t\t\tconst colNames = columns.map((c) => `\"${c}\"`).join(\", \");\n\t\t\tlet successCount = 0;\n\n\t\t\tawait client.query(\"BEGIN\");\n\t\t\tfor (const record of records) {\n\t\t\t\tconst values = columns.map((col) => record[col]);\n\t\t\t\tconst placeholders = columns.map((_, i) => `$${i + 1}`).join(\", \");\n\t\t\t\ttry {\n\t\t\t\t\tawait client.query(\n\t\t\t\t\t\t`INSERT INTO \"${tableName}\" (${colNames}) VALUES (${placeholders}) RETURNING *`,\n\t\t\t\t\t\tvalues,\n\t\t\t\t\t);\n\t\t\t\t\tsuccessCount++;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new HTTPException(500, {\n\t\t\t\t\t\tmessage: `Failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait client.query(\"COMMIT\");\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `Bulk insert completed: ${successCount} records inserted`,\n\t\t\t\tsuccessCount,\n\t\t\t\tfailureCount: 0,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tawait client.query(\"ROLLBACK\");\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, {\n\t\t\t\tmessage: `Failed to bulk insert records into \"${tableName}\"`,\n\t\t\t});\n\t\t} finally {\n\t\t\tclient.release();\n\t\t}\n\t}\n\n\t// --- Query ---\n\n\tasync executeQuery({\n\t\tquery,\n\t\tdb,\n\t}: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\tconst pool = getDbPool(db);\n\t\tif (!query?.trim()) throw new HTTPException(400, { message: \"Query is required\" });\n\t\tconst cleaned = query.trim().replace(/;+$/, \"\");\n\t\tconst start = performance.now();\n\t\tconst result = await pool.query(cleaned);\n\t\tconst duration = performance.now() - start;\n\t\treturn {\n\t\t\tcolumns: result.fields.map((f) => f.name),\n\t\t\trows: result.rows,\n\t\t\trowCount: result.rows.length,\n\t\t\tduration,\n\t\t\tmessage: result.rows.length === 0 ? \"OK\" : undefined,\n\t\t};\n\t}\n\n\t// =========================================================\n\t// Private helpers\n\t// =========================================================\n\n\t/** CockroachDB speaks the PostgreSQL protocol but has no pg_database_size(). */\n\tprivate supportsDatabaseSize(pool: PgPool): Promise<boolean> {\n\t\tthis.databaseSizeSupport ??= pool\n\t\t\t.query(`SELECT to_regprocedure('pg_database_size(name)') IS NOT NULL AS \"supported\"`)\n\t\t\t.then(({ rows }) => rows[0]?.supported === true)\n\t\t\t.catch((e) => {\n\t\t\t\tthis.databaseSizeSupport = undefined;\n\t\t\t\tthrow e;\n\t\t\t});\n\t\treturn this.databaseSizeSupport;\n\t}\n\n\tprivate async getPrimaryKeyColumns(pool: PgPool, tableName: string): Promise<string[]> {\n\t\tconst result = await pool.query(\n\t\t\t`SELECT a.attname as column_name\n\t\t\t FROM pg_index i\n\t\t\t JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)\n\t\t\t WHERE i.indrelid = $1::regclass AND i.indisprimary\n\t\t\t ORDER BY array_position(i.indkey, a.attnum)`,\n\t\t\t[`\"${tableName}\"`],\n\t\t);\n\t\treturn result.rows.map((row) => row.column_name);\n\t}\n\n\tprivate async getFkConstraints(\n\t\tpool: PgPool,\n\t\ttableName: string,\n\t): Promise<ForeignKeyConstraint[]> {\n\t\tconst { rows } = await pool.query(\n\t\t\t`SELECT tc.constraint_name, tc.table_name as referencing_table, kcu.column_name as referencing_column,\n\t\t\t\tccu.table_name AS referenced_table, ccu.column_name AS referenced_column\n\t\t\t FROM information_schema.table_constraints AS tc\n\t\t\t JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema\n\t\t\t JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name AND ccu.table_schema = tc.table_schema\n\t\t\t WHERE tc.constraint_type = 'FOREIGN KEY' AND ccu.table_name = $1`,\n\t\t\t[tableName],\n\t\t);\n\t\treturn rows.map((row: ForeignKeyConstraintRow) => ({\n\t\t\tconstraintName: row.constraint_name,\n\t\t\treferencingTable: row.referencing_table,\n\t\t\treferencingColumn: row.referencing_column,\n\t\t\treferencedTable: row.referenced_table,\n\t\t\treferencedColumn: row.referenced_column,\n\t\t}));\n\t}\n\n\tprivate async getFkReferencesForTable(\n\t\tpool: PgPool,\n\t\ttableName: string,\n\t): Promise<ForeignKeyConstraint[]> {\n\t\treturn this.getFkConstraints(pool, tableName);\n\t}\n\n\tprivate async getRelatedRecordsForTable(\n\t\tpool: PgPool,\n\t\ttableName: string,\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getFkReferencesForTable(pool, tableName);\n\t\tif (fks.length === 0) return [];\n\t\tconst results: RelatedRecord[] = [];\n\t\tfor (const fk of fks) {\n\t\t\tconst { rows } = await pool.query(`SELECT * FROM \"${fk.referencingTable}\" LIMIT 100`);\n\t\t\tif (rows.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: rows,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate async getRelatedRecords(\n\t\tpool: PgPool,\n\t\ttableName: string,\n\t\tprimaryKeys: DeleteRecordSchemaType[\"primaryKeys\"],\n\t\tdb: DatabaseSchemaType[\"db\"],\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getFkConstraints(pool, tableName);\n\t\tif (fks.length === 0) return [];\n\n\t\tconst results: RelatedRecord[] = [];\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst constraintsByTable = new Map<string, ForeignKeyConstraint[]>();\n\t\tfor (const fk of fks) {\n\t\t\tconst key = `${fk.referencingTable}.${fk.referencingColumn}`;\n\t\t\tconst arr = constraintsByTable.get(key) ?? [];\n\t\t\tarr.push(fk);\n\t\t\tconstraintsByTable.set(key, arr);\n\t\t}\n\n\t\tfor (const [, constraints] of constraintsByTable) {\n\t\t\tconst fk = constraints[0];\n\t\t\tif (!fk) continue;\n\t\t\tconst matchingPk = primaryKeys.find((pk) => pk.columnName === fk.referencedColumn);\n\t\t\tif (!matchingPk) continue;\n\t\t\tconst ph = pkValues.map((_, i) => `$${i + 1}`).join(\", \");\n\t\t\tconst { rows } = await pool.query(\n\t\t\t\t`SELECT * FROM \"${fk.referencingTable}\" WHERE \"${fk.referencingColumn}\" IN (${ph}) LIMIT 100`,\n\t\t\t\tpkValues,\n\t\t\t);\n\t\t\tif (rows.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: rows,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tvoid db;\n\t\treturn results;\n\t}\n\n\tprivate async getTableRowCount(pool: PgPool, tableName: string): Promise<number> {\n\t\tconst { rows } = await pool.query(`SELECT COUNT(*) as count FROM \"${tableName}\"`);\n\t\treturn Number.parseInt(rows[0]?.count ?? \"0\", 10);\n\t}\n}\n","import type { ExecuteQueryResult } from \"@db-studio/shared/types\";\n\ntype ShapeFn = (reply: unknown) => Pick<ExecuteQueryResult, \"columns\" | \"rows\" | \"rowCount\">;\n\nconst isStringArray = (v: unknown): v is string[] =>\n\tArray.isArray(v) && v.every((x) => typeof x === \"string\" || x === null);\n\nconst isFlatPairArray = (v: unknown): v is unknown[] => Array.isArray(v) && v.length % 2 === 0;\n\n/**\n * Tokenize a redis-cli style command line into an argv array.\n * Supports single and double quotes; backslash-escapes inside double quotes.\n *\n * Examples:\n * \"GET foo\" -> [\"GET\", \"foo\"]\n * 'SET foo \"hello world\"' -> [\"SET\", \"foo\", \"hello world\"]\n * \"HSET k field 'value with space'\" -> [\"HSET\", \"k\", \"field\", \"value with space\"]\n */\nexport function tokenizeCommand(input: string): string[] {\n\tconst out: string[] = [];\n\tlet cur = \"\";\n\tlet i = 0;\n\tlet inSingle = false;\n\tlet inDouble = false;\n\n\twhile (i < input.length) {\n\t\tconst ch = input[i];\n\n\t\tif (inSingle) {\n\t\t\tif (ch === \"'\") inSingle = false;\n\t\t\telse cur += ch;\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (inDouble) {\n\t\t\tif (ch === \"\\\\\" && i + 1 < input.length) {\n\t\t\t\tcur += input[i + 1];\n\t\t\t\ti += 2;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (ch === '\"') inDouble = false;\n\t\t\telse cur += ch;\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (ch === \"'\") {\n\t\t\tinSingle = true;\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '\"') {\n\t\t\tinDouble = true;\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === \" \" || ch === \"\\t\" || ch === \"\\n\") {\n\t\t\tif (cur.length > 0) {\n\t\t\t\tout.push(cur);\n\t\t\t\tcur = \"\";\n\t\t\t}\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tcur += ch;\n\t\ti++;\n\t}\n\n\tif (inSingle || inDouble) {\n\t\tthrow new Error(\"Unterminated quoted string in command\");\n\t}\n\tif (cur.length > 0) out.push(cur);\n\treturn out;\n}\n\nconst singleCellFallback: ShapeFn = (reply) => ({\n\tcolumns: [\"result\"],\n\trows: [{ result: typeof reply === \"string\" ? reply : JSON.stringify(reply, null, 2) }],\n\trowCount: 1,\n});\n\nconst scalarShape: ShapeFn = (reply) => {\n\tif (reply === null) {\n\t\treturn {\n\t\t\tcolumns: [\"value\"],\n\t\t\trows: [{ value: null }],\n\t\t\trowCount: 0,\n\t\t};\n\t}\n\treturn {\n\t\tcolumns: [\"value\"],\n\t\trows: [{ value: reply as string | number }],\n\t\trowCount: 1,\n\t};\n};\n\nconst statusShape: ShapeFn = (reply) => ({\n\tcolumns: [\"status\"],\n\trows: [{ status: reply as string }],\n\trowCount: 1,\n});\n\nconst flatArrayShape: ShapeFn = (reply) => {\n\tif (!Array.isArray(reply)) return singleCellFallback(reply);\n\treturn {\n\t\tcolumns: [\"#\", \"value\"],\n\t\trows: reply.map((v, idx) => ({ \"#\": idx, value: v as unknown })),\n\t\trowCount: reply.length,\n\t};\n};\n\nconst pairArrayShape: ShapeFn = (reply) => {\n\tif (!isFlatPairArray(reply)) return singleCellFallback(reply);\n\tconst rows: Record<string, unknown>[] = [];\n\tfor (let i = 0; i < reply.length; i += 2) {\n\t\trows.push({ field: reply[i], value: reply[i + 1] });\n\t}\n\treturn { columns: [\"field\", \"value\"], rows, rowCount: rows.length };\n};\n\nconst zrangeWithScoresShape: ShapeFn = (reply) => {\n\tif (!isFlatPairArray(reply)) return flatArrayShape(reply);\n\tconst rows: Record<string, unknown>[] = [];\n\tfor (let i = 0; i < reply.length; i += 2) {\n\t\trows.push({ member: reply[i], score: reply[i + 1] });\n\t}\n\treturn { columns: [\"member\", \"score\"], rows, rowCount: rows.length };\n};\n\nconst infoShape: ShapeFn = (reply) => {\n\tif (typeof reply !== \"string\") return singleCellFallback(reply);\n\tconst rows: Record<string, unknown>[] = [];\n\tlet section = \"\";\n\tfor (const line of reply.split(/\\r?\\n/)) {\n\t\tif (!line.trim()) continue;\n\t\tif (line.startsWith(\"#\")) {\n\t\t\tsection = line.replace(/^#\\s*/, \"\").trim();\n\t\t\tcontinue;\n\t\t}\n\t\tconst idx = line.indexOf(\":\");\n\t\tif (idx < 0) continue;\n\t\trows.push({ section, key: line.slice(0, idx), value: line.slice(idx + 1) });\n\t}\n\treturn { columns: [\"section\", \"key\", \"value\"], rows, rowCount: rows.length };\n};\n\nconst xrangeShape: ShapeFn = (reply) => {\n\tif (!Array.isArray(reply)) return singleCellFallback(reply);\n\tconst rows = reply.map((entry) => {\n\t\tif (!Array.isArray(entry) || entry.length < 2) return { id: null, fields: null };\n\t\tconst [id, fields] = entry;\n\t\tconst fieldsObj: Record<string, unknown> = {};\n\t\tif (Array.isArray(fields)) {\n\t\t\tfor (let i = 0; i < fields.length; i += 2) {\n\t\t\t\tfieldsObj[String(fields[i])] = fields[i + 1];\n\t\t\t}\n\t\t}\n\t\treturn { id, fields: fieldsObj };\n\t});\n\treturn { columns: [\"id\", \"fields\"], rows, rowCount: rows.length };\n};\n\n/**\n * Dispatch table keyed on the canonical (uppercase) command name.\n * If a command isn't found here, the reply is wrapped as a single-cell JSON row.\n */\nconst COMMAND_SHAPES: Record<string, ShapeFn> = {\n\tPING: statusShape,\n\tGET: scalarShape,\n\tSET: statusShape,\n\tTYPE: scalarShape,\n\tTTL: scalarShape,\n\tEXISTS: scalarShape,\n\tDBSIZE: scalarShape,\n\tDEL: scalarShape,\n\tINCR: scalarShape,\n\tDECR: scalarShape,\n\tSTRLEN: scalarShape,\n\tLLEN: scalarShape,\n\tSCARD: scalarShape,\n\tZCARD: scalarShape,\n\tHLEN: scalarShape,\n\n\tHGET: scalarShape,\n\tHMGET: flatArrayShape,\n\tMGET: flatArrayShape,\n\tKEYS: flatArrayShape,\n\tLRANGE: flatArrayShape,\n\tSMEMBERS: flatArrayShape,\n\n\tHGETALL: pairArrayShape,\n\tHKEYS: flatArrayShape,\n\tHVALS: flatArrayShape,\n\t\"CONFIG GET\": pairArrayShape,\n\n\tZRANGE: flatArrayShape, // becomes pair-shaped only with WITHSCORES; caller can post-process\n\tINFO: infoShape,\n\tXRANGE: xrangeShape,\n\tXREVRANGE: xrangeShape,\n};\n\n/**\n * Shape a Redis reply into ExecuteQueryResult-compatible columns/rows/rowCount.\n * Pass `argv` (already tokenized) so we can detect modifiers like `WITHSCORES`.\n */\nexport function shapeReply(\n\targv: string[],\n\treply: unknown,\n): Pick<ExecuteQueryResult, \"columns\" | \"rows\" | \"rowCount\"> {\n\tif (argv.length === 0) return singleCellFallback(reply);\n\n\tconst cmd = argv[0]?.toUpperCase() ?? \"\";\n\tconst subcmd = argv[1]?.toUpperCase();\n\n\t// Special case: ZRANGE … WITHSCORES → pair shape with {member, score}\n\tif (\n\t\t(cmd === \"ZRANGE\" || cmd === \"ZREVRANGE\" || cmd === \"ZRANGEBYSCORE\") &&\n\t\targv.some((a) => a.toUpperCase() === \"WITHSCORES\")\n\t) {\n\t\treturn zrangeWithScoresShape(reply);\n\t}\n\n\t// Two-word commands like CONFIG GET\n\tif (subcmd) {\n\t\tconst compound = `${cmd} ${subcmd}`;\n\t\tconst shaper = COMMAND_SHAPES[compound];\n\t\tif (shaper) return shaper(reply);\n\t}\n\n\tconst shaper = COMMAND_SHAPES[cmd];\n\tif (shaper) return shaper(reply);\n\n\t// Heuristic for unknown commands\n\tif (typeof reply === \"string\" || typeof reply === \"number\" || reply === null) {\n\t\treturn scalarShape(reply);\n\t}\n\tif (isStringArray(reply)) return flatArrayShape(reply);\n\n\treturn singleCellFallback(reply);\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tCellValue,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateKeySchemaType,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteKeyQuerySchemaType,\n\tDeleteKeyResultSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tKeyActionSchemaType,\n\tKeyDetailsQuerySchemaType,\n\tKeyDetailsResultSchemaType,\n\tKeyRawQuerySchemaType,\n\tKeyRawResultSchemaType,\n\tKeyScanQuerySchemaType,\n\tKeyScanResultSchemaType,\n\tKeyWriteResultSchemaType,\n\tRedisKeyTypeSchemaType,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tTableDataResultSchemaType,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { Redis } from \"ioredis\";\nimport { z } from \"zod\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport {\n\tgetIsolatedRedisClient,\n\tgetRedisClient,\n\tgetRedisDefaultDb,\n} from \"@/adapters/connections.js\";\nimport type { IKeyValueAdapter } from \"@/adapters/key-value-adapter.interface.js\";\nimport { shapeReply, tokenizeCommand } from \"./redis.command-shaper.js\";\n\n// ---------------------------------------------------------------------------\n// Constants and types\n// ---------------------------------------------------------------------------\n\nexport const REDIS_TABLES = [\n\t\"strings\",\n\t\"hashes\",\n\t\"lists\",\n\t\"sets\",\n\t\"zsets\",\n\t\"streams\",\n] as const;\nexport type RedisTable = (typeof REDIS_TABLES)[number];\n\nconst TABLE_TO_REDIS_TYPE: Record<RedisTable, string> = {\n\tstrings: \"string\",\n\thashes: \"hash\",\n\tlists: \"list\",\n\tsets: \"set\",\n\tzsets: \"zset\",\n\tstreams: \"stream\",\n};\n\nconst SCHEMA_MUTATION_MESSAGE =\n\t\"Schema is fixed for Redis tables; this operation is not supported\";\nconst SORT_UNSUPPORTED_MESSAGE = \"Sorting is not supported for Redis tables\";\nconst FILTER_UNSUPPORTED_MESSAGE = \"Filtering is not supported for Redis tables\";\nconst PREV_UNSUPPORTED_MESSAGE =\n\t\"Backward pagination is not supported for Redis tables (SCAN is forward-only)\";\nconst SCAN_ROUND_TRIP_CAP = 10;\nconst COUNT_CACHE_TTL_MS = 30_000;\nconst COUNT_SCAN_CEILING = 10_000;\nconst MAX_STRING_PREVIEW_BYTES = 256 * 1024;\nconst MAX_STRING_FULL_BYTES = 8 * 1024 * 1024;\n\nconst isRedisTable = (name: string): name is RedisTable =>\n\t(REDIS_TABLES as readonly string[]).includes(name);\n\nconst assertRedisTable = (tableName: string): RedisTable => {\n\tif (!isRedisTable(tableName)) {\n\t\tthrow new HTTPException(404, {\n\t\t\tmessage: `Table \"${tableName}\" does not exist in Redis. Valid tables: ${REDIS_TABLES.join(\", \")}`,\n\t\t});\n\t}\n\treturn tableName;\n};\n\nconst parseDbIndex = (db: string): number => {\n\tif (db === \"\") return getRedisDefaultDb();\n\tconst parsed = Number.parseInt(db, 10);\n\tif (!Number.isFinite(parsed) || parsed < 0) {\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: `Invalid Redis database index: \"${db}\". Expected a non-negative integer.`,\n\t\t});\n\t}\n\treturn parsed;\n};\n\ninterface ScanCursorEnvelope {\n\tscanCursor: string;\n\ttype: RedisTable;\n}\n\ninterface KeyBrowserCursorEnvelope {\n\tscanCursor: string;\n\tsearch?: string;\n\texactPattern: boolean;\n\ttype?: RedisKeyTypeSchemaType;\n}\n\ninterface KeyDetailsCursorEnvelope {\n\tkey: string;\n\ttype: RedisKeyTypeSchemaType;\n\tcursor: string;\n\tdirection: \"forward\" | \"backward\";\n}\n\nconst encodeKeyBrowserCursor = (env: KeyBrowserCursorEnvelope): string =>\n\tBuffer.from(JSON.stringify(env)).toString(\"base64url\");\n\nconst decodeKeyBrowserCursor = (cursor: string): KeyBrowserCursorEnvelope | null => {\n\ttry {\n\t\treturn z\n\t\t\t.object({\n\t\t\t\tscanCursor: z.string().regex(/^\\d+$/),\n\t\t\t\tsearch: z.string().max(512).optional(),\n\t\t\t\texactPattern: z.boolean(),\n\t\t\t\ttype: z.enum([\"string\", \"hash\", \"list\", \"set\", \"zset\", \"stream\"]).optional(),\n\t\t\t})\n\t\t\t.parse(JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf-8\")));\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nconst encodeKeyDetailsCursor = (env: KeyDetailsCursorEnvelope): string =>\n\tBuffer.from(JSON.stringify(env)).toString(\"base64url\");\n\nconst decodeKeyDetailsCursor = (cursor: string): KeyDetailsCursorEnvelope | null => {\n\ttry {\n\t\treturn z\n\t\t\t.object({\n\t\t\t\tkey: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.min(1)\n\t\t\t\t\t.max(16 * 1024),\n\t\t\t\ttype: z.enum([\"string\", \"hash\", \"list\", \"set\", \"zset\", \"stream\", \"unknown\"]),\n\t\t\t\tcursor: z.string().min(1).max(512),\n\t\t\t\tdirection: z.enum([\"forward\", \"backward\"]),\n\t\t\t})\n\t\t\t.parse(JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf8\")));\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nconst encodeBinaryValue = (value: Buffer): { base64: string; utf8?: string } => {\n\tconst utf8 = value.toString(\"utf8\");\n\treturn Buffer.from(utf8, \"utf8\").equals(value)\n\t\t? { base64: value.toString(\"base64url\"), utf8 }\n\t\t: { base64: value.toString(\"base64url\") };\n};\n\nconst escapeRedisGlob = (value: string): string => value.replaceAll(/[\\\\*?[\\]]/g, \"\\\\$&\");\n\nconst normalizeRedisKeyType = (value: unknown): RedisKeyTypeSchemaType => {\n\tconst type = Buffer.isBuffer(value) ? value.toString(\"utf8\") : String(value);\n\treturn ([\"string\", \"hash\", \"list\", \"set\", \"zset\", \"stream\"] as const).includes(\n\t\ttype as Exclude<RedisKeyTypeSchemaType, \"unknown\">,\n\t)\n\t\t? (type as RedisKeyTypeSchemaType)\n\t\t: \"unknown\";\n};\n\nconst decodeBinaryValue = (value: string): Buffer => Buffer.from(value, \"base64url\");\nconst decodeKeyParam = (value: string): Buffer =>\n\tvalue === \"-\" ? Buffer.alloc(0) : decodeBinaryValue(value);\n\nconst revisionForDump = (dump: Buffer): string =>\n\tcreateHash(\"sha256\").update(dump).digest(\"base64url\");\n\nconst conflict = (): HTTPException =>\n\tnew HTTPException(409, {\n\t\tmessage: \"This key changed since it was loaded. Reload it or explicitly overwrite.\",\n\t});\n\nconst isUnavailableCommandError = (error: unknown): boolean => {\n\tconst message = error instanceof Error ? error.message : String(error);\n\treturn /(NOPERM|unknown command|not allowed|unsupported)/i.test(message);\n};\n\nconst assertKeyType = (\n\tactual: RedisKeyTypeSchemaType,\n\texpected: Exclude<RedisKeyTypeSchemaType, \"unknown\">,\n): void => {\n\tif (actual !== expected) {\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: `This operation requires a ${expected} key, but the key is ${actual}.`,\n\t\t});\n\t}\n};\n\nconst assertTransactionSucceeded = (result: unknown): void => {\n\tif (result === null) throw conflict();\n\tif (!Array.isArray(result)) return;\n\tconst failed = result.find(\n\t\t(entry): entry is [Error, unknown] => Array.isArray(entry) && entry[0] instanceof Error,\n\t);\n\tif (failed) {\n\t\tthrow new HTTPException(400, { message: failed[0].message });\n\t}\n};\n\nconst encodeScanCursor = (env: ScanCursorEnvelope): string =>\n\tBuffer.from(JSON.stringify(env)).toString(\"base64url\");\n\nconst decodeScanCursor = (cursor: string): ScanCursorEnvelope | null => {\n\ttry {\n\t\treturn JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf-8\"));\n\t} catch {\n\t\treturn null;\n\t}\n};\n\ninterface CountCacheEntry {\n\ttimestamp: number;\n\tcounts: Record<RedisTable, number>;\n}\n\n// ---------------------------------------------------------------------------\n// Per-type column definitions\n// ---------------------------------------------------------------------------\n\nconst columnInfo = (\n\toverrides: Partial<ColumnInfoSchemaType> &\n\t\tPick<ColumnInfoSchemaType, \"columnName\" | \"dataType\">,\n): ColumnInfoSchemaType => ({\n\tcolumnName: overrides.columnName,\n\tdataType: overrides.dataType,\n\tdataTypeLabel:\n\t\toverrides.dataTypeLabel ??\n\t\t(overrides.dataType === \"number\"\n\t\t\t? \"int\"\n\t\t\t: overrides.dataType === \"json\"\n\t\t\t\t? \"json\"\n\t\t\t\t: overrides.dataType === \"array\"\n\t\t\t\t\t? \"array\"\n\t\t\t\t\t: \"text\"),\n\tisNullable: overrides.isNullable ?? false,\n\tcolumnDefault: overrides.columnDefault ?? null,\n\tisPrimaryKey: overrides.isPrimaryKey ?? false,\n\tisForeignKey: false,\n\treferencedTable: null,\n\treferencedColumn: null,\n\tenumValues: null,\n});\n\nconst KEY_COL = columnInfo({ columnName: \"key\", dataType: \"text\", isPrimaryKey: true });\nconst TTL_COL = columnInfo({ columnName: \"ttl\", dataType: \"number\", isNullable: true });\n\nconst TABLE_COLUMNS: Record<RedisTable, ColumnInfoSchemaType[]> = {\n\tstrings: [\n\t\tKEY_COL,\n\t\tcolumnInfo({ columnName: \"value\", dataType: \"text\", isNullable: true }),\n\t\tTTL_COL,\n\t],\n\thashes: [KEY_COL, columnInfo({ columnName: \"value\", dataType: \"json\" }), TTL_COL],\n\tlists: [KEY_COL, columnInfo({ columnName: \"value\", dataType: \"array\" }), TTL_COL],\n\tsets: [KEY_COL, columnInfo({ columnName: \"value\", dataType: \"array\" }), TTL_COL],\n\tzsets: [KEY_COL, columnInfo({ columnName: \"value\", dataType: \"json\" }), TTL_COL],\n\tstreams: [\n\t\tKEY_COL,\n\t\tcolumnInfo({ columnName: \"length\", dataType: \"number\" }),\n\t\tcolumnInfo({ columnName: \"first-id\", dataType: \"text\", isNullable: true }),\n\t\tcolumnInfo({ columnName: \"last-id\", dataType: \"text\", isNullable: true }),\n\t\tTTL_COL,\n\t],\n};\n\nconst SCHEMA_DESCRIPTIONS: Record<RedisTable, string> = {\n\tstrings: `-- Redis string keys\n-- Columns: key (text, PK), value (text), ttl (number, seconds; -1 = no TTL, -2 = missing)\n-- Backed by: GET / SET / EXPIRE`,\n\thashes: `-- Redis hash keys\n-- Columns: key (text, PK), value (json: {field: value, ...}), ttl (number)\n-- Backed by: HGETALL / HSET / EXPIRE`,\n\tlists: `-- Redis list keys\n-- Columns: key (text, PK), value (array of elements), ttl (number)\n-- Backed by: LRANGE / RPUSH / EXPIRE`,\n\tsets: `-- Redis set keys\n-- Columns: key (text, PK), value (array of members), ttl (number)\n-- Backed by: SMEMBERS / SADD / EXPIRE`,\n\tzsets: `-- Redis sorted set keys\n-- Columns: key (text, PK), value (json: [{member, score}, ...]), ttl (number)\n-- Backed by: ZRANGE WITHSCORES / ZADD / EXPIRE`,\n\tstreams: `-- Redis stream keys\n-- Columns: key (text, PK), length (number), first-id (text), last-id (text), ttl (number)\n-- Backed by: XINFO STREAM / XADD / EXPIRE (read-only — streams are append-only)`,\n};\n\n// ---------------------------------------------------------------------------\n// RedisAdapter\n// ---------------------------------------------------------------------------\n\nexport class RedisAdapter extends BaseAdapter implements IKeyValueAdapter {\n\tprivate countCache: Map<number, CountCacheEntry> = new Map();\n\n\t// -----------------------------------------------------------------------\n\t// Abstract stubs — Redis does not use SQL\n\t// -----------------------------------------------------------------------\n\n\tprotected runQuery<T>(): Promise<T> {\n\t\tthrow new HTTPException(501, { message: \"runQuery is not supported for Redis\" });\n\t}\n\n\tprotected buildTableDataQuery(_params: GetTableDataParams): QueryBundle {\n\t\tthrow new HTTPException(501, {\n\t\t\tmessage: \"buildTableDataQuery is not supported for Redis\",\n\t\t});\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn rawRows.map((row) => this.normalizeRow(row as Record<string, unknown>));\n\t}\n\n\tprotected buildCursors(): { nextCursor: string | null; prevCursor: string | null } {\n\t\treturn { nextCursor: null, prevCursor: null };\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn name;\n\t}\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\tswitch (nativeType.toLowerCase()) {\n\t\t\tcase \"string\":\n\t\t\t\treturn \"text\";\n\t\t\tcase \"hash\":\n\t\t\t\treturn \"json\";\n\t\t\tcase \"list\":\n\t\t\tcase \"set\":\n\t\t\t\treturn \"array\";\n\t\t\tcase \"zset\":\n\t\t\tcase \"stream\":\n\t\t\t\treturn \"json\";\n\t\t\tcase \"integer\":\n\t\t\tcase \"number\":\n\t\t\tcase \"ttl\":\n\t\t\t\treturn \"number\";\n\t\t\tdefault:\n\t\t\t\treturn \"text\";\n\t\t}\n\t}\n\n\tmapFromUniversalType(_universalType: string): string {\n\t\treturn \"string\";\n\t}\n\n\tasync scanKeys(params: KeyScanQuerySchemaType): Promise<KeyScanResultSchemaType> {\n\t\ttry {\n\t\t\tconst { db, limit, search, exactPattern, type, cursor } = params;\n\t\t\tconst dbIndex = parseDbIndex(db);\n\t\t\tconst client = await getRedisClient(dbIndex);\n\t\t\tlet scanCursor = \"0\";\n\n\t\t\tif (cursor) {\n\t\t\t\tconst decoded = decodeKeyBrowserCursor(cursor);\n\t\t\t\tif (\n\t\t\t\t\t!decoded ||\n\t\t\t\t\tdecoded.search !== search ||\n\t\t\t\t\tdecoded.exactPattern !== exactPattern ||\n\t\t\t\t\tdecoded.type !== type\n\t\t\t\t) {\n\t\t\t\t\tthrow new HTTPException(400, { message: \"Invalid or stale key scan cursor\" });\n\t\t\t\t}\n\t\t\t\tscanCursor = decoded.scanCursor;\n\t\t\t}\n\n\t\t\tconst pattern = search ? (exactPattern ? search : `*${escapeRedisGlob(search)}*`) : \"*\";\n\t\t\tconst scanArgs: Array<string | number> = [scanCursor, \"MATCH\", pattern, \"COUNT\", limit];\n\t\t\tif (type) scanArgs.push(\"TYPE\", type);\n\n\t\t\tconst [nextRaw, pageKeys] = (await (\n\t\t\t\tclient.scanBuffer as unknown as (\n\t\t\t\t\t...args: Array<string | number>\n\t\t\t\t) => Promise<[Buffer | string, Buffer[]]>\n\t\t\t)(...scanArgs)) as [Buffer | string, Buffer[]];\n\t\t\tconst nextScanCursor = Buffer.isBuffer(nextRaw) ? nextRaw.toString(\"utf8\") : nextRaw;\n\t\t\tconst pipeline = client.pipeline();\n\t\t\tfor (const key of pageKeys) {\n\t\t\t\tpipeline.call(\"TYPE\", key);\n\t\t\t\tpipeline.pttl(key);\n\t\t\t\tpipeline.call(\"MEMORY\", \"USAGE\", key);\n\t\t\t}\n\t\t\tconst metadata = (await pipeline.exec()) ?? [];\n\n\t\t\treturn {\n\t\t\t\tkeys: pageKeys.map((key, index) => {\n\t\t\t\t\tconst offset = index * 3;\n\t\t\t\t\tconst memory = metadata[offset + 2]?.[1];\n\t\t\t\t\treturn {\n\t\t\t\t\t\tkey: encodeBinaryValue(key),\n\t\t\t\t\t\ttype: normalizeRedisKeyType(metadata[offset]?.[1]),\n\t\t\t\t\t\tttlMs: Number(metadata[offset + 1]?.[1] ?? -2),\n\t\t\t\t\t\tmemoryBytes: memory === null || memory === undefined ? null : Number(memory),\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t\tnextCursor:\n\t\t\t\t\tnextScanCursor === \"0\"\n\t\t\t\t\t\t? null\n\t\t\t\t\t\t: encodeKeyBrowserCursor({\n\t\t\t\t\t\t\t\tscanCursor: nextScanCursor,\n\t\t\t\t\t\t\t\tsearch,\n\t\t\t\t\t\t\t\texactPattern,\n\t\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t}),\n\t\t\t\thasMore: nextScanCursor !== \"0\",\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getKeyDetails(\n\t\tparams: KeyDetailsQuerySchemaType & { key: string },\n\t): Promise<KeyDetailsResultSchemaType> {\n\t\ttry {\n\t\t\tconst { db, key: encodedKey, cursor, limit, full, direction } = params;\n\t\t\tconst key = decodeKeyParam(encodedKey);\n\t\t\tconst client = await getRedisClient(parseDbIndex(db));\n\t\t\tconst [typeRaw, ttlMs, memoryRaw, dumpRaw] = await Promise.all([\n\t\t\t\tclient.callBuffer(\"TYPE\", key),\n\t\t\t\tclient.pttl(key),\n\t\t\t\tclient.call(\"MEMORY\", \"USAGE\", key).catch(() => null),\n\t\t\t\tclient.callBuffer(\"DUMP\", key),\n\t\t\t]);\n\t\t\tconst dump = dumpRaw as Buffer | null;\n\t\t\tif (!dump) {\n\t\t\t\tthrow new HTTPException(404, { message: \"Redis key no longer exists\" });\n\t\t\t}\n\n\t\t\tconst type = normalizeRedisKeyType(typeRaw);\n\t\t\tconst summary = {\n\t\t\t\tkey: encodeBinaryValue(key),\n\t\t\t\ttype,\n\t\t\t\tttlMs: Number(ttlMs),\n\t\t\t\tmemoryBytes: memoryRaw === null ? null : Number(memoryRaw),\n\t\t\t\trevision: revisionForDump(dump),\n\t\t\t};\n\t\t\tconst decodedCursor = cursor ? decodeKeyDetailsCursor(cursor) : null;\n\t\t\tif (\n\t\t\t\tcursor &&\n\t\t\t\t(!decodedCursor ||\n\t\t\t\t\tdecodedCursor.key !== encodedKey ||\n\t\t\t\t\tdecodedCursor.type !== type ||\n\t\t\t\t\tdecodedCursor.direction !== direction)\n\t\t\t) {\n\t\t\t\tthrow new HTTPException(400, { message: \"Invalid or stale key details cursor\" });\n\t\t\t}\n\n\t\t\tif (type === \"string\") {\n\t\t\t\tconst length = await client.strlen(key);\n\t\t\t\tconst readLimit = full ? MAX_STRING_FULL_BYTES : MAX_STRING_PREVIEW_BYTES;\n\t\t\t\tconst value = await client.getrangeBuffer(key, 0, readLimit - 1);\n\t\t\t\treturn {\n\t\t\t\t\t...summary,\n\t\t\t\t\tlength,\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\tkind: \"string\",\n\t\t\t\t\t\tvalue: encodeBinaryValue(value),\n\t\t\t\t\t\ttruncated: length > readLimit,\n\t\t\t\t\t},\n\t\t\t\t\tnextCursor: null,\n\t\t\t\t\thasMore: false,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (type === \"hash\") {\n\t\t\t\tconst [length, scanResult] = await Promise.all([\n\t\t\t\t\tclient.hlen(key),\n\t\t\t\t\tclient.hscanBuffer(key, decodedCursor?.cursor ?? \"0\", \"COUNT\", String(limit)),\n\t\t\t\t]);\n\t\t\t\tconst [nextRaw, values] = scanResult as [Buffer | string, Buffer[]];\n\t\t\t\tconst next = Buffer.isBuffer(nextRaw) ? nextRaw.toString(\"utf8\") : nextRaw;\n\t\t\t\tconst entries = [];\n\t\t\t\tfor (let index = 0; index < values.length; index += 2) {\n\t\t\t\t\tentries.push({\n\t\t\t\t\t\tfield: encodeBinaryValue(values[index]),\n\t\t\t\t\t\tvalue: encodeBinaryValue(values[index + 1]),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\t...summary,\n\t\t\t\t\tlength,\n\t\t\t\t\tvalue: { kind: \"hash\", entries },\n\t\t\t\t\tnextCursor:\n\t\t\t\t\t\tnext === \"0\"\n\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t: encodeKeyDetailsCursor({ key: encodedKey, type, cursor: next, direction }),\n\t\t\t\t\thasMore: next !== \"0\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (type === \"list\") {\n\t\t\t\tconst offset = Number.parseInt(decodedCursor?.cursor ?? \"0\", 10);\n\t\t\t\tconst length = await client.llen(key);\n\t\t\t\tconst values = await client.lrangeBuffer(key, offset, offset + limit - 1);\n\t\t\t\tconst nextOffset = offset + values.length;\n\t\t\t\tconst hasMore = nextOffset < length;\n\t\t\t\treturn {\n\t\t\t\t\t...summary,\n\t\t\t\t\tlength,\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\tkind: \"list\",\n\t\t\t\t\t\tentries: values.map((value, index) => ({\n\t\t\t\t\t\t\tindex: offset + index,\n\t\t\t\t\t\t\tvalue: encodeBinaryValue(value),\n\t\t\t\t\t\t})),\n\t\t\t\t\t},\n\t\t\t\t\tnextCursor: hasMore\n\t\t\t\t\t\t? encodeKeyDetailsCursor({\n\t\t\t\t\t\t\t\tkey: encodedKey,\n\t\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t\tcursor: String(nextOffset),\n\t\t\t\t\t\t\t\tdirection,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: null,\n\t\t\t\t\thasMore,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (type === \"set\") {\n\t\t\t\tconst [length, scanResult] = await Promise.all([\n\t\t\t\t\tclient.scard(key),\n\t\t\t\t\tclient.sscanBuffer(key, decodedCursor?.cursor ?? \"0\", \"COUNT\", String(limit)),\n\t\t\t\t]);\n\t\t\t\tconst [nextRaw, members] = scanResult as [Buffer | string, Buffer[]];\n\t\t\t\tconst next = Buffer.isBuffer(nextRaw) ? nextRaw.toString(\"utf8\") : nextRaw;\n\t\t\t\treturn {\n\t\t\t\t\t...summary,\n\t\t\t\t\tlength,\n\t\t\t\t\tvalue: { kind: \"set\", members: members.map(encodeBinaryValue) },\n\t\t\t\t\tnextCursor:\n\t\t\t\t\t\tnext === \"0\"\n\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t: encodeKeyDetailsCursor({ key: encodedKey, type, cursor: next, direction }),\n\t\t\t\t\thasMore: next !== \"0\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (type === \"zset\") {\n\t\t\t\tconst [length, scanResult] = await Promise.all([\n\t\t\t\t\tclient.zcard(key),\n\t\t\t\t\tclient.zscanBuffer(key, decodedCursor?.cursor ?? \"0\", \"COUNT\", String(limit)),\n\t\t\t\t]);\n\t\t\t\tconst [nextRaw, values] = scanResult as [Buffer | string, Buffer[]];\n\t\t\t\tconst next = Buffer.isBuffer(nextRaw) ? nextRaw.toString(\"utf8\") : nextRaw;\n\t\t\t\tconst entries = [];\n\t\t\t\tfor (let index = 0; index < values.length; index += 2) {\n\t\t\t\t\tentries.push({\n\t\t\t\t\t\tmember: encodeBinaryValue(values[index]),\n\t\t\t\t\t\tscore: ((): number | \"inf\" | \"-inf\" => {\n\t\t\t\t\t\t\tconst score = values[index + 1].toString(\"utf8\");\n\t\t\t\t\t\t\tif (score === \"inf\") return \"inf\";\n\t\t\t\t\t\t\tif (score === \"-inf\") return \"-inf\";\n\t\t\t\t\t\t\treturn Number(score);\n\t\t\t\t\t\t})(),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\t...summary,\n\t\t\t\t\tlength,\n\t\t\t\t\tvalue: { kind: \"zset\", entries },\n\t\t\t\t\tnextCursor:\n\t\t\t\t\t\tnext === \"0\"\n\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t: encodeKeyDetailsCursor({ key: encodedKey, type, cursor: next, direction }),\n\t\t\t\t\thasMore: next !== \"0\",\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (type === \"stream\") {\n\t\t\t\tconst boundary = decodedCursor?.cursor ?? (direction === \"forward\" ? \"-\" : \"+\");\n\t\t\t\tconst [length, rawEntries] = await Promise.all([\n\t\t\t\t\tclient.xlen(key),\n\t\t\t\t\tdirection === \"forward\"\n\t\t\t\t\t\t? client.xrangeBuffer(key, boundary, \"+\", \"COUNT\", limit + 1)\n\t\t\t\t\t\t: client.xrevrangeBuffer(key, boundary, \"-\", \"COUNT\", limit + 1),\n\t\t\t\t]);\n\t\t\t\tconst hasMore = rawEntries.length > limit;\n\t\t\t\tconst page = rawEntries.slice(0, limit) as Array<[Buffer, Buffer[]]>;\n\t\t\t\tconst entries = page.map(([id, values]) => {\n\t\t\t\t\tconst fields = [];\n\t\t\t\t\tfor (let index = 0; index < values.length; index += 2) {\n\t\t\t\t\t\tfields.push({\n\t\t\t\t\t\t\tfield: encodeBinaryValue(values[index]),\n\t\t\t\t\t\t\tvalue: encodeBinaryValue(values[index + 1]),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn { id: id.toString(\"utf8\"), fields };\n\t\t\t\t});\n\t\t\t\tconst lastId = entries.at(-1)?.id;\n\t\t\t\treturn {\n\t\t\t\t\t...summary,\n\t\t\t\t\tlength,\n\t\t\t\t\tvalue: { kind: \"stream\", entries },\n\t\t\t\t\tnextCursor:\n\t\t\t\t\t\thasMore && lastId\n\t\t\t\t\t\t\t? encodeKeyDetailsCursor({\n\t\t\t\t\t\t\t\t\tkey: encodedKey,\n\t\t\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t\t\tcursor: `(${lastId}`,\n\t\t\t\t\t\t\t\t\tdirection,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\thasMore,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...summary,\n\t\t\t\tlength: null,\n\t\t\t\tvalue: { kind: \"unknown\" },\n\t\t\t\tnextCursor: null,\n\t\t\t\thasMore: false,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getStringChunk(\n\t\tparams: KeyRawQuerySchemaType & { key: string },\n\t): Promise<KeyRawResultSchemaType> {\n\t\ttry {\n\t\t\tconst client = await getRedisClient(parseDbIndex(params.db));\n\t\t\tconst key = decodeKeyParam(params.key);\n\t\t\tconst type = normalizeRedisKeyType(await client.callBuffer(\"TYPE\", key));\n\t\t\tif (type === \"unknown\") {\n\t\t\t\tthrow new HTTPException(404, { message: \"Redis key no longer exists\" });\n\t\t\t}\n\t\t\tassertKeyType(type, \"string\");\n\t\t\tif (params.expectedRevision) {\n\t\t\t\tconst dump = (await client.callBuffer(\"DUMP\", key)) as Buffer | null;\n\t\t\t\tif (!dump || revisionForDump(dump) !== params.expectedRevision) throw conflict();\n\t\t\t}\n\t\t\tconst length = await client.strlen(key);\n\t\t\tconst chunk = await client.getrangeBuffer(\n\t\t\t\tkey,\n\t\t\t\tparams.offset,\n\t\t\t\tparams.offset + params.limit - 1,\n\t\t\t);\n\t\t\tconst next = params.offset + chunk.length;\n\t\t\treturn {\n\t\t\t\tchunk: encodeBinaryValue(chunk),\n\t\t\t\tlength,\n\t\t\t\tnextOffset: next < length ? next : null,\n\t\t\t\thasMore: next < length,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync createKey(\n\t\tparams: CreateKeySchemaType & { db: string },\n\t): Promise<KeyWriteResultSchemaType> {\n\t\tlet client: Redis | null = null;\n\t\ttry {\n\t\t\tclient = await getIsolatedRedisClient(parseDbIndex(params.db));\n\t\t\tconst key = decodeBinaryValue(params.key.base64);\n\t\t\tawait client.watch(key);\n\t\t\tif ((await client.exists(key)) !== 0) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: \"A Redis key with this name already exists.\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (params.type !== params.value.kind) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: \"The initial value does not match the selected Redis key type.\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst transaction = client.multi();\n\t\t\tswitch (params.value.kind) {\n\t\t\t\tcase \"string\":\n\t\t\t\t\ttransaction.set(key, decodeBinaryValue(params.value.value.base64));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hash\":\n\t\t\t\t\ttransaction.hset(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\t...params.value.entries.flatMap(({ field, value }) => [\n\t\t\t\t\t\t\tdecodeBinaryValue(field.base64),\n\t\t\t\t\t\t\tdecodeBinaryValue(value.base64),\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"list\":\n\t\t\t\t\ttransaction.rpush(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\t...params.value.entries.map((value) => decodeBinaryValue(value.base64)),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"set\":\n\t\t\t\t\ttransaction.sadd(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\t...params.value.members.map((member) => decodeBinaryValue(member.base64)),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"zset\":\n\t\t\t\t\ttransaction.zadd(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\t...params.value.entries.flatMap(({ member, score }) => [\n\t\t\t\t\t\t\tscore,\n\t\t\t\t\t\t\tdecodeBinaryValue(member.base64),\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"stream\":\n\t\t\t\t\ttransaction.xadd(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tparams.value.id,\n\t\t\t\t\t\t...params.value.fields.flatMap(({ field, value }) => [\n\t\t\t\t\t\t\tdecodeBinaryValue(field.base64),\n\t\t\t\t\t\t\tdecodeBinaryValue(value.base64),\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (params.ttlMs !== null) transaction.pexpire(key, params.ttlMs);\n\t\t\tassertTransactionSucceeded(await transaction.exec());\n\n\t\t\tconst dump = (await client.callBuffer(\"DUMP\", key)) as Buffer | null;\n\t\t\tif (!dump) throw conflict();\n\t\t\treturn {\n\t\t\t\tkey: encodeBinaryValue(key),\n\t\t\t\trevision: revisionForDump(dump),\n\t\t\t\tdeleted: false,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t} finally {\n\t\t\tif (client) await client.quit().catch(() => client?.disconnect());\n\t\t}\n\t}\n\n\tasync applyKeyAction(\n\t\tparams: KeyActionSchemaType & { db: string; key: string },\n\t): Promise<KeyWriteResultSchemaType> {\n\t\tlet client: Redis | null = null;\n\t\ttry {\n\t\t\tclient = await getIsolatedRedisClient(parseDbIndex(params.db));\n\t\t\tconst key = decodeKeyParam(params.key);\n\t\t\tconst newKey =\n\t\t\t\tparams.operation.action === \"rename\"\n\t\t\t\t\t? decodeBinaryValue(params.operation.newKey.base64)\n\t\t\t\t\t: null;\n\t\t\tif (newKey && !newKey.equals(key)) await client.watch(key, newKey);\n\t\t\telse await client.watch(key);\n\n\t\t\tconst [dumpRaw, typeRaw, ttlMs] = await Promise.all([\n\t\t\t\tclient.callBuffer(\"DUMP\", key),\n\t\t\t\tclient.callBuffer(\"TYPE\", key),\n\t\t\t\tclient.pttl(key),\n\t\t\t]);\n\t\t\tconst dump = dumpRaw as Buffer | null;\n\t\t\tif (!dump) throw new HTTPException(404, { message: \"Redis key no longer exists\" });\n\t\t\tif (!params.force && revisionForDump(dump) !== params.expectedRevision) throw conflict();\n\t\t\tconst type = normalizeRedisKeyType(typeRaw);\n\t\t\tif (newKey && !newKey.equals(key) && (await client.exists(newKey)) !== 0) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: \"A Redis key with the new name already exists.\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst transaction = client.multi();\n\t\t\tswitch (params.operation.action) {\n\t\t\t\tcase \"rename\":\n\t\t\t\t\tif (!newKey || newKey.equals(key)) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tkey: encodeBinaryValue(key),\n\t\t\t\t\t\t\trevision: revisionForDump(dump),\n\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\ttransaction.rename(key, newKey);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"setTtl\":\n\t\t\t\t\tif (params.operation.ttlMs === null) transaction.persist(key);\n\t\t\t\t\telse transaction.pexpire(key, params.operation.ttlMs);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"setString\":\n\t\t\t\t\tassertKeyType(type, \"string\");\n\t\t\t\t\ttransaction.set(key, decodeBinaryValue(params.operation.value.base64));\n\t\t\t\t\tif (ttlMs > 0) transaction.pexpire(key, ttlMs);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"upsertHash\":\n\t\t\t\t\tassertKeyType(type, \"hash\");\n\t\t\t\t\ttransaction.hset(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tdecodeBinaryValue(params.operation.field.base64),\n\t\t\t\t\t\tdecodeBinaryValue(params.operation.value.base64),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"deleteHash\":\n\t\t\t\t\tassertKeyType(type, \"hash\");\n\t\t\t\t\ttransaction.hdel(key, decodeBinaryValue(params.operation.field.base64));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"pushList\":\n\t\t\t\t\tassertKeyType(type, \"list\");\n\t\t\t\t\tif (params.operation.side === \"left\") {\n\t\t\t\t\t\ttransaction.lpush(key, decodeBinaryValue(params.operation.value.base64));\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttransaction.rpush(key, decodeBinaryValue(params.operation.value.base64));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"setList\":\n\t\t\t\t\tassertKeyType(type, \"list\");\n\t\t\t\t\ttransaction.lset(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tparams.operation.index,\n\t\t\t\t\t\tdecodeBinaryValue(params.operation.value.base64),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"deleteList\": {\n\t\t\t\t\tassertKeyType(type, \"list\");\n\t\t\t\t\tconst marker = Buffer.concat([\n\t\t\t\t\t\tBuffer.from(\"db-studio:list-delete:\"),\n\t\t\t\t\t\trandomBytes(32),\n\t\t\t\t\t]);\n\t\t\t\t\ttransaction.lset(key, params.operation.index, marker);\n\t\t\t\t\ttransaction.lrem(key, 1, marker);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"addSet\":\n\t\t\t\t\tassertKeyType(type, \"set\");\n\t\t\t\t\ttransaction.sadd(key, decodeBinaryValue(params.operation.member.base64));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"removeSet\":\n\t\t\t\t\tassertKeyType(type, \"set\");\n\t\t\t\t\ttransaction.srem(key, decodeBinaryValue(params.operation.member.base64));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"upsertZset\":\n\t\t\t\t\tassertKeyType(type, \"zset\");\n\t\t\t\t\ttransaction.zadd(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tparams.operation.score,\n\t\t\t\t\t\tdecodeBinaryValue(params.operation.member.base64),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"removeZset\":\n\t\t\t\t\tassertKeyType(type, \"zset\");\n\t\t\t\t\ttransaction.zrem(key, decodeBinaryValue(params.operation.member.base64));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"appendStream\":\n\t\t\t\t\tassertKeyType(type, \"stream\");\n\t\t\t\t\ttransaction.xadd(\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tparams.operation.id,\n\t\t\t\t\t\t...params.operation.fields.flatMap(({ field, value }) => [\n\t\t\t\t\t\t\tdecodeBinaryValue(field.base64),\n\t\t\t\t\t\t\tdecodeBinaryValue(value.base64),\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"deleteStream\":\n\t\t\t\t\tassertKeyType(type, \"stream\");\n\t\t\t\t\ttransaction.xdel(key, params.operation.id);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tassertTransactionSucceeded(await transaction.exec());\n\t\t\tconst resultKey = newKey && !newKey.equals(key) ? newKey : key;\n\t\t\tconst nextDump = (await client.callBuffer(\"DUMP\", resultKey)) as Buffer | null;\n\t\t\treturn {\n\t\t\t\tkey: encodeBinaryValue(resultKey),\n\t\t\t\trevision: nextDump ? revisionForDump(nextDump) : null,\n\t\t\t\tdeleted: nextDump === null,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t} finally {\n\t\t\tif (client) await client.quit().catch(() => client?.disconnect());\n\t\t}\n\t}\n\n\tasync deleteKey(\n\t\tparams: DeleteKeyQuerySchemaType & { key: string },\n\t): Promise<DeleteKeyResultSchemaType> {\n\t\tlet client: Redis | null = null;\n\t\ttry {\n\t\t\tclient = await getIsolatedRedisClient(parseDbIndex(params.db));\n\t\t\tconst key = decodeKeyParam(params.key);\n\t\t\tawait client.watch(key);\n\t\t\tconst dump = (await client.callBuffer(\"DUMP\", key)) as Buffer | null;\n\t\t\tif (!dump) throw new HTTPException(404, { message: \"Redis key no longer exists\" });\n\t\t\tif (!params.force && revisionForDump(dump) !== params.expectedRevision) throw conflict();\n\t\t\tconst transaction = client.multi().del(key);\n\t\t\tassertTransactionSucceeded(await transaction.exec());\n\t\t\treturn { deleted: true };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t} finally {\n\t\t\tif (client) await client.quit().catch(() => client?.disconnect());\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Database operations\n\t// -----------------------------------------------------------------------\n\n\toverride async getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst client = await getRedisClient(getRedisDefaultDb());\n\t\t\tlet total = 1;\n\t\t\tlet supportsLogicalDatabases = false;\n\t\t\tlet configReply: unknown = null;\n\t\t\ttry {\n\t\t\t\tconfigReply = await client.call(\"CONFIG\", \"GET\", \"databases\");\n\t\t\t} catch (error) {\n\t\t\t\tif (!isUnavailableCommandError(error)) throw error;\n\t\t\t}\n\t\t\tif (Array.isArray(configReply) && configReply.length >= 2) {\n\t\t\t\tconst parsed = Number.parseInt(String(configReply[1]), 10);\n\t\t\t\tif (Number.isFinite(parsed) && parsed > 0) {\n\t\t\t\t\ttotal = parsed;\n\t\t\t\t\tsupportsLogicalDatabases = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet keyspaceInfo = \"\";\n\t\t\ttry {\n\t\t\t\tkeyspaceInfo = await client.info(\"keyspace\");\n\t\t\t} catch (error) {\n\t\t\t\tif (!isUnavailableCommandError(error)) throw error;\n\t\t\t}\n\t\t\tconst keysPerDb = parseKeyspaceInfo(keyspaceInfo);\n\n\t\t\tconst databases = supportsLogicalDatabases\n\t\t\t\t? Array.from({ length: total }, (_, index) => index)\n\t\t\t\t: [getRedisDefaultDb()];\n\t\t\treturn databases.map((index) => ({\n\t\t\t\tname: String(index),\n\t\t\t\tsize: `${keysPerDb.get(index) ?? 0} keys`,\n\t\t\t\towner: \"n/a\",\n\t\t\t\tencoding: \"n/a\",\n\t\t\t}));\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\treturn { db: String(getRedisDefaultDb()) };\n\t}\n\n\toverride async getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\ttry {\n\t\t\tconst client = await getRedisClient(getRedisDefaultDb());\n\t\t\tconst [serverInfo, clientsInfo] = await Promise.all([\n\t\t\t\tclient.info(\"server\"),\n\t\t\t\tclient.info(\"clients\"),\n\t\t\t]);\n\t\t\tconst server = parseInfoSection(serverInfo);\n\t\t\tconst clients = parseInfoSection(clientsInfo);\n\n\t\t\tlet maxclients = Number.parseInt(clients.maxclients ?? \"0\", 10);\n\t\t\tif (!Number.isFinite(maxclients) || maxclients === 0) {\n\t\t\t\tconst reply = await client.call(\"CONFIG\", \"GET\", \"maxclients\").catch((error) => {\n\t\t\t\t\tif (!isUnavailableCommandError(error)) throw error;\n\t\t\t\t\treturn null;\n\t\t\t\t});\n\t\t\t\tif (Array.isArray(reply) && reply.length >= 2) {\n\t\t\t\t\tmaxclients = Number.parseInt(String(reply[1]), 10) || 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst opts = client.options;\n\t\t\treturn {\n\t\t\t\thost: opts.host ?? null,\n\t\t\t\tport: opts.port ?? null,\n\t\t\t\tuser: opts.username || \"default\",\n\t\t\t\tdatabase: String(opts.db ?? getRedisDefaultDb()),\n\t\t\t\tversion: server.redis_version ?? \"unknown\",\n\t\t\t\tactive_connections: Number.parseInt(clients.connected_clients ?? \"0\", 10) || 0,\n\t\t\t\tmax_connections: maxclients || 0,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Table operations\n\t// -----------------------------------------------------------------------\n\n\toverride async getTablesList(db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst dbIndex = parseDbIndex(db);\n\t\t\tconst counts = await this.getCachedCounts(dbIndex);\n\t\t\treturn REDIS_TABLES.map((tableName) => ({\n\t\t\t\ttableName,\n\t\t\t\trowCount: counts[tableName],\n\t\t\t}));\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async createTable(): Promise<void> {\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: \"Redis tables are fixed; cannot create new ones\",\n\t\t});\n\t}\n\n\toverride async deleteTable(_params: DeleteTableParams): Promise<DeleteTableResult> {\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage:\n\t\t\t\t\"Bulk deletion of Redis tables is not supported. Use FLUSHDB from the query runner to clear the entire logical database.\",\n\t\t});\n\t}\n\n\toverride async renameTable(_params: RenameTableParamsSchemaType): Promise<void> {\n\t\tthrow new HTTPException(400, { message: SCHEMA_MUTATION_MESSAGE });\n\t}\n\n\toverride async getTableSchema({\n\t\ttableName,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\tconst table = assertRedisTable(tableName);\n\t\treturn SCHEMA_DESCRIPTIONS[table];\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Column operations — all schema mutations throw 400\n\t// -----------------------------------------------------------------------\n\n\toverride async getTableColumns({\n\t\ttableName,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\tconst table = assertRedisTable(tableName);\n\t\treturn TABLE_COLUMNS[table];\n\t}\n\n\toverride async addColumn(_params: AddColumnParamsSchemaType): Promise<void> {\n\t\tthrow new HTTPException(400, { message: SCHEMA_MUTATION_MESSAGE });\n\t}\n\n\toverride async deleteColumn(\n\t\t_params: DeleteColumnParamsSchemaType,\n\t): Promise<{ deletedCount: number }> {\n\t\tthrow new HTTPException(400, { message: SCHEMA_MUTATION_MESSAGE });\n\t}\n\n\toverride async alterColumn(_params: AlterColumnParamsSchemaType): Promise<void> {\n\t\tthrow new HTTPException(400, { message: SCHEMA_MUTATION_MESSAGE });\n\t}\n\n\toverride async renameColumn(_params: RenameColumnParamsSchemaType): Promise<void> {\n\t\tthrow new HTTPException(400, { message: SCHEMA_MUTATION_MESSAGE });\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// getTableData — forward-only SCAN with envelope cursor\n\t// -----------------------------------------------------------------------\n\n\toverride async getTableData(params: GetTableDataParams): Promise<TableDataResultSchemaType> {\n\t\ttry {\n\t\t\tconst { tableName, db, cursor, limit = 50, direction = \"asc\", sort, filters } = params;\n\n\t\t\tif (direction === \"desc\") {\n\t\t\t\tthrow new HTTPException(400, { message: PREV_UNSUPPORTED_MESSAGE });\n\t\t\t}\n\t\t\tif (sort && (typeof sort === \"string\" ? sort.length > 0 : sort.length > 0)) {\n\t\t\t\tthrow new HTTPException(400, { message: SORT_UNSUPPORTED_MESSAGE });\n\t\t\t}\n\t\t\tif (filters && filters.length > 0) {\n\t\t\t\tthrow new HTTPException(400, { message: FILTER_UNSUPPORTED_MESSAGE });\n\t\t\t}\n\n\t\t\tconst table = assertRedisTable(tableName);\n\t\t\tconst redisType = TABLE_TO_REDIS_TYPE[table];\n\t\t\tconst dbIndex = parseDbIndex(db);\n\t\t\tconst client = await getRedisClient(dbIndex);\n\n\t\t\tlet scanCursor = \"0\";\n\t\t\tif (cursor) {\n\t\t\t\tconst decoded = decodeScanCursor(cursor);\n\t\t\t\tif (!decoded || decoded.type !== table) {\n\t\t\t\t\tthrow new HTTPException(400, { message: \"Invalid or mismatched cursor\" });\n\t\t\t\t}\n\t\t\t\tscanCursor = decoded.scanCursor;\n\t\t\t}\n\n\t\t\tconst collectedKeys: string[] = [];\n\t\t\tlet rounds = 0;\n\t\t\tlet scanComplete = false;\n\n\t\t\twhile (collectedKeys.length < limit && rounds < SCAN_ROUND_TRIP_CAP) {\n\t\t\t\tconst [next, batch] = (await client.scan(\n\t\t\t\t\tscanCursor,\n\t\t\t\t\t\"MATCH\",\n\t\t\t\t\t\"*\",\n\t\t\t\t\t\"COUNT\",\n\t\t\t\t\tMath.max(limit * 2, 100),\n\t\t\t\t\t\"TYPE\",\n\t\t\t\t\tredisType,\n\t\t\t\t)) as [string, string[]];\n\t\t\t\tcollectedKeys.push(...batch);\n\t\t\t\tscanCursor = next;\n\t\t\t\trounds++;\n\t\t\t\tif (next === \"0\") {\n\t\t\t\t\tscanComplete = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst pageKeys = collectedKeys.slice(0, limit);\n\t\t\tconst overflow = collectedKeys.slice(limit);\n\t\t\tconst rows = await this.hydrateRows(client, table, pageKeys);\n\n\t\t\tconst total = await client.dbsize();\n\t\t\tconst hasNextPage = !scanComplete || overflow.length > 0;\n\t\t\tconst nextCursor =\n\t\t\t\thasNextPage && !scanComplete ? encodeScanCursor({ scanCursor, type: table }) : null;\n\n\t\t\treturn {\n\t\t\t\tdata: rows,\n\t\t\t\tmeta: {\n\t\t\t\t\tlimit,\n\t\t\t\t\ttotal,\n\t\t\t\t\thasNextPage,\n\t\t\t\t\thasPreviousPage: false,\n\t\t\t\t\tnextCursor,\n\t\t\t\t\tprevCursor: null,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tprivate async hydrateRows(\n\t\tclient: Redis,\n\t\ttable: RedisTable,\n\t\tkeys: string[],\n\t): Promise<NormalizedRow[]> {\n\t\tif (keys.length === 0) return [];\n\n\t\tconst ttlPipeline = client.pipeline();\n\t\tfor (const key of keys) ttlPipeline.ttl(key);\n\t\tconst ttlResults = (await ttlPipeline.exec()) ?? [];\n\n\t\tconst valuePipeline = client.pipeline();\n\t\tfor (const key of keys) {\n\t\t\tswitch (table) {\n\t\t\t\tcase \"strings\":\n\t\t\t\t\tvaluePipeline.get(key);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hashes\":\n\t\t\t\t\tvaluePipeline.hgetall(key);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"lists\":\n\t\t\t\t\tvaluePipeline.lrange(key, 0, -1);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"sets\":\n\t\t\t\t\tvaluePipeline.smembers(key);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"zsets\":\n\t\t\t\t\tvaluePipeline.zrange(key, 0, -1, \"WITHSCORES\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"streams\":\n\t\t\t\t\tvaluePipeline.xinfo(\"STREAM\", key);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tconst valueResults = (await valuePipeline.exec()) ?? [];\n\n\t\treturn keys.map((key, i) => {\n\t\t\tconst ttl = (ttlResults[i]?.[1] as number | null) ?? -2;\n\t\t\tconst raw = valueResults[i]?.[1];\n\n\t\t\tif (table === \"streams\") {\n\t\t\t\tconst info = streamInfoToObject(raw);\n\t\t\t\treturn this.normalizeRow({\n\t\t\t\t\tkey,\n\t\t\t\t\tlength: info.length,\n\t\t\t\t\t\"first-id\": info.firstId,\n\t\t\t\t\t\"last-id\": info.lastId,\n\t\t\t\t\tttl,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlet value: unknown;\n\t\t\tswitch (table) {\n\t\t\t\tcase \"strings\":\n\t\t\t\t\tvalue = (raw as string | null) ?? null;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hashes\":\n\t\t\t\t\tvalue = raw as Record<string, unknown>;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"lists\":\n\t\t\t\tcase \"sets\":\n\t\t\t\t\tvalue = raw as unknown[];\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"zsets\":\n\t\t\t\t\tvalue = flatPairsToZsetEntries(raw as string[] | undefined);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn this.normalizeRow({ key, value, ttl } as Record<string, unknown>);\n\t\t});\n\t}\n\n\tprivate async getCachedCounts(dbIndex: number): Promise<Record<RedisTable, number>> {\n\t\tconst cached = this.countCache.get(dbIndex);\n\t\tif (cached && Date.now() - cached.timestamp < COUNT_CACHE_TTL_MS) {\n\t\t\treturn cached.counts;\n\t\t}\n\n\t\tconst client = await getRedisClient(dbIndex);\n\t\tconst counts = {} as Record<RedisTable, number>;\n\t\tconst pipeline = client.pipeline();\n\t\tfor (const table of REDIS_TABLES) {\n\t\t\tpipeline.scan(\n\t\t\t\t\"0\",\n\t\t\t\t\"MATCH\",\n\t\t\t\t\"*\",\n\t\t\t\t\"COUNT\",\n\t\t\t\tCOUNT_SCAN_CEILING,\n\t\t\t\t\"TYPE\",\n\t\t\t\tTABLE_TO_REDIS_TYPE[table],\n\t\t\t);\n\t\t}\n\t\tconst results = (await pipeline.exec()) ?? [];\n\t\tREDIS_TABLES.forEach((table, i) => {\n\t\t\tconst reply = results[i]?.[1] as [string, string[]] | undefined;\n\t\t\tcounts[table] = reply?.[1]?.length ?? 0;\n\t\t});\n\n\t\tthis.countCache.set(dbIndex, { timestamp: Date.now(), counts });\n\t\treturn counts;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Record operations\n\t// -----------------------------------------------------------------------\n\n\toverride async addRecord({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\ttry {\n\t\t\tconst { tableName, data } = params;\n\t\t\tconst table = assertRedisTable(tableName);\n\t\t\tconst key = extractKey(data);\n\t\t\tconst ttl = extractTtl(data);\n\t\t\tconst client = await getRedisClient(parseDbIndex(db));\n\n\t\t\tawait this.writeRecord(client, table, key, data.value, { mode: \"create\", ttl });\n\t\t\tthis.countCache.delete(parseDbIndex(db));\n\t\t\treturn { insertedCount: 1 };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async updateRecords({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\ttry {\n\t\t\tconst { tableName, updates, primaryKey, primaryKeys } = params;\n\t\t\tconst table = assertRedisTable(tableName);\n\t\t\tconst pkField = primaryKeys?.[0] || primaryKey || \"key\";\n\t\t\tconst client = await getRedisClient(parseDbIndex(db));\n\n\t\t\tconst updatesByKey = new Map<string, Record<string, unknown>>();\n\t\t\tfor (const u of updates) {\n\t\t\t\tconst k = u.rowData[pkField];\n\t\t\t\tif (k === undefined || k === null) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: `Primary key \"${pkField}\" not found in row data`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst keyStr = String(k);\n\t\t\t\tconst existing = updatesByKey.get(keyStr) ?? { ...u.rowData };\n\t\t\t\texisting[u.columnName] = u.value;\n\t\t\t\tupdatesByKey.set(keyStr, existing);\n\t\t\t}\n\n\t\t\tlet updatedCount = 0;\n\t\t\tfor (const [key, row] of updatesByKey.entries()) {\n\t\t\t\tconst value = row.value;\n\t\t\t\tconst ttl = extractTtl(row);\n\t\t\t\tawait this.writeRecord(client, table, key, value, { mode: \"update\", ttl });\n\n\t\t\t\t// Editing the `key` column is a rename, not a write to the old key.\n\t\t\t\tconst nextKeyRaw = row[pkField];\n\t\t\t\tconst nextKey =\n\t\t\t\t\tnextKeyRaw === undefined || nextKeyRaw === null ? key : String(nextKeyRaw);\n\t\t\t\tif (nextKey !== key) {\n\t\t\t\t\tconst renamed = await client.renamenx(key, nextKey);\n\t\t\t\t\tif (renamed === 0) {\n\t\t\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\t\t\tmessage: `Key \"${nextKey}\" already exists`,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tupdatedCount++;\n\t\t\t}\n\t\t\treturn { updatedCount };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async deleteRecords(params: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\ttry {\n\t\t\tconst { tableName, primaryKeys, db } = params;\n\t\t\tassertRedisTable(tableName);\n\t\t\tconst client = await getRedisClient(parseDbIndex(db));\n\t\t\tconst keys = primaryKeys.map((pk) => String(pk.value));\n\t\t\tif (keys.length === 0)\n\t\t\t\treturn { deletedCount: 0, fkViolation: false, relatedRecords: [] };\n\t\t\tconst deletedCount = await client.del(...keys);\n\t\t\tthis.countCache.delete(parseDbIndex(db));\n\t\t\treturn { deletedCount, fkViolation: false, relatedRecords: [] };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async forceDeleteRecords(\n\t\tparams: DeleteRecordParams,\n\t): Promise<{ deletedCount: number }> {\n\t\tconst result = await this.deleteRecords(params);\n\t\treturn { deletedCount: result.deletedCount };\n\t}\n\n\toverride async bulkInsertRecords(\n\t\tparams: BulkInsertRecordsParams,\n\t): Promise<BulkInsertResult> {\n\t\ttry {\n\t\t\tconst { tableName, records, db } = params;\n\t\t\tif (!records || records.length === 0) {\n\t\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\t\t\t}\n\t\t\tconst table = assertRedisTable(tableName);\n\t\t\tconst client = await getRedisClient(parseDbIndex(db));\n\n\t\t\tconst errors: Array<{ recordIndex: number; error: string }> = [];\n\t\t\tlet successCount = 0;\n\n\t\t\tfor (let i = 0; i < records.length; i++) {\n\t\t\t\tconst record = records[i] as Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tconst key = extractKey(record);\n\t\t\t\t\tconst ttl = extractTtl(record);\n\t\t\t\t\tawait this.writeRecord(client, table, key, record.value, { mode: \"create\", ttl });\n\t\t\t\t\tsuccessCount++;\n\t\t\t\t} catch (e) {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\trecordIndex: i,\n\t\t\t\t\t\terror: e instanceof Error ? e.message : String(e),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.countCache.delete(parseDbIndex(db));\n\t\t\treturn {\n\t\t\t\tsuccess: errors.length === 0,\n\t\t\t\tmessage: `Inserted ${successCount} of ${records.length} record${records.length === 1 ? \"\" : \"s\"}`,\n\t\t\t\tsuccessCount,\n\t\t\t\tfailureCount: errors.length,\n\t\t\t\t...(errors.length > 0 ? { errors } : {}),\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\toverride async exportTableData({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<{ cols: string[]; rows: Record<string, unknown>[] }> {\n\t\ttry {\n\t\t\tconst table = assertRedisTable(tableName);\n\t\t\tconst dbIndex = parseDbIndex(db);\n\t\t\tconst client = await getRedisClient(dbIndex);\n\t\t\tconst redisType = TABLE_TO_REDIS_TYPE[table];\n\n\t\t\tconst allKeys: string[] = [];\n\t\t\tlet scanCursor = \"0\";\n\t\t\tdo {\n\t\t\t\tconst [next, batch] = (await client.scan(\n\t\t\t\t\tscanCursor,\n\t\t\t\t\t\"MATCH\",\n\t\t\t\t\t\"*\",\n\t\t\t\t\t\"COUNT\",\n\t\t\t\t\t1000,\n\t\t\t\t\t\"TYPE\",\n\t\t\t\t\tredisType,\n\t\t\t\t)) as [string, string[]];\n\t\t\t\tallKeys.push(...batch);\n\t\t\t\tscanCursor = next;\n\t\t\t} while (scanCursor !== \"0\");\n\n\t\t\tif (allKeys.length === 0) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Table \"${tableName}\" has no data`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst rows = await this.hydrateRows(client, table, allKeys);\n\t\t\tconst cols = TABLE_COLUMNS[table].map((c) => c.columnName);\n\t\t\treturn { cols, rows: rows as Record<string, CellValue>[] };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tprivate async writeRecord(\n\t\tclient: Redis,\n\t\ttable: RedisTable,\n\t\tkey: string,\n\t\tvalue: unknown,\n\t\topts: { mode: \"create\" | \"update\"; ttl: number | null },\n\t): Promise<void> {\n\t\tif (table === \"streams\" && opts.mode === \"update\") {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: \"Streams are append-only; updating a stream record is not supported\",\n\t\t\t});\n\t\t}\n\n\t\tif (opts.mode === \"create\") {\n\t\t\tif (table === \"strings\") {\n\t\t\t\tconst result = await client.set(\n\t\t\t\t\tkey,\n\t\t\t\t\ttypeof value === \"string\" ? value : JSON.stringify(value),\n\t\t\t\t\t\"NX\",\n\t\t\t\t);\n\t\t\t\tif (result === null) {\n\t\t\t\t\tthrow new HTTPException(409, { message: `Key \"${key}\" already exists` });\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst exists = await client.exists(key);\n\t\t\t\tif (exists) {\n\t\t\t\t\tthrow new HTTPException(409, { message: `Key \"${key}\" already exists` });\n\t\t\t\t}\n\t\t\t\tawait this.writeCollectionValue(client, table, key, value);\n\t\t\t}\n\t\t} else {\n\t\t\tif (table === \"strings\") {\n\t\t\t\tconst result = await client.set(\n\t\t\t\t\tkey,\n\t\t\t\t\ttypeof value === \"string\" ? value : JSON.stringify(value),\n\t\t\t\t\t\"XX\",\n\t\t\t\t);\n\t\t\t\tif (result === null) {\n\t\t\t\t\tthrow new HTTPException(404, { message: `Key \"${key}\" does not exist` });\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst exists = await client.exists(key);\n\t\t\t\tif (!exists) {\n\t\t\t\t\tthrow new HTTPException(404, { message: `Key \"${key}\" does not exist` });\n\t\t\t\t}\n\t\t\t\tawait client.del(key);\n\t\t\t\tawait this.writeCollectionValue(client, table, key, value);\n\t\t\t}\n\t\t}\n\n\t\tif (opts.ttl !== null && opts.ttl > 0) {\n\t\t\tawait client.expire(key, opts.ttl);\n\t\t}\n\t}\n\n\tprivate async writeCollectionValue(\n\t\tclient: Redis,\n\t\ttable: RedisTable,\n\t\tkey: string,\n\t\tvalue: unknown,\n\t): Promise<void> {\n\t\tswitch (table) {\n\t\t\tcase \"hashes\": {\n\t\t\t\tconst obj = coerceObject(value, \"hash\");\n\t\t\t\tconst flat: string[] = [];\n\t\t\t\tfor (const [field, val] of Object.entries(obj)) {\n\t\t\t\t\tflat.push(field, stringifyValue(val));\n\t\t\t\t}\n\t\t\t\tif (flat.length === 0) {\n\t\t\t\t\tthrow new HTTPException(400, { message: \"Hash must have at least one field\" });\n\t\t\t\t}\n\t\t\t\tawait client.hset(key, ...flat);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase \"lists\": {\n\t\t\t\tconst arr = coerceArray(value, \"list\");\n\t\t\t\tif (arr.length === 0) {\n\t\t\t\t\tthrow new HTTPException(400, { message: \"List must have at least one element\" });\n\t\t\t\t}\n\t\t\t\tawait client.rpush(key, ...arr.map(stringifyValue));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase \"sets\": {\n\t\t\t\tconst arr = coerceArray(value, \"set\");\n\t\t\t\tif (arr.length === 0) {\n\t\t\t\t\tthrow new HTTPException(400, { message: \"Set must have at least one member\" });\n\t\t\t\t}\n\t\t\t\tawait client.sadd(key, ...arr.map(stringifyValue));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase \"zsets\": {\n\t\t\t\tconst entries = coerceZsetEntries(value);\n\t\t\t\tif (entries.length === 0) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: \"Sorted set must have at least one member\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst args: (string | number)[] = [];\n\t\t\t\tfor (const e of entries) {\n\t\t\t\t\targs.push(e.score, e.member);\n\t\t\t\t}\n\t\t\t\tawait client.zadd(key, ...(args as [string, ...string[]]));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase \"streams\": {\n\t\t\t\tconst obj = coerceObject(value, \"stream\");\n\t\t\t\tconst flat: string[] = [];\n\t\t\t\tfor (const [field, val] of Object.entries(obj)) {\n\t\t\t\t\tflat.push(field, stringifyValue(val));\n\t\t\t\t}\n\t\t\t\tif (flat.length === 0) {\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: \"Stream entry must have at least one field\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait client.xadd(key, \"*\", ...(flat as [string, ...string[]]));\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Query execution\n\t// -----------------------------------------------------------------------\n\n\toverride async executeQuery({\n\t\tquery,\n\t\tdb,\n\t}: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\tconst startTime = performance.now();\n\t\ttry {\n\t\t\tif (!query?.trim()) {\n\t\t\t\tthrow new HTTPException(400, { message: \"Query is required\" });\n\t\t\t}\n\n\t\t\tlet argv: string[];\n\t\t\ttry {\n\t\t\t\targv = tokenizeCommand(query.trim());\n\t\t\t} catch (e) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: e instanceof Error ? e.message : \"Invalid Redis command\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (argv.length === 0) {\n\t\t\t\tthrow new HTTPException(400, { message: \"Empty command\" });\n\t\t\t}\n\n\t\t\tconst client = await getRedisClient(parseDbIndex(db));\n\t\t\tconst [cmd, ...rest] = argv;\n\n\t\t\tlet reply: unknown;\n\t\t\ttry {\n\t\t\t\treply = await client.call(cmd, ...rest);\n\t\t\t} catch (e) {\n\t\t\t\tconst message = e instanceof Error ? e.message : String(e);\n\t\t\t\treturn {\n\t\t\t\t\tcolumns: [\"error\"],\n\t\t\t\t\trows: [{ error: message }],\n\t\t\t\t\trowCount: 0,\n\t\t\t\t\tduration: performance.now() - startTime,\n\t\t\t\t\terror: message,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst shaped = shapeReply(argv, reply);\n\t\t\treturn {\n\t\t\t\t...shaped,\n\t\t\t\tduration: performance.now() - startTime,\n\t\t\t\tmessage: typeof reply === \"string\" ? reply : undefined,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction parseInfoSection(info: string): Record<string, string> {\n\tconst out: Record<string, string> = {};\n\tfor (const line of info.split(/\\r?\\n/)) {\n\t\tif (!line || line.startsWith(\"#\")) continue;\n\t\tconst idx = line.indexOf(\":\");\n\t\tif (idx < 0) continue;\n\t\tout[line.slice(0, idx)] = line.slice(idx + 1);\n\t}\n\treturn out;\n}\n\nfunction parseKeyspaceInfo(info: string): Map<number, number> {\n\tconst out = new Map<number, number>();\n\tfor (const line of info.split(/\\r?\\n/)) {\n\t\tconst match = line.match(/^db(\\d+):keys=(\\d+)/);\n\t\tif (match) out.set(Number(match[1]), Number(match[2]));\n\t}\n\treturn out;\n}\n\nfunction extractKey(data: Record<string, unknown>): string {\n\tconst k = data.key;\n\tif (k === undefined || k === null || k === \"\") {\n\t\tthrow new HTTPException(400, { message: \"Field 'key' is required\" });\n\t}\n\treturn String(k);\n}\n\nfunction extractTtl(data: Record<string, unknown>): number | null {\n\tconst t = data.ttl;\n\tif (t === undefined || t === null || t === \"\") return null;\n\tconst parsed = typeof t === \"number\" ? t : Number.parseInt(String(t), 10);\n\tif (!Number.isFinite(parsed)) return null;\n\treturn parsed;\n}\n\nfunction stringifyValue(v: unknown): string {\n\tif (typeof v === \"string\") return v;\n\tif (v === null || v === undefined) return \"\";\n\tif (typeof v === \"object\") return JSON.stringify(v);\n\treturn String(v);\n}\n\nfunction coerceObject(value: unknown, kind: string): Record<string, unknown> {\n\tif (typeof value === \"string\") {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(value);\n\t\t\tif (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n\t\t\t\treturn parsed as Record<string, unknown>;\n\t\t\t}\n\t\t} catch {\n\t\t\t// fall through\n\t\t}\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: `Value for ${kind} must be a JSON object`,\n\t\t});\n\t}\n\tif (value && typeof value === \"object\" && !Array.isArray(value)) {\n\t\treturn value as Record<string, unknown>;\n\t}\n\tthrow new HTTPException(400, { message: `Value for ${kind} must be a JSON object` });\n}\n\nfunction coerceArray(value: unknown, kind: string): unknown[] {\n\tif (Array.isArray(value)) return value;\n\tif (typeof value === \"string\") {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(value);\n\t\t\tif (Array.isArray(parsed)) return parsed;\n\t\t} catch {\n\t\t\t// fall through\n\t\t}\n\t}\n\tthrow new HTTPException(400, { message: `Value for ${kind} must be a JSON array` });\n}\n\nfunction coerceZsetEntries(value: unknown): { member: string; score: number }[] {\n\tlet arr: unknown[];\n\tif (Array.isArray(value)) {\n\t\tarr = value;\n\t} else if (typeof value === \"string\") {\n\t\ttry {\n\t\t\tarr = JSON.parse(value);\n\t\t} catch {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: \"Value for zset must be an array of {member, score} entries\",\n\t\t\t});\n\t\t}\n\t} else {\n\t\tthrow new HTTPException(400, {\n\t\t\tmessage: \"Value for zset must be an array of {member, score} entries\",\n\t\t});\n\t}\n\n\tconst out: { member: string; score: number }[] = [];\n\tfor (const entry of arr) {\n\t\tif (!entry || typeof entry !== \"object\") {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: \"Each zset entry must be an object with 'member' and 'score'\",\n\t\t\t});\n\t\t}\n\t\tconst obj = entry as { member?: unknown; score?: unknown };\n\t\tif (obj.member === undefined || obj.score === undefined) {\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage: \"Each zset entry must include 'member' and 'score'\",\n\t\t\t});\n\t\t}\n\t\tconst score = typeof obj.score === \"number\" ? obj.score : Number(obj.score);\n\t\tif (!Number.isFinite(score)) {\n\t\t\tthrow new HTTPException(400, { message: `Invalid score: ${String(obj.score)}` });\n\t\t}\n\t\tout.push({ member: String(obj.member), score });\n\t}\n\treturn out;\n}\n\nfunction flatPairsToZsetEntries(\n\treply: string[] | undefined,\n): { member: string; score: number }[] {\n\tif (!reply) return [];\n\tconst out: { member: string; score: number }[] = [];\n\tfor (let i = 0; i < reply.length; i += 2) {\n\t\tconst score = Number(reply[i + 1]);\n\t\tout.push({ member: reply[i], score: Number.isFinite(score) ? score : 0 });\n\t}\n\treturn out;\n}\n\nfunction streamInfoToObject(reply: unknown): {\n\tlength: number;\n\tfirstId: string | null;\n\tlastId: string | null;\n} {\n\tif (!Array.isArray(reply)) return { length: 0, firstId: null, lastId: null };\n\tconst obj: Record<string, unknown> = {};\n\tfor (let i = 0; i < reply.length; i += 2) {\n\t\tobj[String(reply[i])] = reply[i + 1];\n\t}\n\tconst length =\n\t\ttypeof obj.length === \"number\"\n\t\t\t? obj.length\n\t\t\t: Number.parseInt(String(obj.length ?? \"0\"), 10) || 0;\n\tconst firstEntry = obj[\"first-entry\"];\n\tconst lastEntry = obj[\"last-entry\"];\n\tconst idOf = (entry: unknown): string | null =>\n\t\tArray.isArray(entry) && typeof entry[0] === \"string\" ? entry[0] : null;\n\treturn { length, firstId: idOf(firstEntry), lastId: idOf(lastEntry) };\n}\n","import type { CursorData, FilterType, SortDirection, SortType } from \"@db-studio/shared/types\";\n\nexport function buildWhereClause(filters: FilterType[]): {\n\tclause: string;\n\tvalues: unknown[];\n} {\n\tif (!filters.length) return { clause: \"\", values: [] };\n\n\tconst conditions: string[] = [];\n\tconst values: unknown[] = [];\n\n\tfor (const filter of filters) {\n\t\tconst col = `\"${filter.columnName}\"`;\n\t\tswitch (filter.operator) {\n\t\t\tcase \"=\":\n\t\t\tcase \"!=\":\n\t\t\tcase \">\":\n\t\t\tcase \">=\":\n\t\t\tcase \"<\":\n\t\t\tcase \"<=\":\n\t\t\t\tconditions.push(`${col} ${filter.operator} ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"is\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${col} IS NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} = ?`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"is not\":\n\t\t\t\tif (filter.value.toLowerCase() === \"null\") {\n\t\t\t\t\tconditions.push(`${col} IS NOT NULL`);\n\t\t\t\t} else {\n\t\t\t\t\tconditions.push(`${col} != ?`);\n\t\t\t\t\tvalues.push(filter.value);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"like\":\n\t\t\t\tconditions.push(`CAST(${col} AS TEXT) LIKE ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"not like\":\n\t\t\t\tconditions.push(`CAST(${col} AS TEXT) NOT LIKE ?`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"ilike\":\n\t\t\t\tconditions.push(`CAST(${col} AS TEXT) LIKE ? COLLATE NOCASE`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tcase \"not ilike\":\n\t\t\t\tconditions.push(`CAST(${col} AS TEXT) NOT LIKE ? COLLATE NOCASE`);\n\t\t\t\tvalues.push(filter.value);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!conditions.length) return { clause: \"\", values: [] };\n\treturn { clause: `WHERE ${conditions.join(\" AND \")}`, values };\n}\n\nexport function buildSortClause(sorts: SortType[] | string, order: SortDirection): string {\n\tif (Array.isArray(sorts)) {\n\t\tif (!sorts.length) return \"\";\n\t\treturn `ORDER BY ${sorts.map((s) => `\"${s.columnName}\" ${s.direction.toUpperCase()}`).join(\", \")}`;\n\t}\n\tif (sorts && typeof sorts === \"string\") {\n\t\treturn `ORDER BY \"${sorts}\" ${order?.toUpperCase() || \"ASC\"}`;\n\t}\n\treturn \"\";\n}\n\n/**\n * Builds cursor WHERE clause using SQLite row-value comparison (supported since 3.15.0).\n * Uses `?` positional placeholders.\n */\nexport function buildCursorWhereClause(\n\tcursorData: CursorData,\n\tdirection: SortDirection,\n\tsortDirection: SortDirection,\n): { clause: string; values: unknown[] } {\n\tconst { values, sortColumns } = cursorData;\n\tif (!sortColumns.length) return { clause: \"\", values: [] };\n\n\tconst isAscending = sortDirection === \"asc\";\n\tconst isForward = direction === \"asc\";\n\tconst useGreaterThan = isAscending === isForward;\n\tconst operator = useGreaterThan ? \">\" : \"<\";\n\n\tconst columnList = sortColumns.map((col) => `\"${col}\"`).join(\", \");\n\tconst placeholders = sortColumns.map(() => \"?\").join(\", \");\n\tconst queryValues = sortColumns.map((col) => values[col]);\n\n\treturn {\n\t\tclause: `(${columnList}) ${operator} (${placeholders})`,\n\t\tvalues: queryValues,\n\t};\n}\n\nconst CLOSING_QUOTE: Record<string, string> = { \"'\": \"'\", '\"': '\"', \"`\": \"`\", \"[\": \"]\" };\n\n/** Index just past any leading whitespace and comments. */\nfunction skipTrivia(sql: string, from: number): number {\n\tlet i = from;\n\twhile (i < sql.length) {\n\t\tif (/\\s/.test(sql[i])) i++;\n\t\telse if (sql.startsWith(\"--\", i)) {\n\t\t\tconst end = sql.indexOf(\"\\n\", i);\n\t\t\ti = end === -1 ? sql.length : end + 1;\n\t\t} else if (sql.startsWith(\"/*\", i)) {\n\t\t\tconst end = sql.indexOf(\"*/\", i + 2);\n\t\t\ti = end === -1 ? sql.length : end + 2;\n\t\t} else break;\n\t}\n\treturn i;\n}\n\n/**\n * True when `sql` holds more than one statement. Quotes, comments, trailing `;` and the\n * `BEGIN ... END` body of a CREATE TRIGGER (where `;` separates the body's statements) are ignored.\n */\nexport function hasMultipleStatements(sql: string): boolean {\n\tlet words: string[] = [];\n\tlet depth = 0;\n\tlet sawTerminator = false;\n\tlet i = skipTrivia(sql, 0);\n\twhile (i < sql.length) {\n\t\tconst ch = sql[i];\n\t\tif (ch === \";\") {\n\t\t\tif (depth === 0) {\n\t\t\t\tsawTerminator = true;\n\t\t\t\twords = [];\n\t\t\t}\n\t\t\ti = skipTrivia(sql, i + 1);\n\t\t\tcontinue;\n\t\t}\n\t\tif (sawTerminator) return true;\n\t\tconst close = CLOSING_QUOTE[ch];\n\t\tif (close) {\n\t\t\tconst end = sql.indexOf(close, i + 1);\n\t\t\ti = end === -1 ? sql.length : end + 1;\n\t\t} else if (/[A-Za-z_]/.test(ch)) {\n\t\t\tconst word = /^[A-Za-z_][A-Za-z0-9_$]*/.exec(sql.slice(i))?.[0] ?? ch;\n\t\t\tconst upper = word.toUpperCase();\n\t\t\tconst isTrigger =\n\t\t\t\twords[0] === \"CREATE\" &&\n\t\t\t\t(words[1] === \"TRIGGER\" ||\n\t\t\t\t\t((words[1] === \"TEMP\" || words[1] === \"TEMPORARY\") && words[2] === \"TRIGGER\"));\n\t\t\tif (isTrigger && (upper === \"BEGIN\" || (depth > 0 && upper === \"CASE\"))) depth++;\n\t\t\telse if (depth > 0 && upper === \"END\") depth--;\n\t\t\tif (words.length < 3) words.push(upper);\n\t\t\ti += word.length;\n\t\t} else i++;\n\t\ti = skipTrivia(sql, i);\n\t}\n\treturn false;\n}\n\nconst TRANSACTION_CONTROL =\n\t/^(begin|start\\s+transaction|commit|end|rollback|savepoint|release)\\b/i;\n\n/** True when `sql`, ignoring leading comments, is only a transaction-control statement. */\nexport function isTransactionControl(sql: string): boolean {\n\treturn TRANSACTION_CONTROL.test(sql.slice(skipTrivia(sql, 0)));\n}\n","import { statSync } from \"node:fs\";\nimport type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tCreateTableSchemaType,\n\tCursorData,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tFieldDataType,\n\tForeignKeyConstraint,\n\tForeignKeyDataType,\n\tRelatedRecord,\n\tRenameColumnParamsSchemaType,\n\tRenameTableParamsSchemaType,\n\tSortDirection,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { mapSqliteToDataType, standardizeSqliteDataTypeLabel } from \"@db-studio/shared/types\";\nimport type { InStatement, InValue, ResultSet, Value } from \"@libsql/client\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getSqliteClient } from \"@/adapters/connections.js\";\nimport {\n\tbuildCursorWhereClause,\n\tbuildSortClause,\n\tbuildWhereClause,\n\thasMultipleStatements,\n\tisTransactionControl,\n} from \"./sqlite.query-builder.js\";\n\ninterface TableInfoRow {\n\tcid: number;\n\tname: string;\n\ttype: string;\n\tnotnull: number;\n\tdflt_value: string | null;\n\tpk: number;\n}\n\ninterface FkRow {\n\tid: number;\n\tseq: number;\n\ttable: string;\n\tfrom: string;\n\t/** null when the constraint references the parent's primary key implicitly */\n\tto: string | null;\n\ton_update: string;\n\ton_delete: string;\n}\n\n/** A (possibly composite) foreign key, seen from the table it references. */\ninterface ForeignKeyEdge {\n\tchildTable: string;\n\tchildColumns: string[];\n\tparentColumns: (string | null)[];\n}\n\nconst allNamed = (columns: (string | null)[]): columns is string[] =>\n\tcolumns.every((c) => c !== null);\n\n/** A client or an open transaction. */\ninterface SqlExecutor {\n\texecute(stmt: InStatement): Promise<ResultSet>;\n}\n\nconst toSqliteValue = (value: unknown): InValue => {\n\tif (value === null || value === undefined) return null;\n\tif (typeof value === \"boolean\") return value ? 1 : 0;\n\tif (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"bigint\")\n\t\treturn value;\n\tif (value instanceof Date) return value.toISOString();\n\treturn JSON.stringify(value);\n};\n\nconst stmt = (sql: string, values: unknown[] = []): InStatement => ({\n\tsql,\n\targs: values.map(toSqliteValue),\n});\n\nconst MIN_SAFE = BigInt(Number.MIN_SAFE_INTEGER);\nconst MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);\n\n// The client runs in intMode \"bigint\" so integers past 2^53 don't throw; JSON can't carry\n// bigint or ArrayBuffer, and the export writer renders Buffers as hex.\nconst fromSqliteValue = (value: Value): unknown => {\n\tif (typeof value === \"bigint\")\n\t\treturn value >= MIN_SAFE && value <= MAX_SAFE ? Number(value) : value.toString();\n\tif (value instanceof ArrayBuffer) return Buffer.from(value);\n\treturn value;\n};\n\nconst toRows = <T = Record<string, unknown>>({ columns, rows }: ResultSet): T[] =>\n\trows.map(\n\t\t(row) => Object.fromEntries(columns.map((col, i) => [col, fromSqliteValue(row[i])])) as T,\n\t);\n\nconst all = async <T = Record<string, unknown>>(\n\texecutor: SqlExecutor,\n\tsql: string,\n\tvalues: unknown[] = [],\n): Promise<T[]> => toRows<T>(await executor.execute(stmt(sql, values)));\n\n// The client returns the connection to its pool after every call, which rolls back\n// anything left open, so a lone BEGIN would leave the next query autocommitting.\nconst isFkViolation = (e: unknown) =>\n\te instanceof Error && e.message.includes(\"FOREIGN KEY constraint failed\");\n\nexport class SqliteAdapter extends BaseAdapter {\n\t// alterColumn reads the column list and then rebuilds the table from it; a column added\n\t// between the two would be dropped by the rebuild, so column changes run one at a time.\n\tprivate schemaChange: Promise<unknown> = Promise.resolve();\n\n\tprivate serializeSchemaChange<T>(change: () => Promise<T>): Promise<T> {\n\t\tconst run = this.schemaChange.then(change);\n\t\tthis.schemaChange = run.catch(() => {});\n\t\treturn run;\n\t}\n\n\t// =========================================================\n\t// Abstract method implementations\n\t// =========================================================\n\n\tprotected async runQuery<T>(_db: string, sql: string, values: unknown[]): Promise<T> {\n\t\treturn (await all(await getSqliteClient(), sql, values)) as T;\n\t}\n\n\tprotected quoteIdentifier(name: string): string {\n\t\treturn `\"${name.replaceAll('\"', '\"\"')}\"`;\n\t}\n\n\tmapToUniversalType(nativeType: string): DataTypes {\n\t\treturn mapSqliteToDataType(nativeType);\n\t}\n\n\tmapFromUniversalType(universalType: string): string {\n\t\tconst map: Record<string, string> = {\n\t\t\ttext: \"TEXT\",\n\t\t\tnumber: \"INTEGER\",\n\t\t\tboolean: \"INTEGER\",\n\t\t\tjson: \"TEXT\",\n\t\t\tdate: \"TEXT\",\n\t\t\tarray: \"TEXT\",\n\t\t\tenum: \"TEXT\",\n\t\t};\n\t\treturn map[universalType] ?? \"TEXT\";\n\t}\n\n\tprotected buildTableDataQuery(params: GetTableDataParams): QueryBundle {\n\t\tconst {\n\t\t\ttableName,\n\t\t\tcursor = \"\",\n\t\t\tlimit = 50,\n\t\t\tdirection = \"asc\",\n\t\t\tsort = [],\n\t\t\torder = \"asc\",\n\t\t\tfilters = [],\n\t\t} = params;\n\n\t\tlet sortColumns: string[] = [];\n\t\tlet effectiveSortDirection: SortDirection = order;\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t\teffectiveSortDirection = sort[0].direction;\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\t\tif (!sortColumns.length) sortColumns = [\"rowid\"];\n\n\t\tconst { clause: filterWhere, values: filterValues } = buildWhereClause(filters);\n\n\t\tlet cursorWhere = \"\";\n\t\tlet cursorValues: unknown[] = [];\n\t\tif (cursor) {\n\t\t\tconst cursorData = this.decodeCursor(cursor);\n\t\t\tif (cursorData) {\n\t\t\t\tconst res = buildCursorWhereClause(cursorData, direction, effectiveSortDirection);\n\t\t\t\tcursorWhere = res.clause;\n\t\t\t\tcursorValues = res.values;\n\t\t\t}\n\t\t}\n\n\t\tlet combinedWhere = \"\";\n\t\tif (filterWhere && cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${filterWhere.replace(/^WHERE\\s+/i, \"\")} AND ${cursorWhere}`;\n\t\t} else if (filterWhere) {\n\t\t\tcombinedWhere = filterWhere;\n\t\t} else if (cursorWhere) {\n\t\t\tcombinedWhere = `WHERE ${cursorWhere}`;\n\t\t}\n\n\t\tconst sortClause = buildSortClause(Array.isArray(sort) ? sort : sort, order);\n\t\tlet effectiveSortClause = sortClause;\n\n\t\tif (direction === \"desc\") {\n\t\t\tif (sortClause) {\n\t\t\t\teffectiveSortClause = sortClause\n\t\t\t\t\t.replace(/\\bASC\\b/gi, \"TEMP_DESC\")\n\t\t\t\t\t.replace(/\\bDESC\\b/gi, \"ASC\")\n\t\t\t\t\t.replace(/TEMP_DESC/g, \"DESC\");\n\t\t\t} else {\n\t\t\t\teffectiveSortClause = `ORDER BY ${sortColumns.map((col) => `\"${col}\" ${effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\"}`).join(\", \")}`;\n\t\t\t}\n\t\t} else if (!sortClause) {\n\t\t\teffectiveSortClause = `ORDER BY ${sortColumns.map((col) => `\"${col}\" ${effectiveSortDirection.toUpperCase()}`).join(\", \")}`;\n\t\t}\n\n\t\tconst sql = `SELECT * FROM \"${tableName}\" ${combinedWhere} ${effectiveSortClause} LIMIT ?`;\n\t\tconst values = [...filterValues, ...cursorValues, limit + 1];\n\t\tconst countSql = `SELECT COUNT(*) as total FROM \"${tableName}\" ${filterWhere}`;\n\n\t\treturn { sql, values, countSql, countValues: filterValues };\n\t}\n\n\tprotected normalizeRows(rawRows: unknown[]): NormalizedRow[] {\n\t\treturn (rawRows as Record<string, unknown>[]).map((row) => this.normalizeRow(row));\n\t}\n\n\tprotected buildCursors(\n\t\tparams: GetTableDataParams,\n\t\trows: NormalizedRow[],\n\t\thasMore: boolean,\n\t): { nextCursor: string | null; prevCursor: string | null } {\n\t\tif (!rows.length) return { nextCursor: null, prevCursor: null };\n\n\t\tconst { direction = \"asc\", sort = [], cursor } = params;\n\t\tlet sortColumns: string[] = [];\n\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\tsortColumns = [sort];\n\t\t}\n\t\tif (!sortColumns.length) sortColumns = [\"rowid\"];\n\n\t\tconst createCursor = (row: NormalizedRow): string => {\n\t\t\tconst data: CursorData = {\n\t\t\t\tvalues: Object.fromEntries(sortColumns.map((col) => [col, row[col]])),\n\t\t\t\tsortColumns,\n\t\t\t};\n\t\t\treturn this.encodeCursor(data);\n\t\t};\n\n\t\tconst firstRow = rows[0];\n\t\tconst lastRow = rows[rows.length - 1];\n\t\tlet nextCursor: string | null = null;\n\t\tlet prevCursor: string | null = null;\n\n\t\tif (direction === \"asc\") {\n\t\t\tif (hasMore) nextCursor = createCursor(lastRow);\n\t\t\tif (cursor) prevCursor = createCursor(firstRow);\n\t\t} else {\n\t\t\tif (cursor) nextCursor = createCursor(lastRow);\n\t\t\tif (hasMore) prevCursor = createCursor(firstRow);\n\t\t}\n\n\t\treturn { nextCursor, prevCursor };\n\t}\n\n\t// =========================================================\n\t// Override getTableData to use primary key columns for stable pagination\n\t// =========================================================\n\n\toverride async getTableData(params: GetTableDataParams) {\n\t\ttry {\n\t\t\tconst {\n\t\t\t\ttableName,\n\t\t\t\tdb,\n\t\t\t\tlimit = 50,\n\t\t\t\tdirection = \"asc\",\n\t\t\t\tsort = [],\n\t\t\t\torder = \"asc\",\n\t\t\t\tcursor,\n\t\t\t\tfilters = [],\n\t\t\t} = params;\n\n\t\t\tconst client = await getSqliteClient();\n\n\t\t\tconst colInfoRows = await all<TableInfoRow>(client, `PRAGMA table_info(\"${tableName}\")`);\n\t\t\tconst pkColumns: string[] = colInfoRows\n\t\t\t\t.filter((c) => c.pk > 0)\n\t\t\t\t.sort((a, b) => a.pk - b.pk)\n\t\t\t\t.map((c) => c.name);\n\n\t\t\tlet sortColumns: string[] = [];\n\t\t\tlet effectiveSortDirection: SortDirection = order;\n\t\t\tif (Array.isArray(sort) && sort.length > 0) {\n\t\t\t\tsortColumns = sort.map((s) => s.columnName);\n\t\t\t\teffectiveSortDirection = sort[0].direction;\n\t\t\t} else if (typeof sort === \"string\" && sort) {\n\t\t\t\tsortColumns = [sort];\n\t\t\t}\n\n\t\t\tconst cursorColumns = [\n\t\t\t\t...sortColumns,\n\t\t\t\t...pkColumns.filter((pk) => !sortColumns.includes(pk)),\n\t\t\t];\n\t\t\tconst useRowid = cursorColumns.length === 0;\n\t\t\tif (useRowid) cursorColumns.push(\"rowid\");\n\n\t\t\tconst { clause: filterWhere, values: filterValues } = buildWhereClause(filters);\n\n\t\t\tlet cursorWhere = \"\";\n\t\t\tlet cursorValues: unknown[] = [];\n\t\t\tif (cursor) {\n\t\t\t\tconst cursorData = this.decodeCursor(cursor);\n\t\t\t\tif (cursorData) {\n\t\t\t\t\tconst res = buildCursorWhereClause(cursorData, direction, effectiveSortDirection);\n\t\t\t\t\tcursorWhere = res.clause;\n\t\t\t\t\tcursorValues = res.values;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet combinedWhere = \"\";\n\t\t\tif (filterWhere && cursorWhere) {\n\t\t\t\tcombinedWhere = `WHERE ${filterWhere.replace(/^WHERE\\s+/i, \"\")} AND ${cursorWhere}`;\n\t\t\t} else if (filterWhere) {\n\t\t\t\tcombinedWhere = filterWhere;\n\t\t\t} else if (cursorWhere) {\n\t\t\t\tcombinedWhere = `WHERE ${cursorWhere}`;\n\t\t\t}\n\n\t\t\tconst sortClause = buildSortClause(Array.isArray(sort) ? sort : sort, order);\n\t\t\tconst pkTieBreakerCols = pkColumns.filter((pk) => !sortColumns.includes(pk));\n\t\t\tlet effectiveSortClause = sortClause;\n\n\t\t\tif (direction === \"desc\") {\n\t\t\t\tif (sortClause) {\n\t\t\t\t\teffectiveSortClause = sortClause\n\t\t\t\t\t\t.replace(/\\bASC\\b/gi, \"TEMP_DESC\")\n\t\t\t\t\t\t.replace(/\\bDESC\\b/gi, \"ASC\")\n\t\t\t\t\t\t.replace(/TEMP_DESC/g, \"DESC\");\n\t\t\t\t\tif (pkTieBreakerCols.length) {\n\t\t\t\t\t\tconst tbDir = effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\";\n\t\t\t\t\t\teffectiveSortClause += `, ${pkTieBreakerCols.map((col) => `\"${col}\" ${tbDir}`).join(\", \")}`;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\teffectiveSortClause = `ORDER BY ${cursorColumns.map((col) => `\"${col}\" ${effectiveSortDirection === \"asc\" ? \"DESC\" : \"ASC\"}`).join(\", \")}`;\n\t\t\t\t}\n\t\t\t} else if (!sortClause) {\n\t\t\t\teffectiveSortClause = `ORDER BY ${cursorColumns.map((col) => `\"${col}\" ${effectiveSortDirection.toUpperCase()}`).join(\", \")}`;\n\t\t\t} else if (pkTieBreakerCols.length) {\n\t\t\t\teffectiveSortClause += `, ${pkTieBreakerCols.map((col) => `\"${col}\" ${effectiveSortDirection.toUpperCase()}`).join(\", \")}`;\n\t\t\t}\n\n\t\t\tconst [countRow] = await all<{ total: number }>(\n\t\t\t\tclient,\n\t\t\t\t`SELECT COUNT(*) as total FROM \"${tableName}\" ${filterWhere}`,\n\t\t\t\tfilterValues,\n\t\t\t);\n\t\t\tconst total = Number(countRow?.total ?? 0);\n\n\t\t\t// When falling back to rowid for cursor, include it in SELECT so buildCursors can read it\n\t\t\tconst selectClause = useRowid ? \"*, rowid\" : \"*\";\n\t\t\tconst dataRows = await all(\n\t\t\t\tclient,\n\t\t\t\t`SELECT ${selectClause} FROM \"${tableName}\" ${combinedWhere} ${effectiveSortClause} LIMIT ?`,\n\t\t\t\t[...filterValues, ...cursorValues, limit + 1],\n\t\t\t);\n\n\t\t\tconst hasMore = dataRows.length > limit;\n\t\t\tlet rows = hasMore ? dataRows.slice(0, limit) : dataRows;\n\t\t\tif (direction === \"desc\") rows = rows.reverse();\n\n\t\t\tconst createCursor = (row: Record<string, unknown>): CursorData => ({\n\t\t\t\tvalues: Object.fromEntries(cursorColumns.map((col) => [col, row[col]])),\n\t\t\t\tsortColumns: cursorColumns,\n\t\t\t});\n\n\t\t\tlet nextCursor: string | null = null;\n\t\t\tlet prevCursor: string | null = null;\n\n\t\t\tif (rows.length > 0) {\n\t\t\t\tconst firstRow = rows[0];\n\t\t\t\tconst lastRow = rows[rows.length - 1];\n\t\t\t\tif (direction === \"asc\") {\n\t\t\t\t\tif (hasMore) nextCursor = this.encodeCursor(createCursor(lastRow));\n\t\t\t\t\tif (cursor) prevCursor = this.encodeCursor(createCursor(firstRow));\n\t\t\t\t} else {\n\t\t\t\t\tif (cursor) nextCursor = this.encodeCursor(createCursor(lastRow));\n\t\t\t\t\tif (hasMore) prevCursor = this.encodeCursor(createCursor(firstRow));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Strip the synthetic rowid from output rows if we added it\n\t\t\tconst finalRows = useRowid ? rows.map(({ rowid: _r, ...rest }) => rest) : rows;\n\n\t\t\tvoid db;\n\t\t\treturn {\n\t\t\t\tdata: finalRows as NormalizedRow[],\n\t\t\t\tmeta: {\n\t\t\t\t\tlimit,\n\t\t\t\t\ttotal,\n\t\t\t\t\thasNextPage: direction === \"asc\" ? hasMore : !!cursor,\n\t\t\t\t\thasPreviousPage: direction === \"asc\" ? !!cursor : hasMore,\n\t\t\t\t\tnextCursor,\n\t\t\t\t\tprevCursor,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// IDbAdapter — Databases\n\t// =========================================================\n\n\tasync getDatabasesList(): Promise<DatabaseInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst client = await getSqliteClient();\n\t\t\tconst rows = await all<{ seq: number; name: string; file: string }>(\n\t\t\t\tclient,\n\t\t\t\t\"PRAGMA database_list\",\n\t\t\t);\n\n\t\t\tif (!rows.length)\n\t\t\t\tthrow new HTTPException(500, { message: \"No databases returned from SQLite\" });\n\n\t\t\t// Hide SQLite's internal temp database. `PRAGMA database_list` always\n\t\t\t// reports `main`, so filtering can never empty the list.\n\t\t\treturn rows\n\t\t\t\t.filter((row) => row.name !== \"temp\")\n\t\t\t\t.map((row) => ({\n\t\t\t\t\tname: row.name,\n\t\t\t\t\t// A remote server reports its own filesystem path; there is nothing local to stat.\n\t\t\t\t\tsize: client.protocol === \"file\" ? this.getFileSize(row.file) : \"N/A\",\n\t\t\t\t\towner: \"\",\n\t\t\t\t\tencoding: \"UTF-8\",\n\t\t\t\t}));\n\t\t} catch (e) {\n\t\t\tif (e instanceof HTTPException) throw e;\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getCurrentDatabase(): Promise<DatabaseSchemaType> {\n\t\ttry {\n\t\t\tconst rows = await all<{ name: string }>(\n\t\t\t\tawait getSqliteClient(),\n\t\t\t\t\"PRAGMA database_list\",\n\t\t\t);\n\t\t\tconst main = rows.find((r) => r.name === \"main\");\n\t\t\treturn { db: main?.name ?? \"main\" };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync getDatabaseConnectionInfo(): Promise<ConnectionInfoSchemaType> {\n\t\ttry {\n\t\t\tconst [versionRow] = await all<{ version: string }>(\n\t\t\t\tawait getSqliteClient(),\n\t\t\t\t\"SELECT sqlite_version() as version\",\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\thost: null,\n\t\t\t\tport: null,\n\t\t\t\tuser: \"\",\n\t\t\t\tdatabase: \"main\",\n\t\t\t\tversion: `SQLite ${versionRow.version}`,\n\t\t\t\tactive_connections: 1,\n\t\t\t\tmax_connections: 1,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// IDbAdapter — Tables\n\t// =========================================================\n\n\tasync getTablesList(_db: DatabaseSchemaType[\"db\"]): Promise<TableInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst client = await getSqliteClient();\n\t\t\tconst tables = await all<{ name: string }>(\n\t\t\t\tclient,\n\t\t\t\t`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name`,\n\t\t\t);\n\t\t\tif (!tables.length) return [];\n\n\t\t\t// One round trip for every count; matters against a remote server.\n\t\t\tconst counts = await client.batch(\n\t\t\t\ttables.map((t) => `SELECT COUNT(*) as count FROM ${this.quoteIdentifier(t.name)}`),\n\t\t\t\t\"read\",\n\t\t\t);\n\t\t\treturn tables.map((t, i) => ({\n\t\t\t\ttableName: t.name,\n\t\t\t\trowCount: toRows<{ count: number }>(counts[i])[0]?.count ?? 0,\n\t\t\t}));\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync createTable({\n\t\ttableData,\n\t\tdb,\n\t}: {\n\t\ttableData: CreateTableSchemaType;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<void> {\n\t\tconst { tableName, fields, foreignKeys } = tableData;\n\n\t\tconst primaryKey = fields.filter((f) => f.isPrimaryKey).map((f) => f.columnName);\n\t\tconst columnDefs = fields.map((field: FieldDataType) => {\n\t\t\t// SQLite AUTOINCREMENT requires \"INTEGER PRIMARY KEY AUTOINCREMENT\"\n\t\t\tif (primaryKey.length === 1 && field.isPrimaryKey && field.isIdentity) {\n\t\t\t\treturn `\"${field.columnName}\" INTEGER PRIMARY KEY AUTOINCREMENT`;\n\t\t\t}\n\t\t\tlet def = `\"${field.columnName}\" ${field.columnType}`;\n\t\t\tif (primaryKey.length === 1 && field.isPrimaryKey) def += \" PRIMARY KEY\";\n\t\t\tif (field.isUnique && !field.isPrimaryKey) def += \" UNIQUE\";\n\t\t\tif (!field.isNullable && !field.isPrimaryKey) def += \" NOT NULL\";\n\t\t\tif (field.defaultValue?.trim() && !field.isIdentity)\n\t\t\t\tdef += ` DEFAULT ${field.defaultValue.trim()}`;\n\t\t\treturn def;\n\t\t});\n\t\tif (primaryKey.length > 1)\n\t\t\tcolumnDefs.push(`PRIMARY KEY (${primaryKey.map((c) => `\"${c}\"`).join(\", \")})`);\n\n\t\tconst fkDefs =\n\t\t\tforeignKeys?.map(\n\t\t\t\t(fk: ForeignKeyDataType) =>\n\t\t\t\t\t`FOREIGN KEY (\"${fk.columnName}\") REFERENCES \"${fk.referencedTable}\" (\"${fk.referencedColumn}\") ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}`,\n\t\t\t) ?? [];\n\n\t\tconst client = await getSqliteClient();\n\t\tawait client.execute(\n\t\t\t`CREATE TABLE \"${tableName}\" (${[...columnDefs, ...fkDefs].join(\", \")})`,\n\t\t);\n\n\t\tvoid db;\n\t}\n\n\tasync deleteTable(params: DeleteTableParams): Promise<DeleteTableResult> {\n\t\tconst { tableName, cascade } = params;\n\t\tconst client = await getSqliteClient();\n\n\t\tif (!(await this.tableExists(client, tableName)))\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tconst [countRow] = await all<{ count: number }>(\n\t\t\tclient,\n\t\t\t`SELECT COUNT(*) as count FROM \"${tableName}\"`,\n\t\t);\n\t\tconst rowCount = countRow?.count ?? 0;\n\n\t\tif (!cascade) {\n\t\t\tconst related = await this.getFkReferencesForTable(client, tableName);\n\t\t\tif (related.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\tdeletedCount: 0,\n\t\t\t\t\tfkViolation: true,\n\t\t\t\t\trelatedRecords: await this.getRelatedRecordsForTable(client, tableName),\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tawait client.execute(`DROP TABLE \"${tableName}\"`);\n\t\t\treturn { deletedCount: rowCount, fkViolation: false, relatedRecords: [] };\n\t\t} catch (error) {\n\t\t\tconst errMsg = error instanceof Error ? error.message : String(error);\n\t\t\tif (errMsg.includes(\"FOREIGN KEY constraint\")) {\n\t\t\t\treturn {\n\t\t\t\t\tdeletedCount: 0,\n\t\t\t\t\tfkViolation: true,\n\t\t\t\t\trelatedRecords: await this.getRelatedRecordsForTable(client, tableName),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (error instanceof HTTPException) throw error;\n\t\t\tthrow new HTTPException(500, { message: `Failed to delete table \"${tableName}\"` });\n\t\t}\n\t}\n\n\tasync renameTable(params: RenameTableParamsSchemaType): Promise<void> {\n\t\tconst { tableName, newTableName, db } = params;\n\t\tthis.assertDifferentTableName(tableName, newTableName);\n\t\tconst client = await getSqliteClient();\n\n\t\tif (!(await this.tableExists(client, tableName)))\n\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\tif (await this.tableExists(client, newTableName))\n\t\t\tthrow new HTTPException(409, {\n\t\t\t\tmessage: `Table \"${newTableName}\" already exists`,\n\t\t\t});\n\n\t\ttry {\n\t\t\tawait client.execute(\n\t\t\t\t`ALTER TABLE ${this.quoteIdentifier(tableName)} RENAME TO ${this.quoteIdentifier(newTableName)}`,\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\n\t\tvoid db;\n\t}\n\n\tasync getTableSchema({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<string> {\n\t\ttry {\n\t\t\tconst [row] = await all<{ sql: string }>(\n\t\t\t\tawait getSqliteClient(),\n\t\t\t\t`SELECT sql FROM sqlite_master WHERE type='table' AND name=?`,\n\t\t\t\t[tableName],\n\t\t\t);\n\t\t\tif (!row)\n\t\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\t\t\tvoid db;\n\t\t\treturn row.sql;\n\t\t} catch (e) {\n\t\t\tif (e instanceof HTTPException) throw e;\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// IDbAdapter — Columns\n\t// =========================================================\n\n\tasync getTableColumns({\n\t\ttableName,\n\t\tdb,\n\t}: {\n\t\ttableName: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ColumnInfoSchemaType[]> {\n\t\ttry {\n\t\t\tconst client = await getSqliteClient();\n\n\t\t\tif (!(await this.tableExists(client, tableName)))\n\t\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\t\tconst columns = await all<TableInfoRow>(client, `PRAGMA table_info(\"${tableName}\")`);\n\t\t\tconst fks = await all<FkRow>(client, `PRAGMA foreign_key_list(\"${tableName}\")`);\n\n\t\t\tconst fkMap = new Map<string, FkRow>();\n\t\t\tfor (const fk of fks) {\n\t\t\t\tfkMap.set(fk.from, fk);\n\t\t\t}\n\n\t\t\tvoid db;\n\t\t\treturn columns.map((col) => {\n\t\t\t\tconst fk = fkMap.get(col.name);\n\t\t\t\tconst nativeType = col.type.toLowerCase();\n\t\t\t\treturn {\n\t\t\t\t\tcolumnName: col.name,\n\t\t\t\t\tdataType: mapSqliteToDataType(nativeType),\n\t\t\t\t\tdataTypeLabel: standardizeSqliteDataTypeLabel(nativeType),\n\t\t\t\t\tisNullable: col.notnull === 0 && col.pk === 0,\n\t\t\t\t\tcolumnDefault: col.dflt_value,\n\t\t\t\t\tisPrimaryKey: col.pk > 0,\n\t\t\t\t\tisForeignKey: fkMap.has(col.name),\n\t\t\t\t\treferencedTable: fk?.table ?? null,\n\t\t\t\t\treferencedColumn: fk?.to ?? null,\n\t\t\t\t\tenumValues: null,\n\t\t\t\t};\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tif (e instanceof HTTPException) throw e;\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync addColumn(params: AddColumnParamsSchemaType): Promise<void> {\n\t\treturn this.serializeSchemaChange(async () => {\n\t\t\tconst { tableName, columnName, columnType, defaultValue, isNullable, isUnique, db } =\n\t\t\t\tparams;\n\t\t\tconst client = await getSqliteClient();\n\n\t\t\tif (!(await this.tableExists(client, tableName)))\n\t\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\t\tconst colInfo = await all<TableInfoRow>(client, `PRAGMA table_info(\"${tableName}\")`);\n\t\t\tif (colInfo.some((c) => c.name === columnName)) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Column \"${columnName}\" already exists in table \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlet def = `\"${columnName}\" ${columnType}`;\n\t\t\tif (isUnique) def += \" UNIQUE\";\n\t\t\tif (!isNullable) def += \" NOT NULL\";\n\t\t\tif (defaultValue?.trim()) def += ` DEFAULT ${defaultValue.trim()}`;\n\n\t\t\ttry {\n\t\t\t\tawait client.execute(`ALTER TABLE \"${tableName}\" ADD COLUMN ${def}`);\n\t\t\t} catch (e) {\n\t\t\t\tthrow this.wrapError(e);\n\t\t\t}\n\n\t\t\tvoid db;\n\t\t});\n\t}\n\n\tasync deleteColumn(params: DeleteColumnParamsSchemaType): Promise<{ deletedCount: number }> {\n\t\treturn this.serializeSchemaChange(async () => {\n\t\t\tconst { tableName, columnName, db } = params;\n\t\t\tconst client = await getSqliteClient();\n\n\t\t\tif (!(await this.tableExists(client, tableName)))\n\t\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\t\tconst colInfo = await all<TableInfoRow>(client, `PRAGMA table_info(\"${tableName}\")`);\n\t\t\tif (!colInfo.some((c) => c.name === columnName)) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tawait client.execute(`ALTER TABLE \"${tableName}\" DROP COLUMN \"${columnName}\"`);\n\t\t\t} catch (e) {\n\t\t\t\tthrow this.wrapError(e);\n\t\t\t}\n\n\t\t\tvoid db;\n\t\t\treturn { deletedCount: 1 };\n\t\t});\n\t}\n\n\tasync alterColumn(params: AlterColumnParamsSchemaType): Promise<void> {\n\t\treturn this.serializeSchemaChange(async () => {\n\t\t\tconst { tableName, columnName, columnType, isNullable, defaultValue, db } = params;\n\t\t\tconst client = await getSqliteClient();\n\t\t\tconst q = (name: string) => this.quoteIdentifier(name);\n\n\t\t\tif (!(await this.tableExists(client, tableName)))\n\t\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\t\tconst colInfo = await all<TableInfoRow>(client, `PRAGMA table_info(${q(tableName)})`);\n\t\t\tif (!colInfo.some((c) => c.name === columnName)) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// SQLite doesn't support ALTER COLUMN — use the recreate-table approach\n\t\t\tconst pkCols = colInfo.filter((c) => c.pk > 0).sort((a, b) => a.pk - b.pk);\n\t\t\tconst hasCompositePk = pkCols.length > 1;\n\n\t\t\tconst newColDefs = colInfo.map((col) => {\n\t\t\t\tconst isTarget = col.name === columnName;\n\t\t\t\tconst type = isTarget ? columnType : col.type;\n\t\t\t\tconst nullable = isTarget ? isNullable : col.notnull === 0;\n\t\t\t\tconst defVal = isTarget ? defaultValue?.trim() || null : col.dflt_value;\n\t\t\t\tconst isPk = col.pk > 0;\n\n\t\t\t\tlet def = `${q(col.name)} ${type}`;\n\t\t\t\tif (!hasCompositePk && isPk) def += \" PRIMARY KEY\";\n\t\t\t\tif (!isPk && !nullable) def += \" NOT NULL\";\n\t\t\t\tif (defVal) def += ` DEFAULT ${defVal}`;\n\t\t\t\treturn def;\n\t\t\t});\n\n\t\t\tif (hasCompositePk) {\n\t\t\t\tnewColDefs.push(`PRIMARY KEY (${pkCols.map((c) => q(c.name)).join(\", \")})`);\n\t\t\t}\n\n\t\t\tconst fks = await all<FkRow>(client, `PRAGMA foreign_key_list(${q(tableName)})`);\n\t\t\tconst fksByGroup = new Map<number, FkRow[]>();\n\t\t\tfor (const fk of fks) {\n\t\t\t\tconst arr = fksByGroup.get(fk.id) ?? [];\n\t\t\t\tarr.push(fk);\n\t\t\t\tfksByGroup.set(fk.id, arr);\n\t\t\t}\n\t\t\tconst fkDefs = Array.from(fksByGroup.values()).map((group) => {\n\t\t\t\tconst from = group.map((f) => q(f.from)).join(\", \");\n\t\t\t\tconst toColumns = group.map((f) => f.to);\n\t\t\t\tconst to = allNamed(toColumns) ? ` (${toColumns.map(q).join(\", \")})` : \"\";\n\t\t\t\tconst { table, on_update, on_delete } = group[0];\n\t\t\t\treturn `FOREIGN KEY (${from}) REFERENCES ${q(table)}${to} ON UPDATE ${on_update} ON DELETE ${on_delete}`;\n\t\t\t});\n\n\t\t\tconst colNames = colInfo.map((c) => q(c.name)).join(\", \");\n\t\t\tconst tempName = `${tableName}_alter_${Date.now()}`;\n\n\t\t\tconst existingIndexes = await all<{ sql: string }>(\n\t\t\t\tclient,\n\t\t\t\t`SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name=? AND sql IS NOT NULL`,\n\t\t\t\t[tableName],\n\t\t\t);\n\t\t\tconst existingTriggers = await all<{ sql: string }>(\n\t\t\t\tclient,\n\t\t\t\t`SELECT sql FROM sqlite_master WHERE type='trigger' AND tbl_name=?`,\n\t\t\t\t[tableName],\n\t\t\t);\n\n\t\t\t// DROP TABLE runs an implicit DELETE, which would fire ON DELETE CASCADE on child\n\t\t\t// tables, so foreign keys must be off. That PRAGMA is a no-op inside a transaction\n\t\t\t// and does not outlive one request on a remote server; migrate() turns it off,\n\t\t\t// runs the statements in one transaction on one connection, and turns it back on\n\t\t\t// even when a statement fails.\n\t\t\ttry {\n\t\t\t\tawait client.migrate([\n\t\t\t\t\t`CREATE TABLE ${q(tempName)} (${[...newColDefs, ...fkDefs].join(\", \")})`,\n\t\t\t\t\t`INSERT INTO ${q(tempName)} (${colNames}) SELECT ${colNames} FROM ${q(tableName)}`,\n\t\t\t\t\t`DROP TABLE ${q(tableName)}`,\n\t\t\t\t\t`ALTER TABLE ${q(tempName)} RENAME TO ${q(tableName)}`,\n\t\t\t\t\t...existingIndexes.map(({ sql }) => sql),\n\t\t\t\t\t...existingTriggers.map(({ sql }) => sql),\n\t\t\t\t]);\n\t\t\t} catch (e) {\n\t\t\t\tthrow this.wrapError(e);\n\t\t\t}\n\n\t\t\tvoid db;\n\t\t});\n\t}\n\n\tasync renameColumn(params: RenameColumnParamsSchemaType): Promise<void> {\n\t\treturn this.serializeSchemaChange(async () => {\n\t\t\tconst { tableName, columnName, newColumnName, db } = params;\n\t\t\tconst client = await getSqliteClient();\n\n\t\t\tif (!(await this.tableExists(client, tableName)))\n\t\t\t\tthrow new HTTPException(404, { message: `Table \"${tableName}\" does not exist` });\n\n\t\t\tconst colInfo = await all<TableInfoRow>(client, `PRAGMA table_info(\"${tableName}\")`);\n\t\t\tif (!colInfo.some((c) => c.name === columnName)) {\n\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\tmessage: `Column \"${columnName}\" does not exist in table \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (colInfo.some((c) => c.name === newColumnName)) {\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Column \"${newColumnName}\" already exists in table \"${tableName}\"`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tawait client.execute(\n\t\t\t\t\t`ALTER TABLE \"${tableName}\" RENAME COLUMN \"${columnName}\" TO \"${newColumnName}\"`,\n\t\t\t\t);\n\t\t\t} catch (e) {\n\t\t\t\tthrow this.wrapError(e);\n\t\t\t}\n\n\t\t\tvoid db;\n\t\t});\n\t}\n\n\t// =========================================================\n\t// IDbAdapter — Records\n\t// =========================================================\n\n\tasync addRecord({\n\t\tparams,\n\t}: {\n\t\tparams: AddRecordSchemaType;\n\t}): Promise<{ insertedCount: number }> {\n\t\tconst { tableName, data } = params;\n\t\tconst columns = Object.keys(data);\n\t\tif (!columns.length)\n\t\t\tthrow new HTTPException(400, { message: \"No data provided for insert\" });\n\n\t\tconst colNames = columns.map((c) => `\"${c}\"`).join(\", \");\n\t\tconst placeholders = columns.map(() => \"?\").join(\", \");\n\n\t\ttry {\n\t\t\tconst client = await getSqliteClient();\n\t\t\tconst result = await client.execute(\n\t\t\t\tstmt(\n\t\t\t\t\t`INSERT INTO \"${tableName}\" (${colNames}) VALUES (${placeholders})`,\n\t\t\t\t\tObject.values(data),\n\t\t\t\t),\n\t\t\t);\n\t\t\tif (result.rowsAffected === 0)\n\t\t\t\tthrow new HTTPException(500, {\n\t\t\t\t\tmessage: `Failed to insert record into \"${tableName}\"`,\n\t\t\t\t});\n\t\t\treturn { insertedCount: result.rowsAffected };\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync updateRecords({\n\t\tdb,\n\t\tparams,\n\t}: {\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t\tparams: UpdateRecordsSchemaType;\n\t}): Promise<{ updatedCount: number }> {\n\t\tconst { tableName } = params;\n\n\t\tconst keyColumns = this.resolveKeyColumns(params);\n\t\tconst groups = this.groupUpdatesByKey(params, keyColumns);\n\n\t\ttry {\n\t\t\tconst client = await getSqliteClient();\n\t\t\tthis.assertWholeKey(await this.getPrimaryKeyColumns(client, tableName), keyColumns);\n\t\t\tconst tx = await client.transaction(\"write\");\n\t\t\ttry {\n\t\t\t\tlet total = 0;\n\t\t\t\tfor (const { keyValues, rowUpdates } of groups) {\n\t\t\t\t\tconst setClauses = rowUpdates.map((u) => `\"${u.columnName}\" = ?`).join(\", \");\n\t\t\t\t\tconst whereClauses = keyColumns.map((column) => `\"${column}\" = ?`).join(\" AND \");\n\t\t\t\t\tconst result = await tx.execute(\n\t\t\t\t\t\tstmt(`UPDATE \"${tableName}\" SET ${setClauses} WHERE ${whereClauses}`, [\n\t\t\t\t\t\t\t...rowUpdates.map((u) => u.value),\n\t\t\t\t\t\t\t...keyValues,\n\t\t\t\t\t\t]),\n\t\t\t\t\t);\n\t\t\t\t\tif (result.rowsAffected === 0) {\n\t\t\t\t\t\tthrow new HTTPException(404, {\n\t\t\t\t\t\t\tmessage: `Record with ${this.describeKey(keyColumns, keyValues)} not found in table \"${tableName}\"`,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\ttotal += result.rowsAffected;\n\t\t\t\t}\n\t\t\t\tawait tx.commit();\n\t\t\t\tvoid db;\n\t\t\t\treturn { updatedCount: total };\n\t\t\t} catch (e) {\n\t\t\t\tawait tx.rollback();\n\t\t\t\tthrow e;\n\t\t\t} finally {\n\t\t\t\ttx.close();\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync deleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<DeleteRecordResult> {\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst placeholders = pkValues.map(() => \"?\").join(\", \");\n\t\tconst client = await getSqliteClient();\n\n\t\ttry {\n\t\t\tthis.assertDeletableKey(await this.getPrimaryKeyColumns(client, tableName));\n\t\t\tconst result = await client.execute(\n\t\t\t\tstmt(`DELETE FROM \"${tableName}\" WHERE \"${pkColumn}\" IN (${placeholders})`, pkValues),\n\t\t\t);\n\t\t\tvoid db;\n\t\t\treturn { deletedCount: result.rowsAffected, fkViolation: false, relatedRecords: [] };\n\t\t} catch (e) {\n\t\t\tif (isFkViolation(e)) {\n\t\t\t\tconst relatedRecords = await this.getRelatedRecords(client, tableName, primaryKeys);\n\t\t\t\tvoid db;\n\t\t\t\treturn { deletedCount: 0, fkViolation: true, relatedRecords };\n\t\t\t}\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t/**\n\t * Deletes the rows and, children first, every row that references them through any chain\n\t * of foreign keys. Each table's rows are selected by a predicate nested on its parent's,\n\t * so the plan is a list of plain DELETEs that run as one write batch (one transaction).\n\t * A foreign key cycle is not followed; rows it still references make the batch fail\n\t * and roll back instead of leaving orphans.\n\t */\n\tasync forceDeleteRecords({\n\t\ttableName,\n\t\tprimaryKeys,\n\t\tdb,\n\t}: DeleteRecordParams): Promise<{ deletedCount: number }> {\n\t\tconst pkColumn = primaryKeys[0]?.columnName;\n\t\tif (!pkColumn)\n\t\t\tthrow new HTTPException(400, { message: \"Primary key column name is required\" });\n\n\t\tconst q = (name: string) => this.quoteIdentifier(name);\n\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\tconst rootPredicate = `${q(pkColumn)} IN (${pkValues.map(() => \"?\").join(\", \")})`;\n\n\t\ttry {\n\t\t\tconst client = await getSqliteClient();\n\t\t\tthis.assertDeletableKey(await this.getPrimaryKeyColumns(client, tableName));\n\t\t\tconst fksByParent = await this.getForeignKeysByParent(client);\n\t\t\tconst deletes: InStatement[] = [];\n\n\t\t\tconst plan = async (table: string, predicate: string, path: string[]) => {\n\t\t\t\tfor (const fk of fksByParent.get(table) ?? []) {\n\t\t\t\t\tif (path.includes(fk.childTable)) continue;\n\t\t\t\t\tconst parentCols = allNamed(fk.parentColumns)\n\t\t\t\t\t\t? fk.parentColumns\n\t\t\t\t\t\t: await this.getPrimaryKeyColumns(client, table);\n\t\t\t\t\tconst childPredicate = `(${fk.childColumns.map(q).join(\", \")}) IN (SELECT ${parentCols.map(q).join(\", \")} FROM ${q(table)} WHERE ${predicate})`;\n\t\t\t\t\tawait plan(fk.childTable, childPredicate, [...path, fk.childTable]);\n\t\t\t\t}\n\t\t\t\tdeletes.push(stmt(`DELETE FROM ${q(table)} WHERE ${predicate}`, pkValues));\n\t\t\t};\n\t\t\tawait plan(tableName, rootPredicate, [tableName]);\n\n\t\t\tconst results = await client.batch(deletes, \"write\");\n\t\t\tvoid db;\n\t\t\treturn { deletedCount: results.reduce((sum, r) => sum + r.rowsAffected, 0) };\n\t\t} catch (e) {\n\t\t\tif (isFkViolation(e))\n\t\t\t\tthrow new HTTPException(409, {\n\t\t\t\t\tmessage: `Cannot force delete from \"${tableName}\": rows are still referenced through a foreign key cycle`,\n\t\t\t\t});\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\tasync bulkInsertRecords({\n\t\ttableName,\n\t\trecords,\n\t\tdb,\n\t}: BulkInsertRecordsParams): Promise<BulkInsertResult> {\n\t\tif (!records?.length)\n\t\t\tthrow new HTTPException(400, { message: \"At least one record is required\" });\n\n\t\tconst columns = Object.keys(records[0]);\n\t\tconst colNames = columns.map((c) => `\"${c}\"`).join(\", \");\n\t\tconst placeholders = columns.map(() => \"?\").join(\", \");\n\t\tconst sql = `INSERT INTO \"${tableName}\" (${colNames}) VALUES (${placeholders})`;\n\n\t\ttry {\n\t\t\tconst client = await getSqliteClient();\n\t\t\tawait client.batch(\n\t\t\t\trecords.map((record) =>\n\t\t\t\t\tstmt(\n\t\t\t\t\t\tsql,\n\t\t\t\t\t\tcolumns.map((col) => record[col]),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\t\"write\",\n\t\t\t);\n\t\t\tvoid db;\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `Bulk insert completed: ${records.length} records inserted`,\n\t\t\t\tsuccessCount: records.length,\n\t\t\t\tfailureCount: 0,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// IDbAdapter — Query\n\t// =========================================================\n\n\tasync executeQuery({\n\t\tquery,\n\t\tdb,\n\t}: {\n\t\tquery: string;\n\t\tdb: DatabaseSchemaType[\"db\"];\n\t}): Promise<ExecuteQueryResult> {\n\t\tif (!query?.trim()) throw new HTTPException(400, { message: \"Query is required\" });\n\n\t\tconst cleaned = query.trim().replace(/;+$/, \"\");\n\t\tif (isTransactionControl(cleaned))\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage:\n\t\t\t\t\t\"Transaction statements (BEGIN, COMMIT, ROLLBACK, SAVEPOINT, RELEASE) are not supported in the query runner: each query runs on its own connection, so a transaction cannot span queries.\",\n\t\t\t});\n\t\tif (hasMultipleStatements(cleaned))\n\t\t\tthrow new HTTPException(400, {\n\t\t\t\tmessage:\n\t\t\t\t\t\"The query runner runs one statement at a time. Run each statement separately.\",\n\t\t\t});\n\t\tconst start = performance.now();\n\n\t\ttry {\n\t\t\tconst result = await (await getSqliteClient()).execute(cleaned);\n\t\t\tconst duration = performance.now() - start;\n\t\t\tvoid db;\n\t\t\t// Statements that return rows report their columns even when no row matches.\n\t\t\tif (result.columns.length > 0) {\n\t\t\t\tconst rows = toRows(result);\n\t\t\t\treturn {\n\t\t\t\t\tcolumns: result.columns,\n\t\t\t\t\trows,\n\t\t\t\t\trowCount: rows.length,\n\t\t\t\t\tduration,\n\t\t\t\t\tmessage: rows.length === 0 ? \"OK\" : undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcolumns: [],\n\t\t\t\trows: [],\n\t\t\t\trowCount: result.rowsAffected,\n\t\t\t\tduration,\n\t\t\t\tmessage: `OK (${result.rowsAffected} rows affected)`,\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tthrow this.wrapError(e);\n\t\t}\n\t}\n\n\t// =========================================================\n\t// Private helpers\n\t// =========================================================\n\n\tprivate async tableExists(client: SqlExecutor, tableName: string): Promise<boolean> {\n\t\tconst rows = await all(\n\t\t\tclient,\n\t\t\t`SELECT name FROM sqlite_master WHERE type='table' AND name=?`,\n\t\t\t[tableName],\n\t\t);\n\t\treturn rows.length > 0;\n\t}\n\n\tprivate async getPrimaryKeyColumns(client: SqlExecutor, tableName: string) {\n\t\tconst cols = await all<TableInfoRow>(\n\t\t\tclient,\n\t\t\t`PRAGMA table_info(${this.quoteIdentifier(tableName)})`,\n\t\t);\n\t\treturn cols\n\t\t\t.filter((c) => c.pk > 0)\n\t\t\t.sort((a, b) => a.pk - b.pk)\n\t\t\t.map((c) => c.name);\n\t}\n\n\t/** Every foreign key in the database, keyed by the table it references. */\n\tprivate async getForeignKeysByParent(\n\t\tclient: SqlExecutor,\n\t): Promise<Map<string, ForeignKeyEdge[]>> {\n\t\tconst rows = await all<{\n\t\t\tchild: string;\n\t\t\tid: number;\n\t\t\tparent: string;\n\t\t\tfrom: string;\n\t\t\tto: string | null;\n\t\t}>(\n\t\t\tclient,\n\t\t\t`SELECT m.name AS child, f.id, f.\"table\" AS parent, f.\"from\", f.\"to\"\n\t\t\tFROM sqlite_master m JOIN pragma_foreign_key_list(m.name) f\n\t\t\tWHERE m.type = 'table' AND m.name NOT LIKE 'sqlite_%'\n\t\t\tORDER BY m.name, f.id, f.seq`,\n\t\t);\n\t\tconst byConstraint = new Map<string, ForeignKeyEdge>();\n\t\tconst byParent = new Map<string, ForeignKeyEdge[]>();\n\t\tfor (const row of rows) {\n\t\t\tconst key = `${row.child}\\u0000${row.id}`;\n\t\t\tlet fk = byConstraint.get(key);\n\t\t\tif (!fk) {\n\t\t\t\tfk = { childTable: row.child, childColumns: [], parentColumns: [] };\n\t\t\t\tbyConstraint.set(key, fk);\n\t\t\t\tbyParent.set(row.parent, [...(byParent.get(row.parent) ?? []), fk]);\n\t\t\t}\n\t\t\tfk.childColumns.push(row.from);\n\t\t\tfk.parentColumns.push(row.to);\n\t\t}\n\t\treturn byParent;\n\t}\n\n\tprivate getFileSize(filePath: string): string {\n\t\tif (!filePath) return \"in-memory\";\n\t\ttry {\n\t\t\tconst stats = statSync(filePath);\n\t\t\tconst bytes = stats.size;\n\t\t\tif (bytes < 1024) return `${bytes} B`;\n\t\t\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\t\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n\t\t} catch {\n\t\t\treturn \"N/A\";\n\t\t}\n\t}\n\n\tprivate async getFkReferencesForTable(\n\t\tclient: SqlExecutor,\n\t\ttableName: string,\n\t): Promise<ForeignKeyConstraint[]> {\n\t\tconst fks = await all<{ child: string; from: string; to: string | null }>(\n\t\t\tclient,\n\t\t\t`SELECT m.name AS child, f.\"from\", f.\"to\"\n\t\t\tFROM sqlite_master m JOIN pragma_foreign_key_list(m.name) f\n\t\t\tWHERE m.type = 'table' AND m.name NOT LIKE 'sqlite_%' AND m.name != ? AND f.\"table\" = ?`,\n\t\t\t[tableName, tableName],\n\t\t);\n\t\treturn fks.map((fk) => ({\n\t\t\tconstraintName: `fk_${fk.child}_${fk.from}_${tableName}_${fk.to}`,\n\t\t\treferencingTable: fk.child,\n\t\t\treferencingColumn: fk.from,\n\t\t\treferencedTable: tableName,\n\t\t\treferencedColumn: fk.to ?? \"\",\n\t\t}));\n\t}\n\n\tprivate async getRelatedRecordsForTable(\n\t\tclient: SqlExecutor,\n\t\ttableName: string,\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getFkReferencesForTable(client, tableName);\n\t\tconst results: RelatedRecord[] = [];\n\t\tfor (const fk of fks) {\n\t\t\tconst rows = await all(client, `SELECT * FROM \"${fk.referencingTable}\" LIMIT 100`);\n\t\t\tif (rows.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: rows,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate async getRelatedRecords(\n\t\tclient: SqlExecutor,\n\t\ttableName: string,\n\t\tprimaryKeys: DeleteRecordParams[\"primaryKeys\"],\n\t): Promise<RelatedRecord[]> {\n\t\tconst fks = await this.getFkReferencesForTable(client, tableName);\n\t\tconst results: RelatedRecord[] = [];\n\t\tfor (const fk of fks) {\n\t\t\tconst matchingPk = primaryKeys.find((pk) => pk.columnName === fk.referencedColumn);\n\t\t\tif (!matchingPk) continue;\n\t\t\tconst pkValues = primaryKeys.map((pk) => pk.value);\n\t\t\tconst ph = pkValues.map(() => \"?\").join(\", \");\n\t\t\tconst rows = await all(\n\t\t\t\tclient,\n\t\t\t\t`SELECT * FROM \"${fk.referencingTable}\" WHERE \"${fk.referencingColumn}\" IN (${ph}) LIMIT 100`,\n\t\t\t\tpkValues,\n\t\t\t);\n\t\t\tif (rows.length > 0) {\n\t\t\t\tresults.push({\n\t\t\t\t\ttableName: fk.referencingTable,\n\t\t\t\t\tcolumnName: fk.referencingColumn,\n\t\t\t\t\tconstraintName: fk.constraintName,\n\t\t\t\t\trecords: rows,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n}\n","import { adapterRegistry } from \"@/adapters/adapter.registry.js\";\nimport { ClickhouseAdapter } from \"@/adapters/clickhouse/clickhouse.adapter.js\";\nimport { DuckDbAdapter } from \"@/adapters/duckdb/duckdb.adapter.js\";\nimport { MongoAdapter } from \"@/adapters/mongo/mongo.adapter.js\";\nimport { MsSqlAdapter } from \"@/adapters/mssql/mssql.adapter.js\";\nimport { MySqlAdapter } from \"@/adapters/mysql/mysql.adapter.js\";\nimport { OracleAdapter } from \"@/adapters/oracle/oracle.adapter.js\";\nimport { PgAdapter } from \"@/adapters/pg/pg.adapter.js\";\nimport { RedisAdapter } from \"@/adapters/redis/redis.adapter.js\";\nimport { SqliteAdapter } from \"@/adapters/sqlite/sqlite.adapter.js\";\n\n/**\n * Registers all DB adapters with the registry before routes are mounted.\n */\nexport function registerAdapters(): void {\n\tadapterRegistry.register(\"pg\", new PgAdapter());\n\tadapterRegistry.register(\"mysql\", new MySqlAdapter());\n\tadapterRegistry.register(\"mssql\", new MsSqlAdapter());\n\tadapterRegistry.register(\"mongodb\", new MongoAdapter());\n\tadapterRegistry.register(\"sqlite\", new SqliteAdapter());\n\tadapterRegistry.register(\"redis\", new RedisAdapter());\n\tadapterRegistry.register(\"duckdb\", new DuckDbAdapter());\n\tadapterRegistry.register(\"oracle\", new OracleAdapter());\n\n\tadapterRegistry.register(\"clickhouse\", new ClickhouseAdapter());\n}\n","import type { ApiError } from \"@db-studio/shared/types/api-response.types.js\";\nimport type { Context } from \"hono\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { DatabaseError } from \"pg\";\nimport { ZodError } from \"zod\";\nimport {\n\tcaptureServerError,\n\tdatabaseTypeForRequest,\n\toperationForRequest,\n\twriteOperationalLog,\n} from \"@/observability.js\";\n\n/** HTTPException leaves `name` as \"Error\", so it needs an explicit check. */\nconst errorTypeName = (e: unknown): string => {\n\tif (e instanceof HTTPException) return \"HTTPException\";\n\treturn e instanceof Error ? e.name : \"UnknownError\";\n};\n\nconst isConnectionError = (e: Error): boolean => {\n\tconst mysqlError = e as Error & { code?: string; errno?: number };\n\tconst isMysqlConnectionError =\n\t\tmysqlError.code === \"ECONNREFUSED\" ||\n\t\tmysqlError.code === \"ENOTFOUND\" ||\n\t\tmysqlError.code === \"ETIMEDOUT\" ||\n\t\tmysqlError.code === \"ER_ACCESS_DENIED_ERROR\" ||\n\t\tmysqlError.code === \"ER_BAD_HOST_ERROR\" ||\n\t\tmysqlError.code === \"ECONNRESET\" ||\n\t\tmysqlError.errno === 1045 ||\n\t\tmysqlError.errno === 2003 ||\n\t\tmysqlError.errno === 2002;\n\n\treturn (\n\t\tisMysqlConnectionError ||\n\t\te.message.includes(\"ECONNREFUSED\") ||\n\t\te.message.includes(\"connection refused\") ||\n\t\te.message.includes(\"timeout expired\") ||\n\t\te.message.includes(\"Connection terminated\") ||\n\t\te.message.includes(\"MongoNetworkError\") ||\n\t\te.message.includes(\"MongoServerSelectionError\") ||\n\t\t(e instanceof DatabaseError && e.code?.startsWith(\"08\") === true)\n\t);\n};\n\nconst statusForError = (e: unknown): number => {\n\tif (e instanceof HTTPException) return e.status;\n\tif (e instanceof ZodError) return 400;\n\tif (e instanceof Error && isConnectionError(e)) return 503;\n\treturn 500;\n};\n\n/**\n * Centralized error handler for the application\n */\nexport function handleError(e: Error | unknown, c: Context) {\n\tconst operation = operationForRequest(c.req.method, c.req.path);\n\tconst errorType = errorTypeName(e);\n\tconst status = statusForError(e);\n\twriteOperationalLog(\"error\", \"request_failed\", { operation, error_type: errorType });\n\tcaptureServerError(e, {\n\t\toperation,\n\t\tstatus,\n\t\tdbType: databaseTypeForRequest(c.req.path),\n\t});\n\n\tif (e instanceof HTTPException) {\n\t\treturn c.json<ApiError>(\n\t\t\t{\n\t\t\t\terror: e.message ?? \"Internal server error\",\n\t\t\t},\n\t\t\te.status,\n\t\t);\n\t}\n\n\tif (e instanceof ZodError) {\n\t\tconst issue = e.issues[0];\n\t\treturn c.json<ApiError>(\n\t\t\t{\n\t\t\t\terror: \"Validation error\",\n\t\t\t\tdetails: issue.message,\n\t\t\t},\n\t\t\t400,\n\t\t);\n\t}\n\n\tif (e instanceof Error) {\n\t\tif (isConnectionError(e)) {\n\t\t\treturn c.json<ApiError>(\n\t\t\t\t{ error: \"Database connection failed\", details: e.message },\n\t\t\t\t503,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn c.json<ApiError>(\n\t\t{\n\t\t\terror: e instanceof Error ? e.message : \"Internal server error\",\n\t\t},\n\t\t500,\n\t);\n}\n\nexport const validationHook = (\n\tresult: {\n\t\tsuccess: boolean;\n\t\tdata?: unknown;\n\t\terror?: { issues: { message: string }[] };\n\t},\n\tc: Context,\n): Response | undefined => {\n\tif (!result.success) {\n\t\tconst issue = result.error?.issues[0];\n\t\treturn c.json<ApiError>(\n\t\t\t{\n\t\t\t\terror: \"Validation error\",\n\t\t\t\tdetails: issue?.message ?? \"Unknown validation error\",\n\t\t\t},\n\t\t\t400,\n\t\t);\n\t}\n};\n","import { DATABASE_ENGINES, type DatabaseSchema } from \"@db-studio/shared/types\";\n\n/**\n * Generate system prompt with database context\n */\nexport function generateSystemPrompt(schema: DatabaseSchema | null): string {\n\tif (!schema) {\n\t\treturn `You are a database assistant for db-studio. Keep answers concise and focused.\n\nThe user chose not to share their database schema. Do not claim to know their table or column names. Ask for the minimum missing details needed to answer accurately, generate queries in fenced code blocks, and warn before potentially destructive or expensive operations.`;\n\t}\n\n\tconst dbTypeLower = schema.dbType.toLowerCase();\n\tconst dbTypeLabel = DATABASE_ENGINES[schema.dbType].label;\n\tif (dbTypeLower.includes(\"mongo\")) {\n\t\treturn `You are a database assistant for db-studio. Your responses must be CONCISE and FOCUSED.\n\n**Your Role:**\n1. Keep responses SHORT - 2-3 sentences maximum unless generating a query\n2. When generating MongoDB queries:\n - Provide 1 sentence explanation\n - The MongoDB query in a JSON code block\n - 1 sentence about expected results\n3. Use exact collection/field names from the schema\n4. If query is unclear, ask ONE specific clarifying question\n5. No preamble, no apologies, get straight to the answer\n6. IMPORTANT: When the user asks about collections, fields, or any schema information, answer DIRECTLY from the \"Database Context\" above — do NOT generate a query to retrieve schema info you already have\n\n**Database Context:**\n${formatSchemaForPrompt(schema)}\n\n**Guidelines:**\n1. Always generate syntactically correct MongoDB queries\n2. Use proper collection/field names exactly as defined in the schema\n3. When generating queries, wrap them in \\`\\`\\`json code blocks\n4. Explain what the query does in plain language\n5. Suggest relevant follow-up questions or analyses\n6. If a request is ambiguous, ask clarifying questions\n7. Warn about potentially expensive operations (collection scans, large aggregations)\n8. Consider data privacy - remind users not to share sensitive data externally\n\n**Query Format:**\nReturn a JSON object with the following shape:\n{\n \"collection\": \"collectionName\",\n \"operation\": \"find|aggregate|insertOne|insertMany|updateOne|updateMany|deleteOne|deleteMany|count\",\n \"filter\": { ... },\n \"pipeline\": [ ... ],\n \"document\": { ... } | [ ... ],\n \"update\": { ... },\n \"options\": { ... },\n \"sort\": { \"field\": 1 },\n \"limit\": 100,\n \"skip\": 0\n}\n\nOnly include the fields needed for the chosen operation.\n\n**Example:**\nUser: \"Show me the top 5 customers by revenue\"\n\nResponse: \"I'll aggregate orders to calculate total revenue per customer.\n\n\\`\\`\\`json\n{\n \"collection\": \"orders\",\n \"operation\": \"aggregate\",\n \"pipeline\": [\n { \"$group\": { \"_id\": \"$customer_id\", \"total\": { \"$sum\": \"$total_amount\" } } },\n { \"$sort\": { \"total\": -1 } },\n { \"$limit\": 5 }\n ]\n}\n\\`\\`\\`\n\nThis will return the top 5 customers by revenue.\"`;\n\t}\n\n\treturn `You are a database assistant for db-studio. Your responses must be CONCISE and FOCUSED.\n\n**Your Role:**\n1. Keep responses SHORT - 2-3 sentences maximum unless generating SQL\n2. When generating SQL:\n - Provide 1 sentence explanation\n - The SQL query in a code block\n - 1 sentence about expected results\n - NO verbose explanations\n3. Use exact table/column names from the schema\n4. Generate valid ${dbTypeLabel} syntax\n5. If query is unclear, ask ONE specific clarifying question\n6. No preamble, no apologies, get straight to the answer\n7. IMPORTANT: When the user asks about tables, columns, relationships, or any schema information, answer DIRECTLY from the \"Database Context\" above — do NOT generate a SQL query to retrieve schema info you already have\n\n**Database Context:**\n${formatSchemaForPrompt(schema)}\n\n**Guidelines:**\n1. Always generate syntactically correct SQL for the database type (${dbTypeLabel})\n2. Use proper table/column names exactly as defined in the schema\n3. When generating queries, wrap them in \\`\\`\\`sql code blocks\n4. Explain what the query does in plain language\n5. Suggest relevant follow-up questions or analyses\n6. If a request is ambiguous, ask clarifying questions\n7. For complex queries, break down the logic step-by-step\n8. Warn about potentially expensive operations (full table scans, etc.)\n9. Consider data privacy - remind users not to share sensitive data externally\n\n**Response Format:**\nWhen generating queries, use this structure:\n- Brief explanation of what you'll do\n- The SQL query in a code block\n- Expected results description\n- Optional: suggestions for related queries\n\n**Example:**\nUser: \"Show me the top 5 customers by revenue\"\n\nResponse: \"I'll query the orders and customers tables to find your highest-value customers.\n\n\\`\\`\\`sql\nSELECT \n c.customer_name,\n SUM(o.total_amount) as total_revenue\nFROM customers c\nJOIN orders o ON c.id = o.customer_id\nGROUP BY c.id, c.customer_name\nORDER BY total_revenue DESC\nLIMIT 5;\n\\`\\`\\`\n\nThis will return the 5 customers with the highest total order value. You might also want to see:\n- Revenue trends over time for these customers\n- Their most frequently ordered products\"`;\n}\n\n/**\n * Format schema information for the prompt\n */\nfunction formatSchemaForPrompt(schema: DatabaseSchema): string {\n\tconst dbTypeLabel = DATABASE_ENGINES[schema.dbType].label;\n\tlet output = `Database Type: ${dbTypeLabel}\\n\\n`;\n\n\toutput += \"**Tables and Columns:**\\n\";\n\tfor (const table of schema.tables) {\n\t\toutput += `\\n### ${table.name}\\n`;\n\t\tif (table.description) {\n\t\t\toutput += `Description: ${table.description}\\n`;\n\t\t}\n\t\toutput += \"Columns:\\n\";\n\n\t\tfor (const col of table.columns) {\n\t\t\tconst pkIndicator = col.isPrimaryKey ? \" [PRIMARY KEY]\" : \"\";\n\t\t\tconst fkIndicator = col.foreignKey ? ` [FK -> ${col.foreignKey}]` : \"\";\n\t\t\tconst nullable = col.nullable ? \"NULL\" : \"NOT NULL\";\n\n\t\t\toutput += ` - ${col.name}: ${col.type} ${nullable}${pkIndicator}${fkIndicator}\\n`;\n\t\t\tif (col.description) {\n\t\t\t\toutput += ` ${col.description}\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Add sample data if available\n\t\tif (table.sampleData && table.sampleData.length > 0) {\n\t\t\toutput += `Sample data (${table.sampleData.length} rows):\\n`;\n\t\t\toutput += `${JSON.stringify(table.sampleData.slice(0, 3), null, 2)}\\n`;\n\t\t}\n\t}\n\n\t// Add relationships\n\tif (schema.relationships && schema.relationships.length > 0) {\n\t\toutput += \"\\n**Relationships:**\\n\";\n\t\tfor (const rel of schema.relationships) {\n\t\t\toutput += ` - ${rel.fromTable}.${rel.fromColumn} -> ${rel.toTable}.${rel.toColumn}\\n`;\n\t\t}\n\t}\n\n\treturn output;\n}\n","import type {\n\tColumn,\n\tColumnInfoSchemaType,\n\tDatabaseSchema,\n\tDatabaseSchemaType,\n\tRelationship,\n\tTable,\n} from \"@db-studio/shared/types\";\nimport type { IDbAdapter } from \"@/adapters/adapter.interface.js\";\nimport { getAdapter } from \"@/adapters/adapter.registry.js\";\nimport { getDbType } from \"@/db-manager.js\";\n\nfunction convertColumnInfo(col: ColumnInfoSchemaType): Column {\n\tconst column: Column = {\n\t\tname: col.columnName,\n\t\ttype: col.dataTypeLabel,\n\t\tnullable: col.isNullable,\n\t};\n\n\tif (col.isPrimaryKey) {\n\t\tcolumn.isPrimaryKey = true;\n\t}\n\n\tif (col.isForeignKey && col.referencedTable && col.referencedColumn) {\n\t\tcolumn.foreignKey = `${col.referencedTable}.${col.referencedColumn}`;\n\t}\n\n\tif (col.enumValues && col.enumValues.length > 0) {\n\t\tcolumn.enumValues = col.enumValues;\n\t\tcolumn.description = `Enum values: ${col.enumValues.join(\", \")}`;\n\t}\n\n\treturn column;\n}\n\nfunction extractRelationships(tables: Table[]): Relationship[] {\n\tconst relationships: Relationship[] = [];\n\n\tfor (const table of tables) {\n\t\tfor (const column of table.columns) {\n\t\t\tif (column.foreignKey) {\n\t\t\t\tconst [toTable, toColumn] = column.foreignKey.split(\".\");\n\t\t\t\trelationships.push({\n\t\t\t\t\tfromTable: table.name,\n\t\t\t\t\tfromColumn: column.name,\n\t\t\t\t\ttoTable,\n\t\t\t\t\ttoColumn,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn relationships;\n}\n\nfunction stringifySampleValue(value: unknown): string {\n\tif (value == null) {\n\t\treturn \"\";\n\t}\n\n\tif (value instanceof Date) {\n\t\treturn value.toISOString();\n\t}\n\n\tif (typeof value === \"bigint\") {\n\t\treturn value.toString();\n\t}\n\n\tif (typeof value === \"object\") {\n\t\ttry {\n\t\t\treturn JSON.stringify(value);\n\t\t} catch {\n\t\t\treturn String(value);\n\t\t}\n\t}\n\n\treturn String(value);\n}\n\nasync function getSampleData(\n\tadapter: IDbAdapter,\n\ttableName: string,\n\tdb: DatabaseSchemaType[\"db\"],\n): Promise<Record<string, string>[]> {\n\ttry {\n\t\tconst result = await adapter.getTableData({ tableName, db, limit: 3 });\n\t\treturn result.data.map((row) =>\n\t\t\tObject.fromEntries(\n\t\t\t\tObject.entries(row).map(([key, value]) => [key, stringifySampleValue(value)]),\n\t\t\t),\n\t\t);\n\t} catch (error) {\n\t\tconsole.warn(`Could not fetch sample data for table ${tableName}:`, error);\n\t\treturn [];\n\t}\n}\n\nasync function getTableColumns(\n\tadapter: IDbAdapter,\n\ttableName: string,\n\tdb: DatabaseSchemaType[\"db\"],\n): Promise<ColumnInfoSchemaType[]> {\n\ttry {\n\t\treturn await adapter.getTableColumns({ tableName, db });\n\t} catch (error) {\n\t\tconsole.warn(`Could not fetch columns for table ${tableName}:`, error);\n\t\treturn [];\n\t}\n}\n\nasync function getDatabaseSchema(\n\tdb: DatabaseSchemaType[\"db\"],\n\toptions: {\n\t\tincludeSampleData?: boolean;\n\t\tincludeDescriptions?: boolean;\n\t\tmaxTables?: number;\n\t} = {},\n): Promise<DatabaseSchema> {\n\tconst dbType = getDbType();\n\tconst { includeSampleData = false, maxTables } = options;\n\tconst adapter = getAdapter(dbType);\n\n\ttry {\n\t\tconst tablesList = await adapter.getTablesList(db);\n\t\tconst selectedTables = tablesList.slice(0, maxTables ?? tablesList.length);\n\n\t\tconst tablePromises = selectedTables.map(async ({ schemaName, tableName }) => {\n\t\t\tconst [columns, sampleData] = await Promise.all([\n\t\t\t\tgetTableColumns(adapter, tableName, db),\n\t\t\t\tincludeSampleData ? getSampleData(adapter, tableName, db) : Promise.resolve([]),\n\t\t\t]);\n\n\t\t\tconst table: Table = {\n\t\t\t\tname: schemaName ? `${schemaName}.${tableName}` : tableName,\n\t\t\t\tcolumns: columns.map(convertColumnInfo),\n\t\t\t};\n\n\t\t\tif (sampleData.length > 0) {\n\t\t\t\ttable.sampleData = sampleData;\n\t\t\t}\n\n\t\t\treturn table;\n\t\t});\n\n\t\tconst tables = await Promise.all(tablePromises);\n\t\tconst relationships = extractRelationships(tables);\n\n\t\treturn { dbType, tables, relationships };\n\t} catch (error) {\n\t\tconsole.error(\"Error fetching database schema:\", error);\n\t\tthrow new Error(\n\t\t\t`Failed to fetch database schema: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t);\n\t}\n}\n\nexport async function getDetailedSchema(\n\tdb: DatabaseSchemaType[\"db\"],\n): Promise<DatabaseSchema> {\n\treturn getDatabaseSchema(db, {\n\t\tincludeSampleData: true,\n\t\tincludeDescriptions: true,\n\t});\n}\n","import { DEFAULTS, LIMIT } from \"@db-studio/shared/constants\";\nimport { chatSchema } from \"@db-studio/shared/types\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { RouteEnv } from \"@/app.types.js\";\nimport { generateSystemPrompt } from \"@/utils/system-prompt-generator.js\";\nimport { getDetailedSchema } from \"@/utils/table-details-schema.js\";\n\nconst LOOPBACK_HOSTNAMES = new Set([\"localhost\", \"127.0.0.1\", \"::1\", \"[::1]\"]);\n\n/**\n * BYOK API keys are forwarded to the proxy as request headers, so the\n * destination must be encrypted. `DB_STUDIO_PROXY_URL` can override the HTTPS\n * default, so plain HTTP is only tolerated when it points at loopback — the\n * local `bun run dev` proxy.\n */\nconst resolveProxyUrl = (): string => {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(DEFAULTS.PROXY_URL);\n\t} catch {\n\t\tthrow new HTTPException(500, {\n\t\t\tmessage: \"DB_STUDIO_PROXY_URL is not a valid URL\",\n\t\t});\n\t}\n\n\tconst isLoopback =\n\t\tLOOPBACK_HOSTNAMES.has(url.hostname) || url.hostname.endsWith(\".localhost\");\n\tif (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && isLoopback)) {\n\t\tthrow new HTTPException(500, {\n\t\t\tmessage: \"DB_STUDIO_PROXY_URL must use HTTPS unless it points at loopback\",\n\t\t});\n\t}\n\n\treturn url.origin;\n};\n\nexport const chatRoutes = new Hono<RouteEnv>()\n\t/**\n\t * Base path for the endpoints, /:dbType/chat/...\n\t */\n\t.basePath(\"/chat\")\n\n\t/**\n\t * GET /chat/limit - Proxy rate limit check to Cloudflare Worker\n\t */\n\t.get(\"/limit\", async (c) => {\n\t\t// Outside the try: a misconfigured proxy URL is a server error, not an\n\t\t// exhausted quota, so it must not be masked by the fallback below.\n\t\tconst proxyUrl = resolveProxyUrl();\n\n\t\ttry {\n\t\t\tconst proxyResponse = await fetch(`${proxyUrl}/chat/limit`, {\n\t\t\t\theaders: {\n\t\t\t\t\t\"cf-connecting-ip\": c.req.header(\"cf-connecting-ip\") ?? \"\",\n\t\t\t\t\t\"x-real-ip\": c.req.header(\"x-real-ip\") ?? \"\",\n\t\t\t\t\t\"x-forwarded-for\": c.req.header(\"x-forwarded-for\") ?? \"\",\n\t\t\t\t\t\"x-api-key\": c.req.header(\"x-api-key\") ?? \"\",\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (!proxyResponse.ok) {\n\t\t\t\treturn c.json({ limit: LIMIT, used: LIMIT, remaining: 0 }, 200);\n\t\t\t}\n\t\t\treturn c.json(await proxyResponse.json(), 200);\n\t\t} catch {\n\t\t\treturn c.json({ limit: LIMIT, used: LIMIT, remaining: 0 }, 200);\n\t\t}\n\t})\n\n\t/**\n\t * POST /chat - Handle AI chat requests with streaming\n\t * Proxies to the Cloudflare Worker which has the Gemini API key\n\t */\n\t.post(\"/\", zValidator(\"json\", chatSchema), async (c) => {\n\t\tconst { messages, data, provider, model } = c.req.valid(\"json\");\n\t\tconst { db, conversationId, includeSchema } = data;\n\n\t\t// Get the database schema and generate system prompt\n\t\tconst schema = includeSchema ? await getDetailedSchema(db) : null;\n\t\tconst systemPrompt = generateSystemPrompt(schema);\n\n\t\tconst payload = {\n\t\t\tmessages,\n\t\t\tconversationId,\n\t\t\tsystemPrompt,\n\t\t\tprovider,\n\t\t\tmodel,\n\t\t};\n\n\t\t// Forward request to the proxy with the system prompt.\n\t\t// Pass through IP headers so the proxy rate-limiter keys on the real user IP.\n\t\tconst proxyResponse = await fetch(`${resolveProxyUrl()}/chat`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"cf-connecting-ip\": c.req.header(\"cf-connecting-ip\") ?? \"\",\n\t\t\t\t\"x-real-ip\": c.req.header(\"x-real-ip\") ?? \"\",\n\t\t\t\t\"x-forwarded-for\": c.req.header(\"x-forwarded-for\") ?? \"\",\n\t\t\t\t\"x-api-key\": c.req.header(\"x-api-key\") ?? \"\",\n\t\t\t\t\"x-byok-gemini\": c.req.header(\"x-byok-gemini\") ?? \"\",\n\t\t\t\t\"x-byok-openai\": c.req.header(\"x-byok-openai\") ?? \"\",\n\t\t\t\t\"x-byok-anthropic\": c.req.header(\"x-byok-anthropic\") ?? \"\",\n\t\t\t\t\"x-byok-grok\": c.req.header(\"x-byok-grok\") ?? \"\",\n\t\t\t\t\"x-byok-openrouter\": c.req.header(\"x-byok-openrouter\") ?? \"\",\n\t\t\t},\n\t\t\tbody: JSON.stringify(payload),\n\t\t});\n\n\t\tif (!proxyResponse.ok) {\n\t\t\tconst errorData = await proxyResponse.json();\n\t\t\treturn c.json(\n\t\t\t\t{ error: errorData.error || \"Proxy request failed\" },\n\t\t\t\tproxyResponse.status as 400 | 401 | 500,\n\t\t\t);\n\t\t}\n\n\t\t// Relay the original stream directly. A detached pipe can reject after this\n\t\t// handler returns, which makes the browser see only a generic body-read error.\n\t\treturn new Response(proxyResponse.body, {\n\t\t\tstatus: proxyResponse.status,\n\t\t\theaders: proxyResponse.headers,\n\t\t});\n\t});\n\nexport type ChatRoutes = typeof chatRoutes;\n","import type {\n\tConnectionInfoSchemaType,\n\tCurrentDatabaseSchemaType,\n\tDatabaseListSchemaType,\n} from \"@db-studio/shared/types\";\nimport { Hono } from \"hono\";\nimport { getAdapter } from \"@/adapters/adapter.registry.js\";\nimport type { ApiHandler } from \"@/app.types.js\";\nimport { getDbType } from \"@/db-manager.js\";\n\n/**\n * /databases routes (at root level, no dbType required)\n * GET /databases - Get list of user-visible databases on the server (name, size, owner, encoding).\n * System databases are hidden unless currently connected (pg: postgres, rdsadmin, mysql:\n * information_schema/mysql/performance_schema/sys, mssql: database_id <= 4,\n * mongo: admin/config/local, sqlite: temp).\n * GET /databases/current - Get the name of the database we are currently connected to\n * GET /databases/connection - Get connection details and server information\n */\nexport const databasesRoutes = new Hono()\n\t/**\n\t * Base path for the endpoints, /databases/...\n\t */\n\t.basePath(\"/databases\")\n\n\t/**\n\t * GET /databases\n\t * Returns list of user-visible databases on the server (name, size, owner, encoding) and the database type\n\t */\n\t.get(\"/\", async (c): ApiHandler<DatabaseListSchemaType> => {\n\t\tconst dbType = getDbType();\n\t\tconst dao = getAdapter(dbType);\n\t\tconst databases = await dao.getDatabasesList();\n\t\treturn c.json({ data: { databases, dbType } }, 200);\n\t})\n\n\t/**\n\t * GET /databases/current\n\t * Returns the name of the database we are currently connected to and the database type\n\t */\n\t.get(\"/current\", async (c): ApiHandler<CurrentDatabaseSchemaType> => {\n\t\tconst dbType = getDbType();\n\t\tconst dao = getAdapter(dbType);\n\t\tconst current = await dao.getCurrentDatabase();\n\t\treturn c.json({ data: { db: current.db, dbType } }, 200);\n\t})\n\n\t/**\n\t * GET /databases/connection\n\t * Returns connection details and server information\n\t */\n\t.get(\"/connection\", async (c): ApiHandler<ConnectionInfoSchemaType> => {\n\t\tconst dbType = getDbType();\n\t\tconst dao = getAdapter(dbType);\n\t\tconst info = await dao.getDatabaseConnectionInfo();\n\t\treturn c.json({ data: info }, 200);\n\t});\n\nexport type DatabasesRoutes = typeof databasesRoutes.routes;\n","import {\n\tcreateKeySchema,\n\ttype DeleteKeyResultSchemaType,\n\tdatabaseSchema,\n\tdeleteKeyQuerySchema,\n\ttype KeyDetailsResultSchemaType,\n\ttype KeyRawResultSchemaType,\n\ttype KeyScanResultSchemaType,\n\ttype KeyWriteResultSchemaType,\n\tkeyActionSchema,\n\tkeyDetailsQuerySchema,\n\tkeyParamSchema,\n\tkeyRawQuerySchema,\n\tkeyScanQuerySchema,\n} from \"@db-studio/shared/types\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { assertKeyValueAdapter, getAdapter } from \"@/adapters/adapter.registry.js\";\nimport type { ApiHandler, RouteEnv } from \"@/app.types.js\";\n\nexport const keysRoutes = new Hono<RouteEnv>()\n\t.basePath(\"/keys\")\n\t.get(\n\t\t\"/\",\n\t\tzValidator(\"query\", keyScanQuerySchema),\n\t\tasync (c): ApiHandler<KeyScanResultSchemaType> => {\n\t\t\tconst query = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst adapter = assertKeyValueAdapter(getAdapter(dbType), dbType);\n\t\t\treturn c.json({ data: await adapter.scanKeys(query) }, 200);\n\t\t},\n\t)\n\t.post(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", createKeySchema),\n\t\tasync (c): ApiHandler<KeyWriteResultSchemaType> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst adapter = assertKeyValueAdapter(getAdapter(dbType), dbType);\n\t\t\treturn c.json({ data: await adapter.createKey({ db, ...body }) }, 200);\n\t\t},\n\t)\n\t.get(\n\t\t\"/:key/raw\",\n\t\tzValidator(\"param\", keyParamSchema),\n\t\tzValidator(\"query\", keyRawQuerySchema),\n\t\tasync (c): ApiHandler<KeyRawResultSchemaType> => {\n\t\t\tconst { key } = c.req.valid(\"param\");\n\t\t\tconst query = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst adapter = assertKeyValueAdapter(getAdapter(dbType), dbType);\n\t\t\treturn c.json({ data: await adapter.getStringChunk({ ...query, key }) }, 200);\n\t\t},\n\t)\n\t.get(\n\t\t\"/:key\",\n\t\tzValidator(\"param\", keyParamSchema),\n\t\tzValidator(\"query\", keyDetailsQuerySchema),\n\t\tasync (c): ApiHandler<KeyDetailsResultSchemaType> => {\n\t\t\tconst { key } = c.req.valid(\"param\");\n\t\t\tconst query = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst adapter = assertKeyValueAdapter(getAdapter(dbType), dbType);\n\t\t\treturn c.json({ data: await adapter.getKeyDetails({ ...query, key }) }, 200);\n\t\t},\n\t)\n\t.post(\n\t\t\"/:key/actions\",\n\t\tzValidator(\"param\", keyParamSchema),\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", keyActionSchema),\n\t\tasync (c): ApiHandler<KeyWriteResultSchemaType> => {\n\t\t\tconst { key } = c.req.valid(\"param\");\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst adapter = assertKeyValueAdapter(getAdapter(dbType), dbType);\n\t\t\treturn c.json({ data: await adapter.applyKeyAction({ db, key, ...body }) }, 200);\n\t\t},\n\t)\n\t.delete(\n\t\t\"/:key\",\n\t\tzValidator(\"param\", keyParamSchema),\n\t\tzValidator(\"query\", deleteKeyQuerySchema),\n\t\tasync (c): ApiHandler<DeleteKeyResultSchemaType> => {\n\t\t\tconst { key } = c.req.valid(\"param\");\n\t\t\tconst query = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst adapter = assertKeyValueAdapter(getAdapter(dbType), dbType);\n\t\t\treturn c.json({ data: await adapter.deleteKey({ ...query, key }) }, 200);\n\t\t},\n\t);\n\nexport type KeysRoutes = typeof keysRoutes.routes;\n","import {\n\tdatabaseSchema,\n\ttype ExecuteQueryResult,\n\texecuteQuerySchema,\n} from \"@db-studio/shared/types\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { getAdapter } from \"@/adapters/adapter.registry.js\";\nimport type { ApiHandler, RouteEnv } from \"@/app.types.js\";\n\nexport const queryRoutes = new Hono<RouteEnv>()\n\t/**\n\t * Base path for the endpoints, /:dbType/query/...\n\t */\n\t.basePath(\"/query\")\n\n\t/**\n\t * POST /query\n\t * Executes a SQL query on the currently connected database\n\t */\n\t.post(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", executeQuerySchema),\n\t\tasync (c): ApiHandler<ExecuteQueryResult> => {\n\t\t\tconst { query } = c.req.valid(\"json\");\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst data = await dao.executeQuery({ query, db });\n\t\t\treturn c.json({ data }, 200);\n\t\t},\n\t);\n\nexport type QueryRoutes = typeof queryRoutes;\n","import {\n\taddRecordSchema,\n\tbulkInsertRecordsSchema,\n\ttype DeleteRecordResult,\n\tdatabaseSchema,\n\tdeleteRecordSchema,\n\tupdateRecordsSchema,\n} from \"@db-studio/shared/types\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { getAdapter } from \"@/adapters/adapter.registry.js\";\nimport type { ApiHandler, RouteEnv } from \"@/app.types.js\";\n\nexport const recordsRoutes = new Hono<RouteEnv>()\n\t/**\n\t * Base path for the endpoints, /:dbType/records/...\n\t */\n\t.basePath(\"/records\")\n\n\t/**\n\t * POST /records\n\t * Adds a new record into a table\n\t */\n\t.post(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", addRecordSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName, data } = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst { insertedCount } = await dao.addRecord({ db, params: { tableName, data } });\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Record inserted into \"${tableName}\" with ${insertedCount} rows inserted`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * PATCH /records\n\t * Updates one or more cells in a table\n\t */\n\t.patch(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", updateRecordsSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst params = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst { updatedCount } = await dao.updateRecords({ params, db });\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Updated ${updatedCount} records in \"${params.tableName}\"`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * DELETE /records\n\t * Deletes records from a table\n\t */\n\t.delete(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", deleteRecordSchema),\n\t\tasync (c): ApiHandler<DeleteRecordResult, 409 | 200> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName, primaryKeys } = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst { deletedCount, fkViolation, relatedRecords } = await dao.deleteRecords({\n\t\t\t\ttableName,\n\t\t\t\tprimaryKeys,\n\t\t\t\tdb,\n\t\t\t});\n\t\t\tif (fkViolation) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tdeletedCount: 0,\n\t\t\t\t\t\t\tfkViolation: true,\n\t\t\t\t\t\t\trelatedRecords,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t409,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdeletedCount,\n\t\t\t\t\t\tfkViolation: false,\n\t\t\t\t\t\trelatedRecords: [],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * DELETE /records/force\n\t * Force deletes records and all related FK records\n\t */\n\t.delete(\n\t\t\"/force\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", deleteRecordSchema),\n\t\tasync (c): ApiHandler<{ deletedCount: number }> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName, primaryKeys } = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst deletedCount = await dao.forceDeleteRecords({ tableName, primaryKeys, db });\n\t\t\treturn c.json({ data: deletedCount }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * POST /records/bulk\n\t * Bulk inserts multiple records into a table\n\t */\n\t.post(\n\t\t\"/bulk\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", bulkInsertRecordsSchema),\n\t\tasync (c): ApiHandler<object> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName, records } = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst result = await dao.bulkInsertRecords({ tableName, records, db });\n\t\t\tconsole.log(\"result\", result);\n\t\t\treturn c.json({ data: result }, 200);\n\t\t},\n\t);\n\nexport type RecordsRoutes = typeof recordsRoutes;\n","import type { CellValue, FormatType } from \"@db-studio/shared/types\";\nimport { utils, write } from \"xlsx\";\n\ninterface ExportFileOptions {\n\tcols: string[];\n\trows: Record<string, unknown>[];\n\tformat: FormatType;\n\ttableName: string;\n}\n\n/**\n * Flatten a value into the scalar `CellValue` contract that the sheet writer\n * accepts. Arrays and nested objects (Mongo documents, Postgres `jsonb`, MySQL\n * `json`) are JSON-serialized so they no longer land in the sheet as\n * \"[object Object]\", and binary columns render as `0x`-prefixed hex rather than\n * a serialized Buffer. Scalars pass through untouched.\n *\n * Only CSV and XLSX need this — the JSON export keeps the nested structure.\n */\nconst toCellValue = (value: unknown): CellValue => {\n\tif (value === null || value === undefined) return value;\n\tif (value instanceof Date) return value;\n\t// BLOB/bytea/varbinary arrive as Buffers from the sqlite adapter, mssql and mysql2.\n\t// JSON.stringify would turn them into {\"type\":\"Buffer\",\"data\":[...]}.\n\tif (Buffer.isBuffer(value)) return `0x${value.toString(\"hex\")}`;\n\tif (typeof value === \"object\") return JSON.stringify(value);\n\tif (typeof value === \"bigint\") return value.toString();\n\treturn value as CellValue;\n};\n\nconst toSheetData = (cols: string[], rows: Record<string, unknown>[]): CellValue[][] => [\n\tcols,\n\t...(rows?.map((row) => cols?.map((col) => toCellValue(row[col]))) ?? []),\n];\n\n/**\n * Converts table data to the specified export format (CSV, XLSX, or JSON)\n *\n * @param options - The export options\n * @param options.cols - Array of column names\n * @param options.rows - Array of row data objects\n * @param options.format - The export format ('csv', 'xlsx', or 'json')\n * @param options.tableName - The name of the table being exported\n * @returns The file content as a Uint8Array\n */\nexport function getExportFile({ cols, rows, format, tableName }: ExportFileOptions): BodyInit {\n\tswitch (format) {\n\t\tcase \"json\": {\n\t\t\tconst jsonContent = JSON.stringify(rows ?? [], null, 2);\n\t\t\treturn new Uint8Array(Buffer.from(jsonContent, \"utf-8\"));\n\t\t}\n\n\t\tcase \"csv\": {\n\t\t\tconst worksheet = utils.aoa_to_sheet(toSheetData(cols, rows));\n\t\t\tconst csvContent = utils.sheet_to_csv(worksheet);\n\t\t\treturn new Uint8Array(Buffer.from(csvContent, \"utf-8\"));\n\t\t}\n\n\t\tcase \"xlsx\": {\n\t\t\tconst worksheet = utils.aoa_to_sheet(toSheetData(cols, rows));\n\t\t\tconst workbook = utils.book_new();\n\t\t\tutils.book_append_sheet(workbook, worksheet, tableName.slice(0, 31));\n\t\t\tconst buffer = write(workbook, {\n\t\t\t\tbookType: \"xlsx\",\n\t\t\t\ttype: \"buffer\",\n\t\t\t}) as Buffer;\n\t\t\treturn new Uint8Array(buffer);\n\t\t}\n\t}\n}\n","import {\n\taddColumnSchema,\n\talterColumnSchema,\n\ttype ColumnInfoSchemaType,\n\tcreateTableSchema,\n\ttype DeleteTableResult,\n\tdatabaseSchema,\n\tdeleteColumnParamSchema,\n\tdeleteColumnQuerySchema,\n\tdeleteTableQuerySchema,\n\texportTableSchema,\n\trenameColumnSchema,\n\trenameTableSchema,\n\ttype TableDataResultSchemaType,\n\ttype TableInfoSchemaType,\n\ttype TableSchemaResult,\n\ttableDataQuerySchema,\n\ttableNameSchema,\n} from \"@db-studio/shared/types\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { getAdapter } from \"@/adapters/adapter.registry.js\";\nimport type { ApiHandler, RouteEnv } from \"@/app.types.js\";\nimport { getExportFile } from \"@/utils/get-export-file.js\";\n\nexport const tablesRoutes = new Hono<RouteEnv>()\n\t/**\n\t * Base path for the endpoints, /:dbType/tables/...\n\t */\n\t.basePath(\"/tables\")\n\n\t/**\n\t * GET /tables\n\t * Returns list of all tables in the currently connected database\n\t */\n\t.get(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tasync (c): ApiHandler<TableInfoSchemaType[]> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst tablesList = await dao.getTablesList(db);\n\t\t\treturn c.json({ data: tablesList }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * POST /tables\n\t * Creates a new table in the currently connected database\n\t */\n\t.post(\n\t\t\"/\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"json\", createTableSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tawait dao.createTable({ tableData: body, db });\n\t\t\treturn c.json({ data: `Table ${body.tableName} created successfully` }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * DELETE /tables/:tableName\n\t * Deletes a table from the database\n\t */\n\t.delete(\n\t\t\"/:tableName\",\n\t\tzValidator(\"query\", deleteTableQuerySchema),\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tasync (c): ApiHandler<DeleteTableResult> => {\n\t\t\tconst { db, cascade } = c.req.valid(\"query\");\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst result = await dao.deleteTable({ tableName, db, cascade });\n\t\t\treturn c.json({ data: result }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * PATCH /tables/:tableName/rename\n\t * Renames a table\n\t */\n\t.patch(\n\t\t\"/:tableName/rename\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tzValidator(\"json\", renameTableSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tawait dao.renameTable({ tableName, db, ...body });\n\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Table \"${tableName}\" renamed to \"${body.newTableName}\"`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * DELETE /tables/:tableName/columns/:columnName\n\t * Deletes a column from a table\n\t */\n\t.delete(\n\t\t\"/:tableName/columns/:columnName\",\n\t\tzValidator(\"query\", deleteColumnQuerySchema),\n\t\tzValidator(\"param\", deleteColumnParamSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db, cascade } = c.req.valid(\"query\");\n\t\t\tconst { tableName, columnName } = c.req.valid(\"param\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst { deletedCount } = await dao.deleteColumn({ tableName, columnName, cascade, db });\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Column \"${columnName}\" deleted successfully from table \"${tableName}\" with ${deletedCount} rows deleted`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * POST /tables/:tableName/columns\n\t * Adds a column to a table\n\t */\n\t.post(\n\t\t\"/:tableName/columns\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tzValidator(\"json\", addColumnSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tawait dao.addColumn({ tableName, db, ...body });\n\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Column \"${body.columnName}\" added successfully to table \"${tableName}\"`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * PATCH /tables/:tableName/columns/:columnName/rename\n\t * Renames a column in a table\n\t */\n\t.patch(\n\t\t\"/:tableName/columns/:columnName/rename\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"param\", deleteColumnParamSchema),\n\t\tzValidator(\"json\", renameColumnSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName, columnName } = c.req.valid(\"param\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tawait dao.renameColumn({ tableName, columnName, db, ...body });\n\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Column \"${columnName}\" renamed to \"${body.newColumnName}\" in table \"${tableName}\"`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * PATCH /tables/:tableName/columns/:columnName\n\t * Alters a column in a table\n\t */\n\t.patch(\n\t\t\"/:tableName/columns/:columnName\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"param\", deleteColumnParamSchema),\n\t\tzValidator(\"json\", alterColumnSchema),\n\t\tasync (c): ApiHandler<string> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName, columnName } = c.req.valid(\"param\");\n\t\t\tconst body = c.req.valid(\"json\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tawait dao.alterColumn({ tableName, columnName, db, ...body });\n\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tdata: `Column \"${columnName}\" updated successfully in table \"${tableName}\"`,\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t},\n\t)\n\n\t/**\n\t * GET /tables/:tableName/columns\n\t * Returns list of all columns in a table\n\t */\n\t.get(\n\t\t\"/:tableName/columns\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tasync (c): ApiHandler<ColumnInfoSchemaType[]> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst columns = await dao.getTableColumns({ tableName, db });\n\t\t\treturn c.json({ data: columns }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * GET /tables/:tableName/schema\n\t * Returns the CREATE TABLE schema for a table\n\t */\n\t.get(\n\t\t\"/:tableName/schema\",\n\t\tzValidator(\"query\", databaseSchema),\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tasync (c): ApiHandler<TableSchemaResult> => {\n\t\t\tconst { db } = c.req.valid(\"query\");\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst schema = await dao.getTableSchema({ tableName, db });\n\t\t\treturn c.json({ data: { schema } }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * GET /tables/:tableName/data\n\t * Get cursor-paginated data for a table\n\t */\n\t.get(\n\t\t\"/:tableName/data\",\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tzValidator(\"query\", tableDataQuerySchema),\n\t\tasync (c): ApiHandler<TableDataResultSchemaType> => {\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst { cursor, limit, direction, sort, order, filters, db } = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\t\t\tconst tableData = await dao.getTableData({\n\t\t\t\ttableName,\n\t\t\t\tcursor,\n\t\t\t\tlimit,\n\t\t\t\tdirection,\n\t\t\t\tsort,\n\t\t\t\torder,\n\t\t\t\tfilters,\n\t\t\t\tdb,\n\t\t\t});\n\t\t\treturn c.json({ data: tableData }, 200);\n\t\t},\n\t)\n\n\t/**\n\t * GET /tables/:tableName/export\n\t * Export table data to CSV or XLSX format\n\t */\n\t.get(\n\t\t\"/:tableName/export\",\n\t\tzValidator(\"param\", tableNameSchema),\n\t\tzValidator(\"query\", exportTableSchema),\n\t\tasync (c) => {\n\t\t\tconst { tableName } = c.req.valid(\"param\");\n\t\t\tconst { db, format } = c.req.valid(\"query\");\n\t\t\tconst dbType = c.get(\"dbType\");\n\t\t\tconst dao = getAdapter(dbType);\n\n\t\t\tconst { cols, rows } = await dao.exportTableData({ tableName, db });\n\t\t\tconst fileContent = getExportFile({ cols, rows, format, tableName });\n\t\t\tlet contentType: string | undefined;\n\n\t\t\tswitch (format) {\n\t\t\t\tcase \"csv\":\n\t\t\t\t\tcontentType = \"text/csv\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"xlsx\":\n\t\t\t\t\tcontentType = \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"json\":\n\t\t\t\t\tcontentType = \"application/json\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn new Response(fileContent, {\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": contentType ?? \"\",\n\t\t\t\t\t\"Content-Disposition\": `attachment; filename=\"${tableName}_export.${format}\"`,\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t);\n\nexport type TablesRoutes = typeof tablesRoutes.routes;\n","import { Hono } from \"hono\";\nimport { z } from \"zod\";\nimport type { ApiHandler } from \"@/app.types.js\";\nimport {\n\tcaptureInstallationActive,\n\tgetTelemetryConfig,\n\tresetTelemetryId,\n\tsetTelemetryEnabled,\n} from \"@/observability.js\";\n\nconst preferenceSchema = z.object({ enabled: z.boolean() }).strict();\n\nexport const telemetryRoutes = new Hono()\n\t.basePath(\"/telemetry\")\n\t.get(\"/config\", async (c): ApiHandler<ReturnType<typeof getTelemetryConfig>> => {\n\t\tif (c.req.header(\"x-db-studio-gpc\") === \"1\" || c.req.header(\"sec-gpc\") === \"1\") {\n\t\t\tsetTelemetryEnabled(false);\n\t\t}\n\t\tcaptureInstallationActive();\n\t\treturn c.json({ data: getTelemetryConfig() }, 200);\n\t})\n\t.put(\n\t\t\"/preference\",\n\t\tasync (c): ApiHandler<ReturnType<typeof getTelemetryConfig>, 200 | 400> => {\n\t\t\tconst parsed = preferenceSchema.safeParse(await c.req.json().catch(() => undefined));\n\t\t\tif (!parsed.success) return c.json({ error: \"Invalid telemetry preference\" }, 400);\n\t\t\tsetTelemetryEnabled(parsed.data.enabled);\n\t\t\treturn c.json({ data: getTelemetryConfig() }, 200);\n\t\t},\n\t)\n\t.post(\n\t\t\"/reset\",\n\t\tasync (c): ApiHandler<{ installationId: string }> =>\n\t\t\tc.json({ data: { installationId: resetTelemetryId() } }, 200),\n\t);\n\nexport type TelemetryRoutes = typeof telemetryRoutes.routes;\n","import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { DEFAULTS } from \"@db-studio/shared/constants\";\nimport type { DatabaseTypeSchema } from \"@db-studio/shared/types\";\nimport { serveStatic } from \"@hono/node-server/serve-static\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport { HTTPException } from \"hono/http-exception\";\nimport { logger } from \"hono/logger\";\nimport { prettyJSON } from \"hono/pretty-json\";\nimport { z } from \"zod\";\nimport { adapterRegistry } from \"@/adapters/adapter.registry.js\";\nimport { registerAdapters } from \"@/adapters/register.js\";\nimport type { AppType } from \"@/app.types.js\";\nimport { handleError } from \"@/middlewares/error-handler.js\";\nimport {\n\tcaptureServerEvent,\n\tdurationBucket,\n\toperationForRequest,\n\toutcomeForStatus,\n\tstartServerSpan,\n} from \"@/observability.js\";\nimport { chatRoutes } from \"@/routes/chat.routes.js\";\nimport { databasesRoutes } from \"@/routes/databases.routes.js\";\nimport { keysRoutes } from \"@/routes/keys.routes.js\";\nimport { queryRoutes } from \"@/routes/query.routes.js\";\nimport { recordsRoutes } from \"@/routes/records.routes.js\";\nimport { tablesRoutes } from \"@/routes/tables.routes.js\";\nimport { telemetryRoutes } from \"@/routes/telemetry.routes.js\";\n\nconst { API_PREFIX } = DEFAULTS;\n\n/**\n * Get the path to the web app distribution directory.\n */\nconst getWebDistPath = () => {\n\tif (process.env.NODE_ENV === \"development\") {\n\t\treturn path.resolve(process.cwd(), \"../web/dist\");\n\t}\n\n\tconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\tconst bundledWebDistPath = path.resolve(__dirname, \"./web-dist\");\n\tconst localWebDistPath = path.resolve(process.cwd(), \"../web/dist\");\n\n\tconst bundledIndexPath = path.resolve(bundledWebDistPath, \"index.html\");\n\tconst localIndexPath = path.resolve(localWebDistPath, \"index.html\");\n\n\tif (!existsSync(bundledIndexPath) && existsSync(localIndexPath)) {\n\t\treturn localWebDistPath;\n\t}\n\n\treturn bundledWebDistPath;\n};\n\nconst databaseTypeParamSchema = z.object({\n\tdbType: z\n\t\t.string()\n\t\t.refine(\n\t\t\t(type): type is DatabaseTypeSchema =>\n\t\t\t\tadapterRegistry.getSupportedTypes().includes(type as DatabaseTypeSchema),\n\t\t\t{\n\t\t\t\tmessage: `Invalid database type. Supported types: ${adapterRegistry\n\t\t\t\t\t.getSupportedTypes()\n\t\t\t\t\t.join(\", \")}`,\n\t\t\t},\n\t\t),\n});\n\nexport const createServer = () => {\n\tregisterAdapters();\n\n\tconst app = new Hono<AppType>({ strict: false })\n\t\t/**\n\t\t * Enable CORS.\n\t\t *\n\t\t * Same-origin by default: the SPA is served from the same origin as the\n\t\t * API, so no cross-origin access is needed. An empty allowlist means no\n\t\t * allow-origin header is emitted for cross-origin requests, which\n\t\t * prevents drive-by-localhost attacks (any other browser tab issuing\n\t\t * cross-origin reads/edits/drops against the user's DB).\n\t\t *\n\t\t * Deployments that genuinely need cross-origin access (e.g. a hosted\n\t\t * fork serving the SPA from a different origin) set `ALLOWED_ORIGINS` to\n\t\t * a comma-separated list of explicit origins. Never `*`.\n\t\t */\n\t\t.use(\n\t\t\t\"/*\",\n\t\t\tcors({\n\t\t\t\torigin: (origin) => {\n\t\t\t\t\tif (!origin) return undefined;\n\t\t\t\t\tconst allowed =\n\t\t\t\t\t\tprocess.env.ALLOWED_ORIGINS?.split(\",\")\n\t\t\t\t\t\t\t.map((o) => o.trim())\n\t\t\t\t\t\t\t.filter(Boolean) ?? [];\n\t\t\t\t\tif (allowed.includes(origin)) return origin;\n\t\t\t\t\tif (process.env.NODE_ENV === \"development\") {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst url = new URL(origin);\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\turl.hostname === \"localhost\" ||\n\t\t\t\t\t\t\t\turl.hostname.endsWith(\".localhost\") ||\n\t\t\t\t\t\t\t\turl.hostname === \"127.0.0.1\"\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn origin;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {}\n\t\t\t\t\t}\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t\tallowMethods: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"],\n\t\t\t\tallowHeaders: [\n\t\t\t\t\t\"Content-Type\",\n\t\t\t\t\t\"X-Run-Id\",\n\t\t\t\t\t\"X-DB-Studio-GPC\",\n\t\t\t\t\t\"x-byok-gemini\",\n\t\t\t\t\t\"x-byok-openai\",\n\t\t\t\t\t\"x-byok-anthropic\",\n\t\t\t\t\t\"x-byok-grok\",\n\t\t\t\t\t\"x-byok-openrouter\",\n\t\t\t\t],\n\t\t\t\tmaxAge: 600,\n\t\t\t}),\n\t\t)\n\n\t\t/**\n\t\t * Pretty print the JSON response\n\t\t */\n\t\t.use(prettyJSON({ space: 2 }))\n\n\t\t/**\n\t\t * Enable logger in development mode\n\t\t */\n\t\t.use(process.env.NODE_ENV === \"development\" ? logger() : (_, next) => next())\n\n\t\t.use(`${API_PREFIX}/*`, async (c, next) => {\n\t\t\tif (c.req.path.startsWith(`${API_PREFIX}/telemetry`)) return next();\n\t\t\tconst startedAt = performance.now();\n\t\t\tconst operation = operationForRequest(c.req.method, c.req.path);\n\t\t\tconst rawType = c.req.path.split(\"/\")[2];\n\t\t\tconst dbType = adapterRegistry\n\t\t\t\t.getSupportedTypes()\n\t\t\t\t.find((candidate) => candidate === rawType);\n\t\t\tawait startServerSpan(operation, dbType, next);\n\t\t\tcaptureServerEvent({\n\t\t\t\tevent: \"server_operation\",\n\t\t\t\tproperties: {\n\t\t\t\t\toperation,\n\t\t\t\t\tmethod: c.req.method,\n\t\t\t\t\toutcome: outcomeForStatus(c.res.status),\n\t\t\t\t\tduration_bucket: durationBucket(performance.now() - startedAt),\n\t\t\t\t\tdb_type: dbType,\n\t\t\t\t},\n\t\t\t});\n\t\t})\n\n\t\t/**\n\t\t * Serve the favicon.ico file\n\t\t */\n\t\t.use(\n\t\t\t\"/favicon.ico\",\n\t\t\tserveStatic({\n\t\t\t\tpath: path.resolve(getWebDistPath(), \"favicon.ico\"),\n\t\t\t}),\n\t\t)\n\n\t\t/**\n\t\t * Handle errors\n\t\t */\n\t\t.onError(handleError)\n\n\t\t/**\n\t\t * API routes are namespaced under API_PREFIX so they never collide with\n\t\t * client-side (SPA) routes served from the same origin. A refresh on a\n\t\t * client route like `/table/:name` must fall through to index.html, not\n\t\t * be interpreted as a `/:dbType/...` API request. See db-studio#214.\n\t\t *\n\t\t * Database routes - available at the API root (no dbType required)\n\t\t */\n\t\t.route(API_PREFIX, databasesRoutes)\n\t\t.route(API_PREFIX, chatRoutes)\n\t\t.route(API_PREFIX, telemetryRoutes)\n\n\t\t/**\n\t\t * Serve static assets (SPA-owned; live at the root, not under the API prefix)\n\t\t */\n\t\t.use(\"/assets/*\", serveStatic({ root: getWebDistPath() }))\n\t\t.use(\"/image.png\", serveStatic({ root: getWebDistPath() }))\n\n\t\t/**\n\t\t * Routes that require dbType validation - under API_PREFIX/:dbType/...\n\t\t */\n\t\t.use(\n\t\t\t`${API_PREFIX}/:dbType/*`,\n\t\t\tzValidator(\"param\", databaseTypeParamSchema, (result, c) => {\n\t\t\t\tif (!result.success) {\n\t\t\t\t\tconst rawType = c.req.param(\"dbType\");\n\t\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\t\tmessage: `Invalid database type: \"${rawType}\". Supported types: ${adapterRegistry.getSupportedTypes().join(\", \")}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}),\n\t\t\tasync (c, next) => {\n\t\t\t\tconst { dbType } = databaseTypeParamSchema.parse({ dbType: c.req.param(\"dbType\") });\n\t\t\t\tc.set(\"dbType\", dbType);\n\t\t\t\tawait next();\n\t\t\t},\n\t\t)\n\t\t.route(`${API_PREFIX}/:dbType`, tablesRoutes)\n\t\t.route(`${API_PREFIX}/:dbType`, recordsRoutes)\n\t\t.route(`${API_PREFIX}/:dbType`, queryRoutes)\n\t\t.route(`${API_PREFIX}/:dbType`, keysRoutes);\n\n\tif (process.env.NODE_ENV !== \"test\") {\n\t\t/**\n\t\t * Any unmatched API path is a genuine 404 - respond with JSON so API\n\t\t * clients never receive the SPA's index.html HTML by mistake.\n\t\t */\n\t\tapp.all(`${API_PREFIX}/*`, (c) => c.json({ error: \"Not found\" }, 404));\n\n\t\t/**\n\t\t * SPA fallback - every non-API path serves the client app so that\n\t\t * deep-link refreshes (e.g. /table/:name) load index.html.\n\t\t */\n\t\tapp.use(\"/*\", serveStatic({ root: getWebDistPath() }));\n\t\tapp.get(\"/*\", serveStatic({ path: path.resolve(getWebDistPath(), \"index.html\") }));\n\t}\n\n\treturn { app };\n};\n\nexport type { AppType };\n\n// Export the app type for hc client\nexport type AppRoutes = ReturnType<typeof createServer>[\"app\"];\n","\n import \"_sentry-debug-id-injection-stub\";\n import * as OriginalModule from \"./src/index.ts\";\n export default OriginalModule.default;\n export * from \"./src/index.ts\";","!function(){try{var e=\"undefined\"!=typeof window?window:\"undefined\"!=typeof global?global:\"undefined\"!=typeof globalThis?globalThis:\"undefined\"!=typeof self?self:{};var n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]=\"86de4c89-127a-4461-864f-505b73881ed5\",e._sentryDebugIdIdentifier=\"sentry-dbid-86de4c89-127a-4461-864f-505b73881ed5\");}catch(e){}}();","import { intro, log, outro, spinner } from \"@clack/prompts\";\nimport { DEFAULTS } from \"@db-studio/shared/constants\";\nimport { serve } from \"@hono/node-server\";\nimport color from \"picocolors\";\nimport { args } from \"@/cmd/args.js\";\nimport { getDatabaseUrl } from \"@/cmd/get-db-url.js\";\nimport { loadEnv } from \"@/cmd/load-env.js\";\nimport { openBrowser, shouldOpenBrowser } from \"@/cmd/open-browser.js\";\nimport { sanitizeErrorMessage } from \"@/cmd/sanitize-error.js\";\nimport { showHelp } from \"@/cmd/show-help.js\";\nimport { showStatus } from \"@/cmd/show-status.js\";\nimport { showVersion } from \"@/cmd/show-version.js\";\n\nexport const main = async () => {\n\tconst { env, port, databaseUrl, varName, open, status, help, version } = args();\n\n\t// Handle help flag\n\tif (help) {\n\t\tshowHelp();\n\t\tprocess.exit(0);\n\t}\n\n\t// Handle version flag\n\tif (version) {\n\t\tshowVersion();\n\t\tprocess.exit(0);\n\t}\n\n\t// Handle status flag\n\tif (status) {\n\t\tawait showStatus(env, databaseUrl, varName);\n\t\tprocess.exit(0);\n\t}\n\n\tintro(color.inverse(\" db-studio \"));\n\n\tconst ENV = env ? await loadEnv(env) : await loadEnv();\n\n\t// Populate other env variables from .env if not already set in process.env\n\tif (ENV) {\n\t\tfor (const [key, value] of Object.entries(ENV)) {\n\t\t\tif (process.env[key] === undefined) {\n\t\t\t\tprocess.env[key] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst PORT = Number.parseInt(port ?? process.env.PORT ?? String(DEFAULTS.PORT), 10);\n\tconst HOST = process.env.HOST;\n\tconst VAR_NAME = varName || DEFAULTS.VAR_NAME;\n\tconst hasEnvFileValue = Boolean(ENV?.[VAR_NAME]);\n\tconst hasProcessValue = Boolean(process.env[VAR_NAME]);\n\tconst DATABASE_URL = databaseUrl ? databaseUrl : await getDatabaseUrl(ENV, VAR_NAME);\n\tconst configSource = databaseUrl\n\t\t? \"Using database URL from --database-url\"\n\t\t: hasEnvFileValue\n\t\t\t? `Found ${VAR_NAME} in ${env ?? \".env\"}`\n\t\t\t: hasProcessValue\n\t\t\t\t? `Found ${VAR_NAME} in environment`\n\t\t\t\t: \"Using database URL provided interactively\";\n\tlog.success(configSource);\n\n\t// Set DATABASE_URL in process.env before importing createServer\n\t// This ensures the db pool is initialized with the correct connection string\n\tprocess.env.DATABASE_URL = DATABASE_URL;\n\n\tconst { initServerObservability } = await import(\"@/observability.js\");\n\tinitServerObservability();\n\n\t// Import database modules dynamically after setting DATABASE_URL.\n\tconst { checkDatabaseConnection, getDatabaseConnectionDetails } = await import(\n\t\t\"@/cmd/check-database.js\"\n\t);\n\tconst { type, name, destination } = getDatabaseConnectionDetails(DATABASE_URL);\n\tconst connectionSpinner = spinner();\n\tconnectionSpinner.start(`Connecting to ${name}...`);\n\ttry {\n\t\tawait checkDatabaseConnection(type);\n\t\tconnectionSpinner.stop(`Connected to ${name} at ${destination}`);\n\t} catch (error) {\n\t\tconnectionSpinner.stop(`Could not connect to ${name} at ${destination}`);\n\t\tthrow error;\n\t}\n\n\tconst { createServer } = await import(\"./utils/create-server.js\");\n\tconst { app } = createServer();\n\tserve({\n\t\tfetch: app.fetch,\n\t\thostname: HOST,\n\t\tport: PORT,\n\t});\n\n\tconst serverUrl =\n\t\tprocess.env.DB_STUDIO_SERVER_URL ?? process.env.PORTLESS_URL ?? `http://localhost:${PORT}`;\n\n\tlog.success(`Server listening at ${color.cyan(serverUrl)}`);\n\n\tif (shouldOpenBrowser(open)) {\n\t\ttry {\n\t\t\tawait openBrowser(serverUrl);\n\t\t\tlog.success(\"Opened db-studio in your browser\");\n\t\t} catch {\n\t\t\tlog.warn(`Could not open your browser. Visit ${color.cyan(serverUrl)}`);\n\t\t}\n\t}\n\n\toutro(color.green(\"Ready\"));\n};\n\nif (process.env.NODE_ENV !== \"test\") {\n\tmain().catch((error: unknown) => {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\toutro(color.red(`Startup failed: ${sanitizeErrorMessage(message)}`));\n\t\tprocess.exit(1);\n\t});\n}\n","import type { Args } from \"@db-studio/shared/types\";\nimport { program } from \"commander\";\n\n/**\n * Get the arguments from the command line\n */\nexport const args = () => {\n\tprogram\n\t\t.name(\"db-studio\")\n\t\t.option(\"-e, --env <path>\", \"Path to custom .env file\")\n\t\t.option(\"-p, --port <port>\", \"Port to run the server on\")\n\t\t.option(\"-d, --database-url <url>\", \"Database URL to use\")\n\t\t.option(\n\t\t\t\"-n, --var-name <name>\",\n\t\t\t\"Custom environment variable name (default: DATABASE_URL)\",\n\t\t)\n\t\t.option(\"--open\", \"Open db-studio in the default browser\")\n\t\t.option(\"--no-open\", \"Do not open db-studio in the default browser\")\n\t\t.option(\"-s, --status\", \"Show status of the server\")\n\t\t.option(\"-h, --help\", \"Show help\")\n\t\t.option(\"-v, --version\", \"Show version\")\n\t\t.parse(process.argv);\n\n\tconst options = program.opts<Args>();\n\tconst hasOpen = process.argv.includes(\"--open\");\n\tconst hasNoOpen = process.argv.includes(\"--no-open\");\n\tif (hasOpen && hasNoOpen) {\n\t\tprogram.error(\"Do not combine --open and --no-open\");\n\t}\n\tconst open = hasOpen ? true : hasNoOpen ? false : undefined;\n\n\treturn { ...options, open };\n};\n","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport { cancel, isCancel, note, select, spinner, text } from \"@clack/prompts\";\nimport { type DotenvParseOutput, parse as parseDotenv } from \"dotenv\";\nimport color from \"picocolors\";\n\n/**\n * Get the database URL from .env file, then process.env\n */\nexport const getDatabaseUrl = async (env?: DotenvParseOutput | null, varName?: string) => {\n\tconst envVarName = varName || \"DATABASE_URL\";\n\n\tif (env?.[envVarName]) {\n\t\treturn env[envVarName];\n\t}\n\n\t// Fall back to process.env (e.g. from shell or package.json script)\n\tif (process.env[envVarName]) {\n\t\treturn process.env[envVarName];\n\t}\n\n\tconst s = spinner();\n\ts.start(\"Looking for database connection...\");\n\n\tif (!env) {\n\t\tnote(color.red(`No .env file found and ${envVarName} not set in process.env`));\n\t} else {\n\t\tnote(color.red(`${envVarName} not found in .env or process.env`));\n\t}\n\n\tconst choice = await select({\n\t\tmessage: `How do you want to provide ${envVarName}?`,\n\t\toptions: [\n\t\t\t{ value: \"manual\", label: \"Enter connection string manually\" },\n\t\t\t{ value: \"other-env\", label: \"Use different .env file\" },\n\t\t\t// todo: add multiple db connections support\n\t\t\t{ value: \"cancel\", label: \"Cancel / Exit\" },\n\t\t],\n\t\tinitialValue: \"manual\",\n\t});\n\tif (isCancel(choice) || choice === \"cancel\") {\n\t\tcancel(\"No database connection provided. Exiting...\");\n\t\tprocess.exit(0);\n\t}\n\n\tif (choice === \"other-env\") {\n\t\ts.start(\"Waiting for path...\");\n\t\tconst customPath = await text({\n\t\t\tmessage: \"Enter path to .env file\",\n\t\t\tplaceholder: \"~/projects/myapp/.env.local or ./special.env\",\n\t\t\tvalidate(value?: string) {\n\t\t\t\tif (!value?.trim()) return \"Path is required\";\n\t\t\t},\n\t\t});\n\n\t\tif (isCancel(customPath)) {\n\t\t\tcancel(\"Cancelled.\");\n\t\t\tprocess.exit(0);\n\t\t}\n\n\t\ts.stop(\"Trying custom .env...\");\n\n\t\tconst customEnvPath = resolve(customPath);\n\t\ttry {\n\t\t\tconst content = await readFile(customEnvPath, \"utf-8\");\n\t\t\tconst parsed = parseDotenv(content);\n\t\t\tif (parsed[envVarName]) {\n\t\t\t\treturn parsed[envVarName];\n\t\t\t}\n\t\t\tthrow new Error(`${envVarName} still missing in custom file`);\n\t\t} catch (e: unknown) {\n\t\t\tconst error = e as Error;\n\t\t\tcancel(`Cannot read or parse file: ${color.dim(error.message)}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\t// 3. Manual input\n\ts.stop(\"Manual input...\");\n\n\tconst dbUrl = await text({\n\t\tmessage: `Paste your ${envVarName}`,\n\t\tplaceholder:\n\t\t\t\"postgresql://user:password@localhost:5432/mydb or sqlite:///path/to/db.sqlite\",\n\t\tvalidate(value?: string) {\n\t\t\tif (!value?.trim()) return \"Connection string is required!\";\n\t\t\t// SQLite URLs are valid but may not parse with the standard URL constructor\n\t\t\tif (value.trim().startsWith(\"sqlite://\")) return undefined;\n\t\t\ttry {\n\t\t\t\tnew URL(value);\n\t\t\t\treturn undefined;\n\t\t\t} catch {\n\t\t\t\treturn \"Must be a valid URL format\";\n\t\t\t}\n\t\t},\n\t});\n\n\tif (isCancel(dbUrl)) {\n\t\tcancel(\"Cancelled.\");\n\t\tprocess.exit(0);\n\t}\n\n\treturn dbUrl.trim();\n};\n","import { access, readFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\n\nimport { parse as parseDotenv } from \"dotenv\";\n\n/**\n * Find .env path: try cwd, then walk up parent directories until root.\n */\nconst findEnvPath = async (startDir: string): Promise<string | null> => {\n\tlet dir = resolve(startDir);\n\tfor (;;) {\n\t\tconst envPath = resolve(dir, \".env\");\n\t\ttry {\n\t\t\tawait access(envPath);\n\t\t\treturn envPath;\n\t\t} catch {\n\t\t\t// ENOENT or other: try parent\n\t\t}\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) return null;\n\t\tdir = parent;\n\t}\n};\n\n/**\n * Load the environment variables from the file.\n * When no path is given: tries current directory, then parent directories until a .env is found.\n * When --env path is given: uses that path only (no walk).\n */\nexport const loadEnv = async (env?: string) => {\n\tlet envPath: string | null;\n\n\tif (env) {\n\t\tenvPath = resolve(env);\n\t} else {\n\t\tenvPath = await findEnvPath(process.cwd());\n\t}\n\n\tif (!envPath) return null;\n\n\ttry {\n\t\tconst content = await readFile(envPath, \"utf-8\");\n\t\treturn parseDotenv(content);\n\t} catch (err) {\n\t\tif (err instanceof Error && err.message.includes(\"ENOENT\")) {\n\t\t\treturn null;\n\t\t}\n\t\tthrow err;\n\t}\n};\n","import open from \"open\";\n\nexport const shouldOpenBrowser = (override?: boolean): boolean => {\n\treturn override === true;\n};\n\nexport const openBrowser = async (url: string): Promise<void> => {\n\tawait open(url);\n};\n","import { DATABASE_ENGINES } from \"@db-studio/shared/types\";\n\nconst SCHEMES = Object.values(DATABASE_ENGINES)\n\t.flatMap(({ protocols }) => protocols)\n\t.map((protocol) => protocol.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"))\n\t.join(\"|\");\nconst CONNECTION_URL = new RegExp(`\\\\b(?:${SCHEMES}):\\\\/\\\\/\\\\S+`, \"gi\");\nconst AUTH_TOKEN = /\\b(authToken=)[^&\\s]+/gi;\n\n/**\n * Redact database connection URLs from error text before printing them.\n * The whole URL is replaced — including hosts and credentials that contain\n * `,` or `)`, such as mongodb replica set URIs — while trailing punctuation\n * that belongs to the surrounding prose is kept.\n */\nexport const sanitizeErrorMessage = (message: string): string => {\n\treturn message\n\t\t.replace(\n\t\t\tCONNECTION_URL,\n\t\t\t(url) => `the configured database${url.match(/[),.]+$/)?.[0] ?? \"\"}`,\n\t\t)\n\t\t.replace(AUTH_TOKEN, \"$1[redacted]\");\n};\n","import { intro, outro } from \"@clack/prompts\";\nimport { META } from \"@db-studio/shared/constants/meta.js\";\nimport { DATABASE_ENGINES } from \"@db-studio/shared/types\";\nimport color from \"picocolors\";\n\n/**\n * Display help information\n */\nexport const showHelp = () => {\n\tintro(color.inverse(\" db-studio \"));\n\n\tconsole.log(color.bold(\"\\nUsage:\"));\n\tconsole.log(\" db-studio [options]\\n\");\n\n\tconsole.log(color.bold(\"Supported Databases:\"));\n\tconsole.log(\n\t\t` ${Object.values(DATABASE_ENGINES)\n\t\t\t.map(({ label }) => label)\n\t\t\t.join(\", \")}\\n`,\n\t);\n\n\tconsole.log(color.bold(\"Options:\"));\n\tconsole.log(\" -e, --env <path> Path to custom .env file\");\n\tconsole.log(\" -p, --port <port> Port to run the server on (default: 3333)\");\n\tconsole.log(\" -d, --database-url <url> Database URL to use\");\n\tconsole.log(\n\t\t\" --open Open db-studio in the default browser (off by default)\",\n\t);\n\tconsole.log(\" --no-open Do not open db-studio in the default browser\");\n\tconsole.log(\n\t\t\" -n, --var-name <name> Custom environment variable name (default: DATABASE_URL)\",\n\t);\n\tconsole.log(\" -s, --status Show status of the database connection\");\n\tconsole.log(\" -h, --help Show this help message\");\n\tconsole.log(\" -v, --version Show version number\\n\");\n\n\tconsole.log(color.bold(\"Examples:\"));\n\tconsole.log(\" db-studio\");\n\tconsole.log(\" db-studio -e .env.local\");\n\tconsole.log(\" db-studio -p 4000\");\n\tconsole.log(\" db-studio -d postgresql://user:pass@localhost:5432/mydb\");\n\tconsole.log(\" db-studio -n MY_DATABASE_URL\");\n\tconsole.log(\" db-studio -e .env.production -n PROD_DB_URL\");\n\tconsole.log(\" db-studio --status\\n\");\n\n\toutro(color.green(`For more information, visit: ${META.SITE_DOCS_LINK}`));\n};\n","import { intro, note, outro } from \"@clack/prompts\";\nimport { DEFAULTS } from \"@db-studio/shared/constants\";\nimport { DATABASE_ENGINES } from \"@db-studio/shared/types\";\nimport color from \"picocolors\";\nimport { loadEnv } from \"@/cmd/load-env.js\";\nimport { DRIVER_ALIASES } from \"@/utils/parse-database-url.js\";\n\n/**\n * Show connection status\n */\nexport const showStatus = async (env?: string, databaseUrl?: string, varName?: string) => {\n\tintro(color.inverse(\" db-studio \"));\n\n\tconst envVarName = varName || DEFAULTS.VAR_NAME;\n\tlet foundUrl: string | null = null;\n\n\t// Check if DATABASE_URL is provided via CLI\n\tif (databaseUrl) {\n\t\tfoundUrl = databaseUrl;\n\t} else {\n\t\t// Try .env file, then process.env\n\t\tconst ENV = env ? await loadEnv(env) : await loadEnv();\n\t\tif (ENV?.[envVarName]) {\n\t\t\tfoundUrl = ENV[envVarName];\n\t\t} else if (process.env[envVarName]) {\n\t\t\tfoundUrl = process.env[envVarName] ?? null;\n\t\t}\n\t}\n\n\tif (foundUrl) {\n\t\toutro(color.green(`✓ Database connection configured (using ${envVarName})`));\n\t} else {\n\t\tnote(color.red(`✗ ${envVarName} not found`), \"Status\");\n\t\tconsole.log(color.yellow(\"\\n To configure database connection:\"));\n\t\tconsole.log(\n\t\t\tcolor.dim(\n\t\t\t\t` • Supported databases: ${Object.values(DATABASE_ENGINES)\n\t\t\t\t\t.map(({ label }) => label)\n\t\t\t\t\t.join(\", \")}`,\n\t\t\t),\n\t\t);\n\t\tconsole.log(\n\t\t\tcolor.dim(\n\t\t\t\t` • Also via wire-compatible URLs: ${Object.keys(DRIVER_ALIASES)\n\t\t\t\t\t.map((scheme) => `${scheme}://`)\n\t\t\t\t\t.join(\", \")}`,\n\t\t\t),\n\t\t);\n\t\tconsole.log(color.dim(` • Add ${envVarName} to your .env file or set it in process.env`));\n\t\tconsole.log(color.dim(\" • Use -d flag: db-studio -d <url>\"));\n\t\tconsole.log(color.dim(\" • Use -e flag: db-studio -e <path-to-env>\"));\n\t\tconsole.log(color.dim(\" • Use -n flag: db-studio -n <var-name>\\n\"));\n\n\t\toutro(color.yellow(\"⚠ No database connection configured\"));\n\t}\n};\n","import { intro, outro } from \"@clack/prompts\";\nimport color from \"picocolors\";\nimport packageJson from \"../../package.json\" with { type: \"json\" };\n\n/**\n * Display version information\n */\nexport const showVersion = () => {\n\tintro(color.inverse(\" db-studio \"));\n\toutro(color.green(`🚀 db-studio v${packageJson.version}`));\n};\n"],"mappings":"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","names":["init_sentry_injection_stub","__esmMin","e","init_chat","__esmMin","init_sentry_injection_stub","init_column_types_mysql","__esmMin","init_sentry_injection_stub","init_column_types_pgsql","__esmMin","init_sentry_injection_stub","env","nodeEnv","DEFAULTS","init_defaults","__esmMin","init_sentry_injection_stub","init_links","__esmMin","init_sentry_injection_stub","META","init_meta","__esmMin","init_sentry_injection_stub","init_proxy_limits","__esmMin","init_sentry_injection_stub","init_constants","__esmMin","init_sentry_injection_stub","init_chat","init_column_types_mysql","init_column_types_pgsql","init_defaults","init_links","init_meta","init_proxy_limits","z","databaseSchema","DATABASE_TYPES","databaseTypeSchema","currentDatabaseSchema","databaseTypeParamSchema","tableNameSchema","init_database_types","__esmMin","init_sentry_injection_stub","z","addColumnSchema","addColumnParamSchema","addColumnParamsSchema","init_add_column_types","__esmMin","init_sentry_injection_stub","init_database_types","tableNameSchema","databaseSchema","z","addRecordSchema","init_add_record_types","__esmMin","init_sentry_injection_stub","z","AI_PROVIDERS","aiProviderSchema","AI_PROVIDER_OPTIONS","getDefaultAiModel","init_ai_provider_types","__esmMin","init_sentry_injection_stub","provider","option","z","deleteColumnQuerySchema","deleteColumnParamSchema","deleteColumnParamsSchema","deleteColumnSuccessResponseSchema","init_delete_column_types","__esmMin","init_sentry_injection_stub","init_database_types","databaseSchema","val","z","alterColumnSchema","alterColumnParamSchema","alterColumnParamsSchema","init_alter_column_types","__esmMin","init_sentry_injection_stub","init_database_types","init_delete_column_types","deleteColumnParamSchema","databaseSchema","init_api_response_types","__esmMin","init_sentry_injection_stub","z","bulkInsertRecordsSchema","init_bulk_insert_records_type","__esmMin","init_sentry_injection_stub","z","messagePart","chatBodySchema","chatSchema","init_chat_types","__esmMin","init_sentry_injection_stub","init_ai_provider_types","init_database_types","aiProviderSchema","databaseSchema","body","getDefaultAiModel","init_cmd_args_types","__esmMin","init_sentry_injection_stub","z","dataTypes","dataTypesSchema","DataTypes","standardizedDataTypes","standardizedDataTypeSchema","columnInfoSchema","init_column_info_types","__esmMin","init_sentry_injection_stub","mapPostgresToDataType","pgType","normalized","DataTypes","standardizeDataTypeLabel","StandardizedDataType","mapMysqlToDataType","mysqlDataType","columnType","fullType","standardizeMysqlDataTypeLabel","mapMssqlToDataType","mssqlDataType","standardizeMssqlDataTypeLabel","mapSqliteToDataType","sqliteType","standardizeSqliteDataTypeLabel","mapDuckdbToDataType","duckdbType","standardizeDuckdbDataTypeLabel","mapOracleToDataType","oracleType","standardizeOracleDataTypeLabel","integer","precision","unwrapClickhouseType","clickhouseType","type","match","mapClickhouseToDataType","standardizeClickhouseDataTypeLabel","init_column_type","__esmMin","init_sentry_injection_stub","init_column_info_types","z","FOREIGN_KEY_ACTIONS","foreignKeyActionSchema","fieldDataSchema","foreignKeyDataSchema","createTableSchema","init_create_table_types","__esmMin","init_sentry_injection_stub","DATABASE_ENGINES","dbTypeFromProtocol","init_database_engines_types","__esmMin","init_sentry_injection_stub","init_database_types","protocol","DATABASE_TYPES","type","z","databaseInfoSchema","databaseListSchema","connectionInfoSchema","init_database_list_types","__esmMin","init_sentry_injection_stub","init_database_types","databaseTypeSchema","init_database_schema_type","__esmMin","init_sentry_injection_stub","z","deleteRecordSchema","init_delete_record_types","__esmMin","init_sentry_injection_stub","z","deleteTableQuerySchema","init_delete_table_types","__esmMin","init_sentry_injection_stub","init_database_types","databaseSchema","val","z","executeQuerySchema","init_execute_query_types","__esmMin","init_sentry_injection_stub","z","FORMAT_TYPES","exportTableSchema","init_export_table_types","__esmMin","init_sentry_injection_stub","init_database_types","databaseSchema","z","redisKeyTypeSchema","encodedRedisValueSchema","keyScanQuerySchema","redisKeySummarySchema","keyScanResultSchema","keyDetailsQuerySchema","keyParamSchema","redisStringValueSchema","redisHashValueSchema","redisListValueSchema","redisSetValueSchema","redisSortedSetValueSchema","redisStreamValueSchema","redisUnknownValueSchema","redisKeyValueSchema","keyDetailsResultSchema","keyRawQuerySchema","keyRawResultSchema","createStringValueSchema","createHashValueSchema","createListValueSchema","createSetValueSchema","createSortedSetValueSchema","createStreamValueSchema","createKeySchema","keyWriteResultSchema","renameKeyActionSchema","setTtlKeyActionSchema","setStringKeyActionSchema","upsertHashKeyActionSchema","deleteHashKeyActionSchema","pushListKeyActionSchema","setListKeyActionSchema","deleteListKeyActionSchema","addSetKeyActionSchema","removeSetKeyActionSchema","upsertSortedSetKeyActionSchema","removeSortedSetKeyActionSchema","appendStreamKeyActionSchema","deleteStreamKeyActionSchema","keyActionSchema","deleteKeyQuerySchema","deleteKeyResultSchema","init_key_browser_types","__esmMin","init_sentry_injection_stub","value","init_rate_limit_response_type","__esmMin","init_sentry_injection_stub","z","renameColumnSchema","renameColumnParamSchema","renameColumnParamsSchema","init_rename_column_types","__esmMin","init_sentry_injection_stub","init_database_types","init_delete_column_types","deleteColumnParamSchema","databaseSchema","z","renameTableSchema","renameTableParamSchema","renameTableParamsSchema","init_rename_table_types","__esmMin","init_sentry_injection_stub","init_database_types","tableNameSchema","databaseSchema","z","filterSchema","sortDirections","sortSchema","tableDataMetaSchema","tableDataResultSchema","tableDataQuerySchema","init_table_data_types","__esmMin","init_sentry_injection_stub","init_database_types","databaseSchema","val","parsed","z","tableInfoSchema","init_table_info_type","__esmMin","init_sentry_injection_stub","z","tableSchemaResultSchema","init_table_schema_types","__esmMin","init_sentry_injection_stub","z","updateRecordsSchema","init_update_recors_types","__esmMin","init_sentry_injection_stub","types_exports","__export","AI_PROVIDERS","AI_PROVIDER_OPTIONS","DATABASE_ENGINES","DATABASE_TYPES","DataTypes","FOREIGN_KEY_ACTIONS","FORMAT_TYPES","StandardizedDataType","addColumnParamSchema","addColumnParamsSchema","addColumnSchema","addRecordSchema","aiProviderSchema","alterColumnParamSchema","alterColumnParamsSchema","alterColumnSchema","bulkInsertRecordsSchema","chatSchema","columnInfoSchema","connectionInfoSchema","createKeySchema","createTableSchema","currentDatabaseSchema","dataTypesSchema","databaseInfoSchema","databaseListSchema","databaseSchema","databaseTypeParamSchema","databaseTypeSchema","dbTypeFromProtocol","deleteColumnParamSchema","deleteColumnParamsSchema","deleteColumnQuerySchema","deleteColumnSuccessResponseSchema","deleteKeyQuerySchema","deleteKeyResultSchema","deleteRecordSchema","deleteTableQuerySchema","encodedRedisValueSchema","executeQuerySchema","exportTableSchema","fieldDataSchema","filterSchema","foreignKeyActionSchema","foreignKeyDataSchema","getDefaultAiModel","keyActionSchema","keyDetailsQuerySchema","keyDetailsResultSchema","keyParamSchema","keyRawQuerySchema","keyRawResultSchema","keyScanQuerySchema","keyScanResultSchema","keyWriteResultSchema","mapClickhouseToDataType","mapDuckdbToDataType","mapMssqlToDataType","mapMysqlToDataType","mapOracleToDataType","mapPostgresToDataType","mapSqliteToDataType","redisKeySummarySchema","redisKeyTypeSchema","redisKeyValueSchema","renameColumnParamSchema","renameColumnParamsSchema","renameColumnSchema","renameTableParamSchema","renameTableParamsSchema","renameTableSchema","sortDirections","sortSchema","standardizeClickhouseDataTypeLabel","standardizeDataTypeLabel","standardizeDuckdbDataTypeLabel","standardizeMssqlDataTypeLabel","standardizeMysqlDataTypeLabel","standardizeOracleDataTypeLabel","standardizeSqliteDataTypeLabel","standardizedDataTypeSchema","tableDataMetaSchema","tableDataQuerySchema","tableDataResultSchema","tableInfoSchema","tableNameSchema","tableSchemaResultSchema","unwrapClickhouseType","updateRecordsSchema","init_types","__esmMin","init_sentry_injection_stub","init_add_column_types","init_add_record_types","init_ai_provider_types","init_alter_column_types","init_api_response_types","init_bulk_insert_records_type","init_chat_types","init_cmd_args_types","init_column_type","init_column_info_types","init_create_table_types","init_database_types","init_database_engines_types","init_database_list_types","init_database_schema_type","init_delete_column_types","init_delete_record_types","init_delete_table_types","init_execute_query_types","init_export_table_types","init_key_browser_types","init_rate_limit_response_type","init_rename_column_types","init_rename_table_types","init_table_data_types","init_table_info_type","init_table_schema_types","init_update_recors_types","parseDatabaseUrl","databaseUrl","url","defaultPortFor","error","DRIVER_ALIASES","toDriverUrl","init_parse_database_url","__esmMin","init_sentry_injection_stub","init_types","scheme","dbType","dbTypeFromProtocol","DATABASE_ENGINES","alias","package_default","init_package","__esmMin","observability_exports","__export","captureInstallationActive","captureServerError","captureServerEvent","databaseTypeForRequest","durationBucket","getTelemetryConfig","initServerObservability","isTelemetryEnabled","operationForRequest","outcomeForStatus","resetTelemetryId","setTelemetryEnabled","startServerSpan","writeOperationalLog","randomUUID","existsSync","mkdirSync","readFileSync","writeFileSync","homedir","platform","path","Sentry","HTTPException","PostHog","isTestOrDevelopment","telemetryStatePath","writeState","createState","readState","state","posthog","OFFICIAL_SENTRY_DSN","OFFICIAL_POSTHOG_KEY","currentState","DB_TYPE_PATH","safeErrorType","safeErrorCode","sanitizedError","init_observability","__esmMin","init_sentry_injection_stub","init_types","init_package","base","value","file","package_default","enabled","durationMs","status","DATABASE_TYPES","method","pathname","pathWithoutType","resource","pattern","sentryDsn","event","span","key","posthogKey","current","lastActive","error","name","code","errno","errorType","sanitized","frames","line","operation","dbType","diagnosticError","errorCode","callback","level","fields","safeFields","resolve","pathToFileURL","ClickHouseLogLevel","createClickhouseClient","DuckDBInstance","createLibsqlClient","Redis","MongoClient","ObjectId","mssql","createMysqlPool","oracledb","Pool","DatabaseManager","databaseManager","getDbPool","getMysqlPool","getMssqlPool","getClickhouseClient","getDbType","getSqliteClient","withDuckdbConnection","getOraclePool","getMongoClient","getMongoDbName","getMongoDb","getRedisClient","getIsolatedRedisClient","getRedisDefaultDb","isValidObjectId","coerceObjectId","init_db_manager","__esmMin","init_sentry_injection_stub","init_types","init_parse_database_url","url","protocol","dbType","dbTypeFromProtocol","supported","DATABASE_ENGINES","label","protocols","databaseUrl","fileDbType","driverUrl","toDriverUrl","detectedType","error","database","sqlitePath","libsqlUrl","client","fn","run","filePath","instance","e","message","open","handle","host","port","user","password","service","connection","_tag","done","pool","connectionString","poolConfig","err","dbName","config","existing","tls","nextClient","raw","dbIndex","index","options","info","version","major","minor","path","parsed","pgClosePromises","mysqlClosePromises","mssqlClosePromises","redisClosePromises","value","check_database_exports","__export","checkDatabaseConnection","getDatabaseConnectionDetails","STARTUP_TIMEOUT_MS","withStartupTimeout","init_check_database","__esmMin","init_sentry_injection_stub","init_types","init_db_manager","init_parse_database_url","operation","timeout","_","reject","databaseUrl","type","getDbType","name","defaultPort","DATABASE_ENGINES","host","port","parseDatabaseUrl","getDbPool","getMysqlPool","getMssqlPool","getMongoClient","getMongoDbName","getSqliteClient","client","getRedisClient","withDuckdbConnection","connection","getOraclePool","getClickhouseClient","HTTPException","getAdapter","dbType","adapterRegistry","assertKeyValueAdapter","adapter","isKeyValueAdapter","AdapterRegistry","init_adapter_registry","__esmMin","init_sentry_injection_stub","type","HTTPException","DatabaseError","notImplemented","method","BaseAdapter","init_base_adapter","__esmMin","init_sentry_injection_stub","pkColumns","err","code","params","keyColumns","missing","column","groups","update","keyValues","value","groupKey","group","sort","order","sorts","tieBreakerDirection","key","s","i","tableName","newTableName","data","cursor","row","out","k","v","db","limit","direction","bundle","countRes","total","rawRows","hasMore","rows","nextCursor","prevCursor","e","sql","_db","_params","getDbPool","getMysqlPool","getMssqlPool","getSqliteClient","withDuckdbConnection","getOraclePool","getMongoClient","getMongoDbName","getMongoDb","getRedisClient","getIsolatedRedisClient","getRedisDefaultDb","getClickhouseClient","init_connections","__esmMin","init_sentry_injection_stub","init_db_manager","database","fn","dbName","dbIndex","buildWhereClause","filters","conditions","values","bind","value","columnName","operator","col","q","buildOrderByClause","sort","order","tieBreakers","sorts","direction","terms","expr","mapColumnTypeToClickhouse","columnType","isArray","supportsJsonType","base","buildClickhouseColumnDefinition","field","name","type","nullable","def","defaultValue","DEFAULT_FUNCTIONS","quoteClickhouseIdentifier","init_clickhouse_query_builder","__esmMin","init_sentry_injection_stub","HTTPException","MUTATION_SETTINGS","isNullableType","toClickhouseValue","ClickhouseAdapter","init_clickhouse_adapter","__esmMin","init_sentry_injection_stub","init_types","init_base_adapter","init_connections","init_parse_database_url","init_clickhouse_query_builder","type","value","base","unwrapClickhouseType","BaseAdapter","db","sql","values","params","i","name","quoteClickhouseIdentifier","nativeType","mapClickhouseToDataType","universalType","rawRows","row","_rows","hasMore","cursor","limit","offset","tableName","table","tieBreakers","bundle","countRows","rows","e","info","host","port","parseDatabaseUrl","tableData","fields","foreignKeys","unique","f","supportsJson","columns","buildClickhouseColumnDefinition","keys","newTableName","col","standardizeClickhouseDataTypeLabel","m","columnName","c","def","column","newColumnName","records","_input","DATABASE_ENGINES","_params","query","cleaned","start","client","getClickhouseClient","firstKeyword","result","meta","data","summary","rowCount","queryParams","settings","filters","sort","order","clause","buildWhereClause","orderBy","buildOrderByClause","n","types","record","shaped","major","minor","actualMajor","actualMinor","buildFilterConditions","filters","conditions","values","filter","col","quoteDuckdbIdent","isNull","buildKeysetPredicate","terms","cursor","backward","branches","equal","equalValues","term","value","descending","nullsLast","placement","after","mapColumnTypeToDuckdb","columnType","isArray","normalized","mapped","whereSql","buildOrderBy","SERIAL_TYPES","isSerialType","init_duckdb_query_builder","__esmMin","init_sentry_injection_stub","name","statSync","DuckDBTypeId","ResultReturnType","StatementType","HTTPException","IN_CURRENT_SCHEMA","BIG_INTEGER_TYPES","toRows","toDuckdbValue","query","execute","inTransaction","placeholders","joinOn","sequenceNamesIn","LIMITATIONS","FK_ACTIONS_DUCKDB_REJECTS","DuckDbAdapter","init_duckdb_adapter","__esmMin","init_sentry_injection_stub","init_types","init_base_adapter","init_connections","init_duckdb_query_builder","reader","types","bigColumns","_","i","rows","row","column","value","conn","sql","values","fn","result","e","fk","c","quoteDuckdbIdent","columns","m","BaseAdapter","_db","withDuckdbConnection","name","nativeType","mapDuckdbToDataType","universalType","_params","rawRows","limitation","signature","params","tableName","limit","direction","sort","order","cursor","filters","primaryKey","terms","backward","filter","buildFilterConditions","cursorData","keyset","buildKeysetPredicate","orderBy","buildOrderBy","select","where","whereSql","countRow","fetched","hasMore","page","cursorOf","t","first","last","hasNextPage","hasPreviousPage","_rowid","rest","tables","table_name","tableData","fields","foreignKeys","rejected","a","sequences","f","columnDefs","field","def","mapColumnTypeToDuckdb","isSerialType","sequence","fkDefs","cascade","referencing","newTableName","references","col","isPrimaryKey","standardizeDuckdbDataTypeLabel","columnName","columnType","defaultValue","isNullable","isUnique","alter","newColumnName","data","keyColumns","groups","total","keyValues","rowUpdates","changed","u","primaryKeys","pkColumn","pk","relatedRecords","records","successCount","statement","record","start","statements","duration","filePath","bytes","side","related","SYSTEM_DATABASES","visibleMongoDatabases","init_mongo_database_visibility","__esmMin","init_sentry_injection_stub","databases","currentDb","visible","db","buildMatchStage","filters","andConditions","filter","field","value","parseFilterValue","op","escapeRegex","buildSortStage","sort","order","s","encodeMongoCursor","offset","decodeMongoCursor","cursor","parsed","init_mongo_pipeline_builder","__esmMin","init_sentry_injection_stub","init_db_manager","raw","trimmed","asNumber","isValidObjectId","coerceObjectId","HTTPException","normalizeValue","normalizeDoc","inferValueType","dataTypeLabel","canCoerce","toMongoId","formatBytes","MONGO_BSON_TYPES","mapBsonType","inferBsonType","resolveFieldDefault","normalizeIdFilter","MongoAdapter","init_mongo_adapter","__esmMin","init_sentry_injection_stub","init_base_adapter","init_connections","init_db_manager","init_mongo_database_visibility","init_parse_database_url","init_mongo_pipeline_builder","value","item","k","v","doc","dt","isValidObjectId","coerceObjectId","bytes","units","i","rawType","n","bson","defaultValue","columnType","filter","obj","BaseAdapter","_params","rawRows","row","name","nativeType","universalType","params","tableName","db","cursor","limit","direction","sort","order","filters","collection","getMongoDb","filterObj","buildMatchStage","sortObj","buildSortStage","safeLimit","decodedOffset","decodeMongoCursor","offset","skip","total","rows","normalizedRows","nextOffset","prevOffset","encodeMongoCursor","e","normalized","databases","getMongoClient","visibleMongoDatabases","getMongoDbName","admin","urlDefaults","parseDatabaseUrl","serverStatus","error","mongoDb","collections","results","col","rowCount","tableData","fields","properties","required","field","bsonType","newTableName","docs","totalDocs","fieldTypes","fieldPresence","key","types","presence","typeList","t","isNullable","schema","documents","columnMap","ensureColumn","columnName","entry","meta","resolvedDefault","existingSchema","reqIndex","newColumnName","data","payload","totalUpdated","keyColumns","column","groups","keyValues","rowUpdates","update","updateSet","result","primaryKeys","pkColumn","pkValues","pk","records","record","query","startTime","message","duration","buildWhereClause","filters","startIdx","conditions","values","idx","filter","col","buildSortClause","sorts","order","s","buildOrderByClause","keyColumns","sortClause","sortColumns","direction","tieBreakers","mapColumnTypeToMssql","columnType","isArray","normalized","formatMssqlDefaultValue","defaultValue","trimmed","buildMssqlColumnDefinition","field","options","mappedType","def","dv","init_mssql_query_builder","__esmMin","init_sentry_injection_stub","HTTPException","MSSQL_FK_VIOLATION","MSSQL_FK_DEPENDENCY","MsSqlAdapter","init_mssql_adapter","__esmMin","init_sentry_injection_stub","init_types","init_base_adapter","init_connections","init_parse_database_url","init_mssql_query_builder","BaseAdapter","db","sql","values","request","getMssqlPool","val","idx","name","nativeType","mapMssqlToDataType","universalType","params","tableName","filters","sort","order","limit","cursor","filterWhere","filterValues","nextIdx","buildWhereClause","sortClause","buildSortClause","currentOffset","countSql","rawRows","row","_rows","hasMore","pool","pkColumns","buildOrderByClause","countRequest","countResult","total","dataRequest","rows","e","result","info","urlDefaults","parseDatabaseUrl","table","tableData","fields","foreignKeys","columnDefs","field","mappedType","mapColumnTypeToMssql","colDef","dv","formatMssqlDefaultValue","constraintDefs","primaryKeyFields","f","fkDefs","fk","cascade","tableCheck","rowCount","relatedRecords","fkConstraints","error","newTableName","targetCheck","schemaResult","columns","col","checkResult","checkEnumMap","r","enumValues","standardizeMssqlDataTypeLabel","columnName","columnType","defaultValue","isPrimaryKey","isNullable","isUnique","isIdentity","colCheck","buildMssqlColumnDefinition","constraintName","nullability","newColumnName","newColCheck","data","booleanColumns","identityResult","identityColumns","value","columnNames","paramNames","_col","keyColumns","groups","transaction","keyValues","rowUpdates","setClauses","u","whereClauses","column","primaryKeys","pkColumn","pkValues","pk","paramList","_","totalRelated","deletedTables","visited","deleteRelatedRecursively","targetTable","targetColumn","visitedSet","key","nestedFks","nestedFk","selectRequest","selectParamList","nestedValues","deleteRequest","deleteParamList","deleteResult","constraint","mainRequest","mainParamList","records","i","record","query","cleanedQuery","start","duration","fks","results","relatedResult","constraintsByTable","constraints","cols","c","checkClause","matches","m","offset","buildWhereClause","filters","conditions","values","filter","col","buildSortClause","sorts","order","s","buildCursorWhereClause","cursorData","direction","sortDirection","sortColumns","operator","columnList","placeholders","queryValues","mapColumnTypeToMysql","columnType","isArray","normalized","formatMysqlDefaultValue","defaultValue","trimmed","buildMysqlColumnDefinition","field","options","mappedType","def","dv","init_mysql_query_builder","__esmMin","init_sentry_injection_stub","HTTPException","MYSQL_FK_VIOLATION","MYSQL_FK_DEPENDENCY","MySqlAdapter","init_mysql_adapter","__esmMin","init_sentry_injection_stub","init_types","init_base_adapter","init_connections","init_parse_database_url","init_mysql_query_builder","BaseAdapter","db","sql","values","pool","getMysqlPool","rows","name","nativeType","mapMysqlToDataType","universalType","params","tableName","cursor","limit","direction","sort","order","filters","sortColumns","effectiveSortDirection","s","filterWhere","filterValues","buildWhereClause","cursorWhere","cursorValues","cursorData","res","buildCursorWhereClause","combinedWhere","sortClause","buildSortClause","effectiveSortClause","col","countSql","rawRows","row","hasMore","createCursor","firstRow","lastRow","nextCursor","prevCursor","pkColumns","cursorColumns","pk","pkTieBreakerCols","tbDir","countRows","total","dataRows","makeCursor","infoRows","connRows","info","urlDefaults","parseDatabaseUrl","tables","table","tableData","fields","foreignKeys","columnDefs","field","buildMysqlColumnDefinition","constraintDefs","primaryKeyFields","f","fkDefs","fk","cascade","tableRows","rowCount","relatedRecords","connection","error","mysqlError","newTableName","targetRows","e","createTableSql","isJsonCheckedText","r","isEnum","dataType","columnType","standardizeMysqlDataTypeLabel","columnName","defaultValue","isPrimaryKey","isNullable","isUnique","isIdentity","isArray","colRows","colDef","result","colRow","newColumnName","newColRows","data","booleanColumns","columns","value","i","c","keyColumns","groups","keyValues","rowUpdates","setClauses","u","whereClauses","column","primaryKeys","pkColumn","pkValues","placeholders","fkConstraints","totalRelated","deletedTables","visited","deleteRelatedRecursively","targetTable","targetColumn","visitedSet","key","nestedFks","nestedFk","nestedPh","selectRows","nestedValues","ph","deleteResult","constraint","mainPh","records","colNames","record","query","cleaned","start","duration","dmlResult","fks","results","relatedRows","constraintsByTable","constraints","cols","match","v","HTTPException","buildFilterConditions","filters","bind","columnTypes","conditions","filter","col","quoteOracleIdent","columnType","isNull","bindOracleValue","formatTemporalColumn","mapColumnTypeToOracle","isArray","native","normalized","formatOracleDefault","defaultValue","trimmed","lower","createBinds","ORACLE_DATE_FORMAT","ORACLE_TIMESTAMP_FORMAT","ORACLE_TIMESTAMP_TZ_FORMAT","ISO_DATE","temporalTypeOf","temporalFormatOf","normalizeTemporalValue","buildOracleSelectList","groupOracleForeignKeys","whereSql","buildOrderBy","SERIAL_TYPES","isSerialType","IDENTITY_CLAUSE","init_oracle_query_builder","__esmMin","init_sentry_injection_stub","name","values","value","type","temporalType","column","format","input","match","year","month","day","hour","minute","second","fraction","zone","wallClock","timestamp","compactZone","placeholder","columns","tableAlias","dataType","projected","rows","constraints","row","existing","terms","toJsonNumber","init_oracle_values","__esmMin","init_sentry_injection_stub","value","number","HTTPException","oracledb","supportsNativeTypes","toHex","fetchTypeHandler","toOracleValue","defaultOf","formatColumnType","columnRef","joinOn","matchesAny","isTemporalMetadata","LIMITATIONS","FK_DELETE_ACTIONS","OracleAdapter","init_oracle_adapter","__esmMin","init_sentry_injection_stub","init_types","init_base_adapter","init_connections","init_parse_database_url","init_oracle_query_builder","init_oracle_values","conn","value","meta","toJsonNumber","columnType","c","column","alias","quoteOracleIdent","fk","index","selection","bind","key","BaseAdapter","_db","sql","values","name","nativeType","mapOracleToDataType","universalType","_params","rawRows","row","limitation","code","fn","getOraclePool","e","result","params","tableName","limit","sort","order","cursor","filters","columns","columnTypes","primaryKey","terms","offset","createBinds","where","whereSql","buildFilterConditions","filterValues","countRow","tableAlias","fetched","buildOracleSelectList","buildOrderBy","hasMore","offsetCursor","at","rows","pool","host","port","parseDatabaseUrl","tables","toCount","t","counts","i","tableData","fields","foreignKeys","native","f","definitions","field","cascade","referencing","newTableName","references","col","type","standardizeOracleDataTypeLabel","columnName","definition","isNullable","defaultValue","mapColumnTypeToOracle","formatOracleDefault","newColumnName","data","types","expressions","bindOracleValue","keyColumns","groups","total","keyValues","rowUpdates","set","u","changed","primaryKeys","pkColumn","deletedCount","relatedRecords","childColumns","records","purge","table","path","deleted","referenced","successCount","record","rowExpressions","trimmed","statement","start","duration","affected","withConstraints","def","isSerialType","IDENTITY_CLAUSE","bytes","r","side","groupOracleForeignKeys","related","buildWhereClause","filters","conditions","values","filter","paramIndex","columnName","buildSortClause","sorts","order","s","buildCursorWhereClause","cursorData","direction","sortDirection","startParamIndex","sortColumns","queryValues","useGreaterThan","columnList","col","placeholders","_","i","operator","resolvedSchemaFor","init_pg_query_builder","__esmMin","init_sentry_injection_stub","tableParam","HTTPException","PgAdapter","init_pg_adapter","__esmMin","init_sentry_injection_stub","init_types","init_base_adapter","init_connections","init_parse_database_url","init_pg_query_builder","BaseAdapter","db","sql","values","getDbPool","name","nativeType","mapPostgresToDataType","universalType","params","tableName","cursor","limit","direction","sort","order","filters","pool","sortColumns","effectiveSortDirection","s","cursorColumns","filterWhere","filterValues","buildWhereClause","cursorWhere","cursorValues","cursorData","res","buildCursorWhereClause","combinedWhere","sortClause","buildSortClause","effectiveSortClause","col","limitParamIndex","countSql","rawRows","row","rows","hasMore","createCursor","data","firstRow","lastRow","nextCursor","prevCursor","pkColumns","keyColumns","key","tieBreakers","tieDirection","countRes","total","usesCtid","extraSelect","_ctid","rest","size","connectionInfoSchema","result","urlDefaults","parseDatabaseUrl","escapeChar","tables","t","tableData","fields","foreignKeys","primaryKey","f","columnDefs","field","def","c","fkDefs","fk","cascade","tableRows","rowCount","error","newTableName","requestedSchema","schemaRows","schemas","r","schemaName","targetRows","e","existsRows","columns","resolvedSchemaFor","constraints","indexes","formatType","data_type","udt_name","character_maximum_length","numeric_precision","numeric_scale","lines","colDefs","constraintMap","arr","constraintDefs","cols","first","colNames","idx","parsedEnumValues","standardizeDataTypeLabel","columnName","columnType","defaultValue","isPrimaryKey","isNullable","isUnique","isIdentity","isArray","colRows","client","newColumnName","colExistsQuery","curRows","nextRows","placeholders","_","i","groups","keyValues","rowUpdates","setClauses","u","whereClauses","column","primaryKeys","pkColumn","pkValues","pk","fkConstraints","totalRelated","deletedTables","deleteRelated","targetTable","targetColumn","nested","nfk","nestedVals","ph","records","successCount","record","query","cleaned","start","duration","fks","results","constraintsByTable","tokenizeCommand","input","out","cur","i","inSingle","inDouble","ch","shapeReply","argv","reply","singleCellFallback","cmd","subcmd","a","zrangeWithScoresShape","compound","shaper","COMMAND_SHAPES","scalarShape","isStringArray","flatArrayShape","isFlatPairArray","statusShape","pairArrayShape","infoShape","xrangeShape","init_redis_command_shaper","__esmMin","init_sentry_injection_stub","v","x","idx","rows","section","line","entry","id","fields","fieldsObj","createHash","randomBytes","HTTPException","z","parseInfoSection","info","out","line","idx","parseKeyspaceInfo","match","extractKey","data","k","extractTtl","t","parsed","stringifyValue","v","coerceObject","value","kind","coerceArray","coerceZsetEntries","arr","entry","obj","score","flatPairsToZsetEntries","reply","i","streamInfoToObject","length","firstEntry","lastEntry","idOf","REDIS_TABLES","TABLE_TO_REDIS_TYPE","SCHEMA_MUTATION_MESSAGE","SORT_UNSUPPORTED_MESSAGE","FILTER_UNSUPPORTED_MESSAGE","PREV_UNSUPPORTED_MESSAGE","SCAN_ROUND_TRIP_CAP","COUNT_CACHE_TTL_MS","COUNT_SCAN_CEILING","MAX_STRING_PREVIEW_BYTES","MAX_STRING_FULL_BYTES","isRedisTable","assertRedisTable","parseDbIndex","encodeKeyBrowserCursor","decodeKeyBrowserCursor","encodeKeyDetailsCursor","decodeKeyDetailsCursor","encodeBinaryValue","escapeRedisGlob","normalizeRedisKeyType","decodeBinaryValue","decodeKeyParam","revisionForDump","conflict","isUnavailableCommandError","assertKeyType","assertTransactionSucceeded","encodeScanCursor","decodeScanCursor","columnInfo","KEY_COL","TTL_COL","TABLE_COLUMNS","SCHEMA_DESCRIPTIONS","RedisAdapter","init_redis_adapter","__esmMin","init_sentry_injection_stub","init_base_adapter","init_connections","init_redis_command_shaper","name","tableName","db","getRedisDefaultDb","env","cursor","utf8","type","dump","error","message","actual","expected","result","failed","overrides","BaseAdapter","_params","rawRows","row","nativeType","_universalType","params","limit","search","exactPattern","dbIndex","client","getRedisClient","scanCursor","decoded","pattern","scanArgs","nextRaw","pageKeys","nextScanCursor","pipeline","key","metadata","index","offset","memory","e","encodedKey","full","direction","typeRaw","ttlMs","memoryRaw","dumpRaw","summary","decodedCursor","readLimit","scanResult","values","next","entries","nextOffset","hasMore","members","boundary","rawEntries","id","fields","lastId","chunk","getIsolatedRedisClient","transaction","field","member","newKey","marker","resultKey","nextDump","total","supportsLogicalDatabases","configReply","keyspaceInfo","keysPerDb","_","serverInfo","clientsInfo","server","clients","maxclients","opts","counts","table","sort","filters","redisType","collectedKeys","rounds","scanComplete","batch","overflow","rows","hasNextPage","nextCursor","keys","ttlPipeline","ttlResults","valuePipeline","valueResults","ttl","raw","cached","results","updates","primaryKey","primaryKeys","pkField","updatesByKey","u","keyStr","existing","updatedCount","nextKeyRaw","nextKey","pk","deletedCount","records","errors","successCount","record","allKeys","c","flat","val","args","query","startTime","argv","tokenizeCommand","cmd","rest","shapeReply","buildWhereClause","filters","conditions","values","filter","col","buildSortClause","sorts","order","s","buildCursorWhereClause","cursorData","direction","sortDirection","sortColumns","operator","columnList","placeholders","queryValues","skipTrivia","sql","from","i","end","hasMultipleStatements","words","depth","sawTerminator","ch","close","CLOSING_QUOTE","word","upper","isTransactionControl","TRANSACTION_CONTROL","init_sqlite_query_builder","__esmMin","init_sentry_injection_stub","statSync","HTTPException","allNamed","toSqliteValue","stmt","MIN_SAFE","MAX_SAFE","fromSqliteValue","toRows","all","isFkViolation","SqliteAdapter","init_sqlite_adapter","__esmMin","init_sentry_injection_stub","init_types","init_base_adapter","init_connections","init_sqlite_query_builder","columns","c","value","sql","values","rows","row","col","i","executor","e","BaseAdapter","change","run","_db","getSqliteClient","name","nativeType","mapSqliteToDataType","universalType","params","tableName","cursor","limit","direction","sort","order","filters","sortColumns","effectiveSortDirection","s","filterWhere","filterValues","buildWhereClause","cursorWhere","cursorValues","cursorData","res","buildCursorWhereClause","combinedWhere","sortClause","buildSortClause","effectiveSortClause","countSql","rawRows","hasMore","createCursor","data","firstRow","lastRow","nextCursor","prevCursor","db","client","pkColumns","a","b","cursorColumns","pk","useRowid","pkTieBreakerCols","tbDir","countRow","total","dataRows","_r","rest","versionRow","tables","counts","t","tableData","fields","foreignKeys","primaryKey","f","columnDefs","field","def","fkDefs","fk","cascade","rowCount","error","newTableName","fks","fkMap","standardizeSqliteDataTypeLabel","columnName","columnType","defaultValue","isNullable","isUnique","q","colInfo","pkCols","hasCompositePk","newColDefs","isTarget","type","nullable","defVal","isPk","fksByGroup","arr","group","from","toColumns","to","table","on_update","on_delete","colNames","tempName","existingIndexes","existingTriggers","newColumnName","placeholders","result","keyColumns","groups","tx","keyValues","rowUpdates","setClauses","u","whereClauses","column","primaryKeys","pkColumn","pkValues","rootPredicate","fksByParent","deletes","plan","predicate","path","parentCols","childPredicate","sum","r","records","record","query","cleaned","isTransactionControl","hasMultipleStatements","start","duration","byConstraint","byParent","key","filePath","bytes","results","ph","registerAdapters","adapterRegistry","PgAdapter","MySqlAdapter","MsSqlAdapter","MongoAdapter","SqliteAdapter","RedisAdapter","DuckDbAdapter","OracleAdapter","ClickhouseAdapter","init_register","__esmMin","init_sentry_injection_stub","init_adapter_registry","init_clickhouse_adapter","init_duckdb_adapter","init_mongo_adapter","init_mssql_adapter","init_mysql_adapter","init_oracle_adapter","init_pg_adapter","init_redis_adapter","init_sqlite_adapter","HTTPException","DatabaseError","ZodError","handleError","e","c","operation","operationForRequest","errorType","errorTypeName","status","statusForError","writeOperationalLog","captureServerError","databaseTypeForRequest","issue","isConnectionError","init_error_handler","__esmMin","init_sentry_injection_stub","init_observability","mysqlError","generateSystemPrompt","schema","dbTypeLower","dbTypeLabel","DATABASE_ENGINES","formatSchemaForPrompt","output","table","col","pkIndicator","fkIndicator","nullable","rel","init_system_prompt_generator","__esmMin","init_sentry_injection_stub","init_types","convertColumnInfo","col","column","extractRelationships","tables","relationships","table","toTable","toColumn","stringifySampleValue","value","getSampleData","adapter","tableName","db","row","key","error","getTableColumns","getDatabaseSchema","options","dbType","getDbType","includeSampleData","maxTables","getAdapter","tablesList","tablePromises","schemaName","columns","sampleData","getDetailedSchema","init_table_details_schema","__esmMin","init_sentry_injection_stub","init_adapter_registry","init_db_manager","zValidator","Hono","HTTPException","LOOPBACK_HOSTNAMES","resolveProxyUrl","chatRoutes","init_chat_routes","__esmMin","init_sentry_injection_stub","init_constants","init_types","init_system_prompt_generator","init_table_details_schema","url","DEFAULTS","isLoopback","c","proxyUrl","proxyResponse","chatSchema","messages","data","provider","model","db","conversationId","includeSchema","schema","getDetailedSchema","systemPrompt","generateSystemPrompt","payload","errorData","Hono","databasesRoutes","init_databases_routes","__esmMin","init_sentry_injection_stub","init_adapter_registry","init_db_manager","c","dbType","getDbType","databases","getAdapter","current","info","zValidator","Hono","keysRoutes","init_keys_routes","__esmMin","init_sentry_injection_stub","init_types","init_adapter_registry","keyScanQuerySchema","c","query","dbType","adapter","assertKeyValueAdapter","getAdapter","databaseSchema","createKeySchema","db","body","keyParamSchema","keyRawQuerySchema","key","keyDetailsQuerySchema","keyActionSchema","deleteKeyQuerySchema","zValidator","Hono","queryRoutes","init_query_routes","__esmMin","init_sentry_injection_stub","init_types","init_adapter_registry","databaseSchema","executeQuerySchema","c","query","db","dbType","data","getAdapter","zValidator","Hono","recordsRoutes","init_records_routes","__esmMin","init_sentry_injection_stub","init_types","init_adapter_registry","databaseSchema","addRecordSchema","c","db","tableName","data","dbType","dao","getAdapter","insertedCount","updateRecordsSchema","params","updatedCount","deleteRecordSchema","primaryKeys","deletedCount","fkViolation","relatedRecords","bulkInsertRecordsSchema","records","result","utils","write","getExportFile","cols","rows","format","tableName","jsonContent","worksheet","toSheetData","csvContent","workbook","buffer","toCellValue","init_get_export_file","__esmMin","init_sentry_injection_stub","value","row","col","zValidator","Hono","tablesRoutes","init_tables_routes","__esmMin","init_sentry_injection_stub","init_types","init_adapter_registry","init_get_export_file","databaseSchema","c","db","dbType","tablesList","getAdapter","createTableSchema","body","deleteTableQuerySchema","tableNameSchema","cascade","tableName","result","renameTableSchema","deleteColumnQuerySchema","deleteColumnParamSchema","columnName","dao","deletedCount","addColumnSchema","renameColumnSchema","alterColumnSchema","columns","schema","tableDataQuerySchema","cursor","limit","direction","sort","order","filters","tableData","exportTableSchema","format","cols","rows","fileContent","getExportFile","contentType","Hono","z","preferenceSchema","telemetryRoutes","init_telemetry_routes","__esmMin","init_sentry_injection_stub","init_observability","c","setTelemetryEnabled","captureInstallationActive","getTelemetryConfig","parsed","resetTelemetryId","create_server_exports","__export","createServer","existsSync","path","fileURLToPath","serveStatic","zValidator","Hono","cors","HTTPException","logger","prettyJSON","z","API_PREFIX","getWebDistPath","databaseTypeParamSchema","init_create_server","__esmMin","init_sentry_injection_stub","init_constants","init_adapter_registry","init_register","init_error_handler","init_observability","init_chat_routes","init_databases_routes","init_keys_routes","init_query_routes","init_records_routes","init_tables_routes","init_telemetry_routes","DEFAULTS","__dirname","bundledWebDistPath","localWebDistPath","bundledIndexPath","localIndexPath","type","adapterRegistry","registerAdapters","app","origin","o","url","_","next","c","startedAt","operation","operationForRequest","rawType","dbType","candidate","startServerSpan","captureServerEvent","outcomeForStatus","durationBucket","handleError","databasesRoutes","chatRoutes","telemetryRoutes","result","tablesRoutes","recordsRoutes","queryRoutes","keysRoutes","init_sentry_injection_stub","init_sentry_injection_stub","e","n","init_sentry_injection_stub","init_constants","intro","log","outro","spinner","serve","color","init_sentry_injection_stub","program","args","options","hasOpen","hasNoOpen","init_sentry_injection_stub","readFile","resolve","cancel","isCancel","note","select","spinner","text","parseDotenv","color","getDatabaseUrl","env","varName","envVarName","s","choice","customPath","value","customEnvPath","content","parsed","e","error","dbUrl","init_sentry_injection_stub","access","readFile","dirname","resolve","parseDotenv","findEnvPath","startDir","dir","envPath","parent","loadEnv","env","content","err","init_sentry_injection_stub","open","shouldOpenBrowser","override","openBrowser","url","init_sentry_injection_stub","init_types","SCHEMES","DATABASE_ENGINES","protocols","protocol","CONNECTION_URL","AUTH_TOKEN","sanitizeErrorMessage","message","url","init_sentry_injection_stub","init_meta","init_types","intro","outro","color","showHelp","DATABASE_ENGINES","label","META","init_sentry_injection_stub","init_constants","init_types","intro","note","outro","color","init_parse_database_url","showStatus","env","databaseUrl","varName","intro","color","envVarName","DEFAULTS","foundUrl","ENV","loadEnv","outro","note","DATABASE_ENGINES","label","DRIVER_ALIASES","scheme","init_sentry_injection_stub","init_package","intro","outro","color","showVersion","package_default","main","env","port","databaseUrl","varName","open","status","help","version","args","showHelp","showVersion","showStatus","intro","color","ENV","loadEnv","key","value","PORT","DEFAULTS","HOST","VAR_NAME","hasEnvFileValue","hasProcessValue","DATABASE_URL","getDatabaseUrl","configSource","log","initServerObservability","checkDatabaseConnection","getDatabaseConnectionDetails","type","name","destination","connectionSpinner","spinner","error","createServer","app","serve","serverUrl","shouldOpenBrowser","openBrowser","outro","message","sanitizeErrorMessage","index_default"]}
|