db-studio 1.9.4 → 1.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/index.js +20 -20
- package/dist/index.js.map +1 -1
- package/dist/web-dist/assets/_pathlessLayout-BByrt-IV.js +2 -0
- package/dist/web-dist/assets/{_pathlessLayout-DhK1pVQZ.js.map → _pathlessLayout-BByrt-IV.js.map} +1 -1
- package/dist/web-dist/assets/{_queryId-PHL0xcKj.js → _queryId-cyxa5wMS.js} +1 -1
- package/dist/web-dist/assets/{_queryId-PHL0xcKj.js.map → _queryId-cyxa5wMS.js.map} +1 -1
- package/dist/web-dist/assets/{_table-Ud147_vw.js → _table-B0yPxctF.js} +1 -1
- package/dist/web-dist/assets/{_table-Ud147_vw.js.map → _table-B0yPxctF.js.map} +1 -1
- package/dist/web-dist/assets/{_table-CThT7wMT.js → _table-DwIZYs3U.js} +1 -1
- package/dist/web-dist/assets/{_table-CThT7wMT.js.map → _table-DwIZYs3U.js.map} +1 -1
- package/dist/web-dist/assets/{format-cell-value-DG6WpZw_.js → format-cell-value-BDLw73u3.js} +6 -6
- package/dist/web-dist/assets/format-cell-value-BDLw73u3.js.map +1 -0
- package/dist/web-dist/assets/index-DRNEODC_.js +86 -0
- package/dist/web-dist/assets/index-DRNEODC_.js.map +1 -0
- package/dist/web-dist/assets/{queries.store-DruKauzK.js → queries.store-DvaENLe7.js} +1 -1
- package/dist/web-dist/assets/{queries.store-DruKauzK.js.map → queries.store-DvaENLe7.js.map} +1 -1
- package/dist/web-dist/assets/{query-runner-Db56mYGQ.js → query-runner-D4jp77L6.js} +2 -2
- package/dist/web-dist/assets/{query-runner-Db56mYGQ.js.map → query-runner-D4jp77L6.js.map} +1 -1
- package/dist/web-dist/assets/{runner-DAA3MnAn.js → runner-EqOuNKQH.js} +1 -1
- package/dist/web-dist/assets/{runner-DAA3MnAn.js.map → runner-EqOuNKQH.js.map} +1 -1
- package/dist/web-dist/assets/{tanstack-C38qytx8.js → tanstack-BfO3BbGk.js} +5 -5
- package/dist/web-dist/assets/tanstack-BfO3BbGk.js.map +1 -0
- package/dist/web-dist/index.html +3 -3
- package/package.json +1 -1
- package/dist/web-dist/assets/_pathlessLayout-DhK1pVQZ.js +0 -2
- package/dist/web-dist/assets/format-cell-value-DG6WpZw_.js.map +0 -1
- package/dist/web-dist/assets/index-GnOMl7Md.js +0 -86
- package/dist/web-dist/assets/index-GnOMl7Md.js.map +0 -1
- package/dist/web-dist/assets/tanstack-C38qytx8.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../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","../src/adapters/adapter.registry.ts","../src/adapters/base.adapter.ts","../src/db-manager.ts","../src/adapters/connections.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/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-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/rate-limit-response.type.ts","../../shared/src/types/rename-column.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/query.routes.ts","../src/routes/records.routes.ts","../src/utils/get-export-file.ts","../src/routes/tables.routes.ts","../src/utils/create-server.ts","../src/index.ts","../src/cmd/args.ts","../src/cmd/get-db-url.ts","../src/cmd/load-env.ts","../src/cmd/show-help.ts","../src/cmd/show-status.ts","../src/cmd/show-version.ts","../package.json"],"sourcesContent":["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.dbstudio.localhost\",\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.dbstudio.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: \"dbstudio\",\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","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 type { DatabaseTypeSchema } from \"@db-studio/shared/types/database.types.js\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { IDbAdapter } from \"./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","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\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/** 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 });\n\t\t\t}\n\n\t\t\treturn new HTTPException(500, { message: e.message });\n\t\t}\n\n\t\treturn new HTTPException(500, { message: \"Internal server error\" });\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, CellValue>[] }> {\n\t\ttry {\n\t\t\tconst sql = `SELECT * FROM ${this.quoteIdentifier(tableName)}`;\n\t\t\tconst rows = await this.runQuery<Record<string, CellValue>[]>(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\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 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\t// case \"redis\":\n\t\t\t// case \"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://).`,\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\tconsole.log(`Opened SQLite database: ${filePath}`);\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\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\tconsole.log(`Created PostgreSQL connection pool for: ${connectionString}`);\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\tconsole.log(`Created MySQL connection pool for: ${connectionString}`);\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\tconsole.log(`Created SQL Server connection pool for: ${connectionString}`);\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 path = new URL(this.baseConfig.url).pathname?.replace(/^\\//, \"\");\n\t\treturn path || \"admin\";\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\\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 mode is not supported. Use a single-node redis:// connection.\",\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\tconsole.log(`Created Redis client for db=${index}`);\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\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 * 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 getRedisDefaultDb: typeof dbManager.getRedisDefaultDb = () =>\n\tdbManager.getRedisDefaultDb();\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\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 { 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 { 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 });\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\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 databases.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 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, updates, primaryKey } = 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 pkField = primaryKey || \"_id\";\n\t\t\tconst updatesByRow = new Map<unknown, Record<string, unknown>>();\n\n\t\t\tfor (const update of updates) {\n\t\t\t\tconst pkValue = update.rowData[pkField];\n\t\t\t\tif (pkValue === undefined || pkValue === 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\tif (!updatesByRow.has(pkValue)) updatesByRow.set(pkValue, {});\n\t\t\t\tupdatesByRow.get(pkValue)![update.columnName] = update.value;\n\t\t\t}\n\n\t\t\tfor (const [pkValue, updateSet] of updatesByRow.entries()) {\n\t\t\t\tconst queryValue =\n\t\t\t\t\tpkField === \"_id\" && canCoerce(pkValue) ? toMongoId(pkValue) : pkValue;\n\t\t\t\tconst result = await collection.updateOne(\n\t\t\t\t\t{ [pkField]: queryValue },\n\t\t\t\t\t{ $set: updateSet },\n\t\t\t\t);\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 ${pkField} = ${String(pkValue)} 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 { deletedCount: result.deletedCount ?? 0 };\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 = [\n\t\"pg\",\n\t\"mysql\",\n\t\"mssql\",\n\t\"mongodb\",\n\t\"sqlite\",\n\t// \"redis\"\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\";\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 { databaseSchema } from \"./database.types.js\";\n\n// UI message part schema (from @tanstack/ai-react)\nconst messagePart = z\n\t.object({\n\t\ttype: z.string(),\n\t\tcontent: z.string().optional(),\n\t})\n\t.passthrough();\n\n// `@tanstack/ai-react`'s `fetchServerSentEvents` adapter sends UI messages\n// with `parts` (not `content`) and wraps extra body under `data`.\nexport const chatSchema = z.object({\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\"]),\n\t\t\t\tparts: z.array(messagePart),\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}),\n});\n","export type Args = {\n\tenv?: string;\n\tport?: string;\n\tdatabaseUrl?: string;\n\tvarName?: string;\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 { 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","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 } 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\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 \"./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-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 \"./rate-limit-response.type.js\";\nexport * from \"./rename-column.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\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\tconst pool = await getMssqlPool();\n\t\tconst result = await pool.request().query(`\n\t\t\tSELECT\n\t\t\t d.name AS name,\n\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 SUSER_SNAME(d.owner_sid) AS owner,\n\t\t\t d.collation_name AS encoding\n\t\t\tFROM sys.databases d\n\t\t\tJOIN sys.master_files mf ON d.database_id = mf.database_id\n\t\t\tWHERE d.database_id > 4\n\t\t\tGROUP BY d.name, d.owner_sid, d.collation_name\n\t\t\tORDER BY d.name\n\t\t`);\n\t\tif (!result.recordset[0]) {\n\t\t\tthrow new HTTPException(500, { message: \"No databases returned from server\" });\n\t\t}\n\t\treturn result.recordset as DatabaseInfoSchemaType[];\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 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, updates, primaryKey } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\tconst updatesByRow = new Map<unknown, Array<{ columnName: string; value: unknown }>>();\n\t\tfor (const update of updates) {\n\t\t\tconst pkValue = update.rowData[primaryKey];\n\t\t\tif (pkValue === undefined || pkValue === null) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Primary key \"${primaryKey}\" not found in row data.`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!updatesByRow.has(pkValue)) updatesByRow.set(pkValue, []);\n\t\t\tupdatesByRow.get(pkValue)?.push({ columnName: update.columnName, value: update.value });\n\t\t}\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 [pkValue, rowUpdates] of updatesByRow.entries()) {\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\trequest.input(\"pkValue\", pkValue);\n\n\t\t\t\tconst result = await request.query(\n\t\t\t\t\t`UPDATE [${tableName}] SET ${setClauses.join(\", \")} WHERE [${primaryKey}] = @pkValue`,\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 ${primaryKey} = ${pkValue} 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\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\tconst pool = getMysqlPool();\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(`\n\t\t\tSELECT\n\t\t\t s.SCHEMA_NAME AS name,\n\t\t\t CONCAT(ROUND(COALESCE(SUM(t.data_length + t.index_length), 0) / 1024 / 1024, 2), ' MB') AS size,\n\t\t\t CURRENT_USER() AS owner,\n\t\t\t s.DEFAULT_CHARACTER_SET_NAME AS encoding\n\t\t\tFROM information_schema.SCHEMATA s\n\t\t\tLEFT JOIN information_schema.TABLES t ON t.TABLE_SCHEMA = s.SCHEMA_NAME\n\t\t\tGROUP BY s.SCHEMA_NAME, s.DEFAULT_CHARACTER_SET_NAME\n\t\t\tORDER BY s.SCHEMA_NAME\n\t\t`);\n\t\tif (!rows[0])\n\t\t\tthrow new HTTPException(500, { message: \"No databases returned from server\" });\n\t\treturn rows as DatabaseInfoSchemaType[];\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 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, updates, primaryKey } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\tconst updatesByRow = new Map<unknown, Array<{ columnName: string; value: unknown }>>();\n\t\tfor (const update of updates) {\n\t\t\tconst pkValue = update.rowData[primaryKey];\n\t\t\tif (pkValue === undefined || pkValue === null) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Primary key \"${primaryKey}\" not found in row data.`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!updatesByRow.has(pkValue)) updatesByRow.set(pkValue, []);\n\t\t\tupdatesByRow.get(pkValue)?.push({ columnName: update.columnName, value: update.value });\n\t\t}\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 [pkValue, rowUpdates] of updatesByRow.entries()) {\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(pkValue);\n\n\t\t\t\tconst [result] = await connection.execute<ResultSetHeader>(\n\t\t\t\t\t`UPDATE \\`${tableName}\\` SET ${setClauses.join(\", \")} WHERE \\`${primaryKey}\\` = ?`,\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 ${primaryKey} = ${pkValue} 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","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\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} 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\tconst pool = getDbPool();\n\t\tconst { rows } = await pool.query(`\n\t\t\tSELECT\n\t\t\t\td.datname as name,\n\t\t\t\tpg_size_pretty(pg_database_size(d.datname)) as size,\n\t\t\t\tpg_catalog.pg_get_userbyid(d.datdba) as owner,\n\t\t\t\tpg_encoding_to_char(d.encoding) as encoding\n\t\t\tFROM pg_catalog.pg_database d\n\t\t\tWHERE d.datistemplate = false\n\t\t\tORDER BY d.datname;\n\t\t`);\n\t\tif (!rows[0])\n\t\t\tthrow new HTTPException(500, { message: \"No databases returned from database\" });\n\t\treturn rows;\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 = 'public') 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 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 = 'public' 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 = 'public' 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 = 'public' 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 = 'public' AND tablename = $1\n\t\t\t AND indexname NOT IN (SELECT constraint_name FROM information_schema.table_constraints WHERE table_schema = 'public' 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 = 'public' 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 = 'public' AND tc.table_name = $1\n\t\t\t) fk ON c.column_name = fk.column_name\n\t\t\tWHERE c.table_schema = 'public' 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 = 'public') 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 = 'public') 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 = 'public') 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 = 'public') 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 = 'public') 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 = 'public') 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 = 'public') 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 = 'public') 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, updates, primaryKey } = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst updatesByRow = new Map<unknown, Array<{ columnName: string; value: unknown }>>();\n\t\tfor (const u of updates) {\n\t\t\tconst pkValue = u.rowData[primaryKey];\n\t\t\tif (pkValue === undefined || pkValue === null)\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Primary key \"${primaryKey}\" not found in row data.`,\n\t\t\t\t});\n\t\t\tif (!updatesByRow.has(pkValue)) updatesByRow.set(pkValue, []);\n\t\t\tupdatesByRow.get(pkValue)?.push({ columnName: u.columnName, value: u.value });\n\t\t}\n\n\t\tawait pool.query(\"BEGIN\");\n\t\ttry {\n\t\t\tlet total = 0;\n\t\t\tfor (const [pkValue, rowUpdates] of updatesByRow.entries()) {\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\tvalues.push(pkValue);\n\t\t\t\tconst result = await pool.query(\n\t\t\t\t\t`UPDATE \"${tableName}\" SET ${setClauses.join(\", \")} WHERE \"${primaryKey}\" = $${values.length} 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 ${primaryKey} = ${pkValue} 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 type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tCellValue,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tRenameColumnParamsSchemaType,\n\tTableDataResultSchemaType,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { Redis } from \"ioredis\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getRedisClient, getRedisDefaultDb } from \"@/adapters/connections.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;\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\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 {\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\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\tconst configReply = (await client.call(\"CONFIG\", \"GET\", \"databases\")) as unknown;\n\t\t\tlet total = 16;\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) total = parsed;\n\t\t\t}\n\n\t\t\tconst keyspaceInfo = await client.info(\"keyspace\");\n\t\t\tconst keysPerDb = parseKeyspaceInfo(keyspaceInfo);\n\n\t\t\treturn Array.from({ length: total }, (_, i) => ({\n\t\t\t\tname: String(i),\n\t\t\t\tsize: `${keysPerDb.get(i) ?? 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\")) as unknown;\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 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 } = params;\n\t\t\tconst table = assertRedisTable(tableName);\n\t\t\tconst pkField = 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\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, CellValue>[] }> {\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\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\treturn rows.map((row) => ({\n\t\t\t\tname: row.name,\n\t\t\t\tsize: this.getFileSize(row.file),\n\t\t\t\towner: \"\",\n\t\t\t\tencoding: \"UTF-8\",\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 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 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, updates, primaryKey } = params;\n\t\tconst sqliteDb = getSqliteDb();\n\n\t\tconst updatesByRow = new Map<unknown, Array<{ columnName: string; value: unknown }>>();\n\t\tfor (const u of updates) {\n\t\t\tconst pkValue = u.rowData[primaryKey];\n\t\t\tif (pkValue === undefined || pkValue === null) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Primary key \"${primaryKey}\" not found in row data.`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!updatesByRow.has(pkValue)) updatesByRow.set(pkValue, []);\n\t\t\tupdatesByRow.get(pkValue)?.push({ columnName: u.columnName, value: u.value });\n\t\t}\n\n\t\tconst doUpdate = sqliteDb.transaction(() => {\n\t\t\tlet total = 0;\n\t\t\tfor (const [pkValue, rowUpdates] of updatesByRow.entries()) {\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\tpkValue,\n\t\t\t\t];\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 \"${primaryKey}\" = ?`)\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 ${primaryKey} = ${pkValue} 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\";\n\n/**\n * Centralized error handler for the application\n */\nexport function handleError(e: Error | unknown, c: Context) {\n\tconsole.error(\"handleError:\", e);\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\t// MySQL-specific error codes\n\t\tconst mysqlError = e as { code?: string; errno?: number };\n\t\tconst isMysqlConnectionError =\n\t\t\tmysqlError.code === \"ECONNREFUSED\" ||\n\t\t\tmysqlError.code === \"ENOTFOUND\" ||\n\t\t\tmysqlError.code === \"ETIMEDOUT\" ||\n\t\t\tmysqlError.code === \"ER_ACCESS_DENIED_ERROR\" ||\n\t\t\tmysqlError.code === \"ER_BAD_HOST_ERROR\" ||\n\t\t\tmysqlError.code === \"ECONNRESET\" ||\n\t\t\tmysqlError.errno === 1045 || // ER_ACCESS_DENIED_ERROR\n\t\t\tmysqlError.errno === 2003 || // Can't connect to MySQL server\n\t\t\tmysqlError.errno === 2002; // Can't connect to local MySQL server\n\n\t\tconst isConnectionError =\n\t\t\tisMysqlConnectionError ||\n\t\t\te.message.includes(\"ECONNREFUSED\") ||\n\t\t\te.message.includes(\"connection refused\") ||\n\t\t\te.message.includes(\"timeout expired\") ||\n\t\t\te.message.includes(\"Connection terminated\") ||\n\t\t\te.message.includes(\"MongoNetworkError\") ||\n\t\t\te.message.includes(\"MongoServerSelectionError\") ||\n\t\t\t(e instanceof DatabaseError && e.code?.startsWith(\"08\")); // PostgreSQL connection exception class\n\n\t\tif (isConnectionError) {\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): string {\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 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 tableNames = tablesList\n\t\t\t.slice(0, maxTables ?? tablesList.length)\n\t\t\t.map((t) => t.tableName);\n\n\t\tconst tablePromises = tableNames.map(async (tableName) => {\n\t\t\tconst [columns, sampleData] = await Promise.all([\n\t\t\t\tadapter.getTableColumns({ 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: 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 } from \"@db-studio/shared/constants\";\nimport { chatSchema } from \"@db-studio/shared/types\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { generateSystemPrompt } from \"@/utils/system-prompt-generator.js\";\nimport { getDetailedSchema } from \"@/utils/table-details-schema.js\";\n\nexport const chatRoutes = new Hono()\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\tconst proxyResponse = await fetch(`${DEFAULTS.PROXY_URL}/chat/limit`, {\n\t\t\theaders: {\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},\n\t\t});\n\t\tconst data = await proxyResponse.json();\n\t\treturn c.json(data, proxyResponse.status as 200 | 500);\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 } = c.req.valid(\"json\");\n\t\tconst { db, conversationId } = data;\n\t\tconsole.log(\"POST /chat messages\", messages);\n\n\t\t// Get the database schema and generate system prompt\n\t\tconst schema = await getDetailedSchema(db);\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};\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(`${DEFAULTS.PROXY_URL}/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},\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 | 500,\n\t\t\t);\n\t\t}\n\n\t\t// Stream the SSE response back to the client\n\t\tconst { readable, writable } = new TransformStream();\n\t\tproxyResponse.body?.pipeTo(writable);\n\n\t\treturn new Response(readable, {\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/event-stream\",\n\t\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t\t\tConnection: \"keep-alive\",\n\t\t\t},\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 all databases on the server (name, size, owner, encoding)\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 all 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\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, CellValue>[];\n\tformat: FormatType;\n\ttableName: string;\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 data: CellValue[][] = [\n\t\t\t\tcols,\n\t\t\t\t...(rows?.map((row) => cols?.map((col) => row[col])) ?? []),\n\t\t\t];\n\t\t\tconst worksheet = utils.aoa_to_sheet(data);\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 data: CellValue[][] = [\n\t\t\t\tcols,\n\t\t\t\t...(rows?.map((row) => cols?.map((col) => row[col])) ?? []),\n\t\t\t];\n\t\t\tconst worksheet = utils.aoa_to_sheet(data);\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\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 * 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 { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\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 { chatRoutes } from \"@/routes/chat.routes.js\";\nimport { databasesRoutes } from \"@/routes/databases.routes.js\";\nimport { queryRoutes } from \"@/routes/query.routes.js\";\nimport { recordsRoutes } from \"@/routes/records.routes.js\";\nimport { tablesRoutes } from \"@/routes/tables.routes.js\";\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.use(\"/*\", cors())\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/**\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 CORS requests\n\t\t */\n\t\t.use(\"*\", async (c, next) => {\n\t\t\tc.header(\"Access-Control-Allow-Origin\", \"*\");\n\t\t\tc.header(\"Access-Control-Allow-Methods\", \"GET, POST, PUT, DELETE, OPTIONS\");\n\t\t\tc.header(\"Access-Control-Allow-Headers\", \"Content-Type\");\n\t\t\tawait next();\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 * Database routes - available at root level (no dbType required)\n\t\t */\n\t\t.route(\"/\", databasesRoutes)\n\t\t.route(\"/\", chatRoutes)\n\n\t\t/**\n\t\t * Serve static assets (before dbType validation to avoid conflicts)\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 /:dbType/...\n\t\t */\n\t\t.use(\n\t\t\t\"/: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 } = c.req.valid(\"param\");\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(\"/:dbType\", tablesRoutes)\n\t\t.route(\"/:dbType\", recordsRoutes)\n\t\t.route(\"/:dbType\", queryRoutes);\n\n\tif (process.env.NODE_ENV !== \"test\") {\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","import { intro, outro } 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 { 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, 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 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 ENV = env ? await loadEnv(env) : await loadEnv();\n\tconst DATABASE_URL = databaseUrl ? databaseUrl : await getDatabaseUrl(ENV, VAR_NAME);\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\t// Import createServer dynamically after setting DATABASE_URL\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\toutro(color.green(`Server running at ${color.cyan(serverUrl)}`));\n};\n\nmain().catch((err) => {\n\tconsole.error(color.red(`❌ Unexpected error: ${err.message}`));\n\tprocess.exit(1);\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(\"-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\treturn program.opts<Args>();\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 { 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(\" MySQL, PostgreSQL\\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\" -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(color.dim(\" • Supported databases: MySQL, PostgreSQL\"));\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","{\n \"name\": \"db-studio\",\n \"type\": \"module\",\n \"version\": \"1.9.4\",\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\\u00fcsam \\ud83e\\udd51 <devhsmq@gmail.com>\",\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\": \"BSL-1.1\",\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 --sourcemap\",\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.dbstudio\",\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.8.0\",\n \"better-sqlite3\": \"^12.9.0\",\n \"commander\": \"^15.0.0\",\n \"dotenv\": \"^17.3.1\",\n \"hono\": \"^4.10.4\",\n \"ioredis\": \"^5.4.1\",\n \"mongodb\": \"^7.1.1\",\n \"mssql\": \"^12.2.0\",\n \"mysql2\": \"^3.18.2\",\n \"pg\": \"^8.13.1\",\n \"picocolors\": \"^1.1.1\",\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 \"@types/better-sqlite3\": \"^7.6.13\",\n \"@types/mssql\": \"^12.3.0\",\n \"@types/node\": \"^26.0.0\",\n \"@types/pg\": \"^8.16.0\",\n \"@vitest/coverage-v8\": \"^4.0.17\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.7.1\",\n \"typescript\": \"^6.0.3\",\n \"vitest\": \"^4.0.17\"\n }\n}\n"],"mappings":"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","names":["init_chat","__esmMin","init_column_types_mysql","__esmMin","init_column_types_pgsql","__esmMin","env","nodeEnv","DEFAULTS","init_defaults","__esmMin","init_links","__esmMin","META","init_meta","__esmMin","init_proxy_limits","__esmMin","init_constants","__esmMin","init_chat","init_column_types_mysql","init_column_types_pgsql","init_defaults","init_links","init_meta","init_proxy_limits","HTTPException","getAdapter","dbType","adapterRegistry","AdapterRegistry","init_adapter_registry","__esmMin","type","adapter","HTTPException","DatabaseError","notImplemented","method","BaseAdapter","init_base_adapter","__esmMin","err","data","cursor","row","out","k","v","params","db","limit","direction","bundle","countRes","total","rawRows","hasMore","rows","nextCursor","prevCursor","e","tableName","sql","_db","_params","Database","Redis","MongoClient","ObjectId","mssql","createMysqlPool","Pool","DatabaseManager","databaseManager","getDbPool","getMysqlPool","getMssqlPool","getDbType","getSqliteDb","getMongoClient","getMongoDbName","getMongoDb","getRedisClient","getRedisDefaultDb","isValidObjectId","coerceObjectId","init_db_manager","__esmMin","url","protocol","databaseUrl","detectedType","defaultPort","error","database","filePath","db","connectionString","poolConfig","pool","err","dbName","config","nextClient","dbIndex","index","existing","options","client","info","path","parsed","pgClosePromises","mysqlClosePromises","mssqlClosePromises","redisClosePromises","value","getDbPool","getMysqlPool","getMssqlPool","getSqliteDb","getMongoClient","getMongoDbName","getMongoDb","getRedisClient","getRedisDefaultDb","init_connections","__esmMin","init_db_manager","database","dbName","dbIndex","parseDatabaseUrl","databaseUrl","url","protocol","defaultPort","init_parse_database_url","__esmMin","buildMatchStage","filters","andConditions","filter","field","value","parseFilterValue","op","escapeRegex","buildSortStage","sort","order","s","encodeMongoCursor","offset","decodeMongoCursor","cursor","parsed","init_mongo_pipeline_builder","__esmMin","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_base_adapter","init_connections","init_db_manager","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","getMongoDbName","admin","urlDefaults","parseDatabaseUrl","serverStatus","mongoDb","collections","results","col","rowCount","tableData","fields","properties","required","field","bsonType","docs","totalDocs","fieldTypes","fieldPresence","key","types","presence","typeList","t","isNullable","schema","documents","columnMap","ensureColumn","columnName","entry","meta","resolvedDefault","existingSchema","reqIndex","newColumnName","data","payload","updates","primaryKey","totalUpdated","pkField","updatesByRow","update","pkValue","updateSet","queryValue","result","primaryKeys","pkColumn","pkValues","pk","records","record","query","startTime","message","duration","z","databaseSchema","DATABASE_TYPES","databaseTypeSchema","currentDatabaseSchema","databaseTypeParamSchema","tableNameSchema","init_database_types","__esmMin","z","addColumnSchema","addColumnParamSchema","addColumnParamsSchema","init_add_column_types","__esmMin","init_database_types","tableNameSchema","databaseSchema","z","addRecordSchema","init_add_record_types","__esmMin","z","deleteColumnQuerySchema","deleteColumnParamSchema","deleteColumnParamsSchema","deleteColumnSuccessResponseSchema","init_delete_column_types","__esmMin","init_database_types","databaseSchema","val","z","alterColumnSchema","alterColumnParamSchema","alterColumnParamsSchema","init_alter_column_types","__esmMin","init_database_types","init_delete_column_types","deleteColumnParamSchema","databaseSchema","init_api_response_types","__esmMin","z","bulkInsertRecordsSchema","init_bulk_insert_records_type","__esmMin","z","messagePart","chatSchema","init_chat_types","__esmMin","init_database_types","databaseSchema","init_cmd_args_types","__esmMin","z","dataTypes","dataTypesSchema","DataTypes","standardizedDataTypes","standardizedDataTypeSchema","columnInfoSchema","init_column_info_types","__esmMin","mapPostgresToDataType","pgType","normalized","DataTypes","standardizeDataTypeLabel","StandardizedDataType","mapMysqlToDataType","mysqlDataType","columnType","fullType","standardizeMysqlDataTypeLabel","mapMssqlToDataType","mssqlDataType","standardizeMssqlDataTypeLabel","mapSqliteToDataType","sqliteType","standardizeSqliteDataTypeLabel","init_column_type","__esmMin","init_column_info_types","z","FOREIGN_KEY_ACTIONS","foreignKeyActionSchema","fieldDataSchema","foreignKeyDataSchema","createTableSchema","init_create_table_types","__esmMin","z","databaseInfoSchema","databaseListSchema","connectionInfoSchema","init_database_list_types","__esmMin","init_database_types","databaseTypeSchema","init_database_schema_type","__esmMin","z","deleteRecordSchema","init_delete_record_types","__esmMin","z","deleteTableQuerySchema","init_delete_table_types","__esmMin","init_database_types","databaseSchema","val","z","executeQuerySchema","init_execute_query_types","__esmMin","z","FORMAT_TYPES","exportTableSchema","init_export_table_types","__esmMin","init_database_types","databaseSchema","init_rate_limit_response_type","__esmMin","z","renameColumnSchema","renameColumnParamSchema","renameColumnParamsSchema","init_rename_column_types","__esmMin","init_database_types","init_delete_column_types","deleteColumnParamSchema","databaseSchema","z","filterSchema","sortDirections","sortSchema","tableDataMetaSchema","tableDataResultSchema","tableDataQuerySchema","init_table_data_types","__esmMin","init_database_types","databaseSchema","val","parsed","z","tableInfoSchema","init_table_info_type","__esmMin","z","tableSchemaResultSchema","init_table_schema_types","__esmMin","z","updateRecordsSchema","init_update_recors_types","__esmMin","types_exports","__export","DATABASE_TYPES","DataTypes","FOREIGN_KEY_ACTIONS","FORMAT_TYPES","StandardizedDataType","addColumnParamSchema","addColumnParamsSchema","addColumnSchema","addRecordSchema","alterColumnParamSchema","alterColumnParamsSchema","alterColumnSchema","bulkInsertRecordsSchema","chatSchema","columnInfoSchema","connectionInfoSchema","createTableSchema","currentDatabaseSchema","dataTypesSchema","databaseInfoSchema","databaseListSchema","databaseSchema","databaseTypeParamSchema","databaseTypeSchema","deleteColumnParamSchema","deleteColumnParamsSchema","deleteColumnQuerySchema","deleteColumnSuccessResponseSchema","deleteRecordSchema","deleteTableQuerySchema","executeQuerySchema","exportTableSchema","fieldDataSchema","filterSchema","foreignKeyActionSchema","foreignKeyDataSchema","mapMssqlToDataType","mapMysqlToDataType","mapPostgresToDataType","mapSqliteToDataType","renameColumnParamSchema","renameColumnParamsSchema","renameColumnSchema","sortDirections","sortSchema","standardizeDataTypeLabel","standardizeMssqlDataTypeLabel","standardizeMysqlDataTypeLabel","standardizeSqliteDataTypeLabel","standardizedDataTypeSchema","tableDataMetaSchema","tableDataQuerySchema","tableDataResultSchema","tableInfoSchema","tableNameSchema","tableSchemaResultSchema","updateRecordsSchema","init_types","__esmMin","init_add_column_types","init_add_record_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_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_rate_limit_response_type","init_rename_column_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","HTTPException","MSSQL_FK_VIOLATION","MSSQL_FK_DEPENDENCY","MsSqlAdapter","init_mssql_adapter","__esmMin","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","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","updates","primaryKey","updatesByRow","update","pkValue","transaction","rowUpdates","setClauses","u","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","HTTPException","MYSQL_FK_VIOLATION","MYSQL_FK_DEPENDENCY","MySqlAdapter","init_mysql_adapter","__esmMin","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","createTableSql","r","isEnum","standardizeMysqlDataTypeLabel","columnName","columnType","defaultValue","isPrimaryKey","isNullable","isUnique","isIdentity","isArray","colRows","colDef","result","colRow","newColumnName","newColRows","data","booleanColumns","columns","value","i","c","updates","primaryKey","updatesByRow","update","pkValue","rowUpdates","setClauses","u","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","init_pg_query_builder","__esmMin","HTTPException","PgAdapter","init_pg_adapter","__esmMin","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","existsRows","columns","constraints","indexes","formatType","data_type","udt_name","character_maximum_length","numeric_precision","numeric_scale","lines","colDefs","constraintMap","c","arr","constraintDefs","cols","first","colNames","idx","r","parsedEnumValues","standardizeDataTypeLabel","columnName","columnType","defaultValue","isPrimaryKey","isNullable","isUnique","isIdentity","isArray","colRows","client","newColumnName","colExistsQuery","curRows","nextRows","placeholders","_","i","updates","primaryKey","updatesByRow","u","pkValue","rowUpdates","setClauses","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","v","x","idx","rows","section","line","entry","id","fields","fieldsObj","HTTPException","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","isRedisTable","assertRedisTable","parseDbIndex","encodeScanCursor","decodeScanCursor","columnInfo","KEY_COL","TTL_COL","TABLE_COLUMNS","SCHEMA_DESCRIPTIONS","RedisAdapter","init_redis_adapter","__esmMin","init_base_adapter","init_connections","init_redis_command_shaper","name","tableName","db","getRedisDefaultDb","env","cursor","overrides","BaseAdapter","_params","rawRows","row","nativeType","_universalType","client","getRedisClient","configReply","total","keyspaceInfo","keysPerDb","_","serverInfo","clientsInfo","server","clients","maxclients","opts","dbIndex","counts","e","table","params","limit","direction","sort","filters","redisType","scanCursor","decoded","collectedKeys","rounds","scanComplete","next","batch","pageKeys","overflow","rows","hasNextPage","nextCursor","keys","ttlPipeline","key","ttlResults","valuePipeline","valueResults","ttl","raw","cached","pipeline","results","updates","primaryKey","pkField","updatesByKey","u","keyStr","existing","updatedCount","primaryKeys","pk","deletedCount","records","errors","successCount","record","allKeys","c","flat","field","val","entries","args","query","startTime","argv","tokenizeCommand","cmd","rest","message","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","statSync","HTTPException","SqliteAdapter","init_sqlite_adapter","__esmMin","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","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","updates","primaryKey","updatesByRow","u","pkValue","doUpdate","rowUpdates","setClauses","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_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","issue","mysqlError","init_error_handler","__esmMin","generateSystemPrompt","schema","dbTypeLower","dbTypeLabel","formatSchemaForPrompt","output","table","col","pkIndicator","fkIndicator","nullable","rel","init_system_prompt_generator","__esmMin","convertColumnInfo","col","column","extractRelationships","tables","relationships","table","toTable","toColumn","stringifySampleValue","value","getSampleData","adapter","tableName","db","row","key","getDatabaseSchema","options","dbType","getDbType","includeSampleData","maxTables","getAdapter","tablesList","tablePromises","t","columns","sampleData","error","getDetailedSchema","init_table_details_schema","__esmMin","init_adapter_registry","init_db_manager","zValidator","Hono","chatRoutes","init_chat_routes","__esmMin","init_constants","init_types","init_system_prompt_generator","init_table_details_schema","c","proxyResponse","DEFAULTS","data","chatSchema","messages","db","conversationId","schema","getDetailedSchema","systemPrompt","generateSystemPrompt","payload","errorData","readable","writable","Hono","databasesRoutes","init_databases_routes","__esmMin","init_adapter_registry","init_db_manager","c","dbType","getDbType","databases","getAdapter","current","info","zValidator","Hono","queryRoutes","init_query_routes","__esmMin","init_types","init_adapter_registry","databaseSchema","executeQuerySchema","c","query","db","dbType","data","getAdapter","zValidator","Hono","recordsRoutes","init_records_routes","__esmMin","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","data","row","col","worksheet","csvContent","workbook","buffer","init_get_export_file","__esmMin","zValidator","Hono","tablesRoutes","init_tables_routes","__esmMin","init_types","init_adapter_registry","init_get_export_file","databaseSchema","c","db","dbType","tablesList","getAdapter","createTableSchema","body","deleteTableQuerySchema","tableNameSchema","cascade","tableName","result","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","create_server_exports","__export","createServer","existsSync","path","fileURLToPath","serveStatic","zValidator","Hono","cors","HTTPException","logger","prettyJSON","z","getWebDistPath","databaseTypeParamSchema","init_create_server","__esmMin","init_adapter_registry","init_register","init_error_handler","init_chat_routes","init_databases_routes","init_query_routes","init_records_routes","init_tables_routes","__dirname","bundledWebDistPath","localWebDistPath","bundledIndexPath","localIndexPath","type","adapterRegistry","registerAdapters","app","_","next","c","handleError","databasesRoutes","chatRoutes","result","rawType","dbType","tablesRoutes","recordsRoutes","queryRoutes","init_constants","intro","outro","serve","color","program","args","readFile","resolve","cancel","isCancel","note","select","spinner","text","parseDotenv","color","getDatabaseUrl","env","varName","envVarName","s","choice","customPath","value","customEnvPath","content","parsed","e","error","dbUrl","access","readFile","dirname","resolve","parseDotenv","findEnvPath","startDir","dir","envPath","parent","loadEnv","env","content","err","init_meta","intro","outro","color","showHelp","META","init_constants","intro","note","outro","color","showStatus","env","databaseUrl","varName","intro","color","envVarName","DEFAULTS","foundUrl","ENV","loadEnv","outro","note","intro","outro","color","package_default","showVersion","intro","color","outro","package_default","main","env","port","databaseUrl","varName","status","help","version","args","showHelp","showVersion","showStatus","intro","color","PORT","DEFAULTS","HOST","VAR_NAME","ENV","loadEnv","DATABASE_URL","getDatabaseUrl","createServer","app","serve","serverUrl","outro","err"]}
|
|
1
|
+
{"version":3,"sources":["../../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","../src/adapters/adapter.registry.ts","../src/adapters/base.adapter.ts","../src/db-manager.ts","../src/adapters/connections.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/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-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/rate-limit-response.type.ts","../../shared/src/types/rename-column.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/query.routes.ts","../src/routes/records.routes.ts","../src/utils/get-export-file.ts","../src/routes/tables.routes.ts","../src/utils/create-server.ts","../src/index.ts","../src/cmd/args.ts","../src/cmd/get-db-url.ts","../src/cmd/load-env.ts","../src/cmd/show-help.ts","../src/cmd/show-status.ts","../src/cmd/show-version.ts","../package.json"],"sourcesContent":["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.dbstudio.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.dbstudio.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: \"dbstudio\",\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","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 type { DatabaseTypeSchema } from \"@db-studio/shared/types/database.types.js\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { IDbAdapter } from \"./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","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\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/** 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 });\n\t\t\t}\n\n\t\t\treturn new HTTPException(500, { message: e.message });\n\t\t}\n\n\t\treturn new HTTPException(500, { message: \"Internal server error\" });\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, CellValue>[] }> {\n\t\ttry {\n\t\t\tconst sql = `SELECT * FROM ${this.quoteIdentifier(tableName)}`;\n\t\t\tconst rows = await this.runQuery<Record<string, CellValue>[]>(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\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 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\t// case \"redis\":\n\t\t\t// case \"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://).`,\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\tconsole.log(`Opened SQLite database: ${filePath}`);\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\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\tconsole.log(`Created PostgreSQL connection pool for: ${connectionString}`);\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\tconsole.log(`Created MySQL connection pool for: ${connectionString}`);\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\tconsole.log(`Created SQL Server connection pool for: ${connectionString}`);\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 path = new URL(this.baseConfig.url).pathname?.replace(/^\\//, \"\");\n\t\treturn path || \"admin\";\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\\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 mode is not supported. Use a single-node redis:// connection.\",\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\tconsole.log(`Created Redis client for db=${index}`);\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\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 * 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 getRedisDefaultDb: typeof dbManager.getRedisDefaultDb = () =>\n\tdbManager.getRedisDefaultDb();\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\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 { 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 { 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 });\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\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 databases.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 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, updates, primaryKey } = 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 pkField = primaryKey || \"_id\";\n\t\t\tconst updatesByRow = new Map<unknown, Record<string, unknown>>();\n\n\t\t\tfor (const update of updates) {\n\t\t\t\tconst pkValue = update.rowData[pkField];\n\t\t\t\tif (pkValue === undefined || pkValue === 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\tif (!updatesByRow.has(pkValue)) updatesByRow.set(pkValue, {});\n\t\t\t\tupdatesByRow.get(pkValue)![update.columnName] = update.value;\n\t\t\t}\n\n\t\t\tfor (const [pkValue, updateSet] of updatesByRow.entries()) {\n\t\t\t\tconst queryValue =\n\t\t\t\t\tpkField === \"_id\" && canCoerce(pkValue) ? toMongoId(pkValue) : pkValue;\n\t\t\t\tconst result = await collection.updateOne(\n\t\t\t\t\t{ [pkField]: queryValue },\n\t\t\t\t\t{ $set: updateSet },\n\t\t\t\t);\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 ${pkField} = ${String(pkValue)} 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 { deletedCount: result.deletedCount ?? 0 };\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 = [\n\t\"pg\",\n\t\"mysql\",\n\t\"mssql\",\n\t\"mongodb\",\n\t\"sqlite\",\n\t// \"redis\"\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\";\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 { databaseSchema } from \"./database.types.js\";\n\n// UI message part schema (from @tanstack/ai-react)\nconst messagePart = z\n\t.object({\n\t\ttype: z.string(),\n\t\tcontent: z.string().optional(),\n\t})\n\t.passthrough();\n\n// `@tanstack/ai-react`'s `fetchServerSentEvents` adapter sends UI messages\n// with `parts` (not `content`) and wraps extra body under `data`.\nexport const chatSchema = z.object({\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\"]),\n\t\t\t\tparts: z.array(messagePart),\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}),\n});\n","export type Args = {\n\tenv?: string;\n\tport?: string;\n\tdatabaseUrl?: string;\n\tvarName?: string;\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 { 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","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 } 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\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 \"./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-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 \"./rate-limit-response.type.js\";\nexport * from \"./rename-column.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\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\tconst pool = await getMssqlPool();\n\t\tconst result = await pool.request().query(`\n\t\t\tSELECT\n\t\t\t d.name AS name,\n\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 SUSER_SNAME(d.owner_sid) AS owner,\n\t\t\t d.collation_name AS encoding\n\t\t\tFROM sys.databases d\n\t\t\tJOIN sys.master_files mf ON d.database_id = mf.database_id\n\t\t\tWHERE d.database_id > 4\n\t\t\tGROUP BY d.name, d.owner_sid, d.collation_name\n\t\t\tORDER BY d.name\n\t\t`);\n\t\tif (!result.recordset[0]) {\n\t\t\tthrow new HTTPException(500, { message: \"No databases returned from server\" });\n\t\t}\n\t\treturn result.recordset as DatabaseInfoSchemaType[];\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 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, updates, primaryKey } = params;\n\t\tconst pool = await getMssqlPool(db);\n\n\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\tconst updatesByRow = new Map<unknown, Array<{ columnName: string; value: unknown }>>();\n\t\tfor (const update of updates) {\n\t\t\tconst pkValue = update.rowData[primaryKey];\n\t\t\tif (pkValue === undefined || pkValue === null) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Primary key \"${primaryKey}\" not found in row data.`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!updatesByRow.has(pkValue)) updatesByRow.set(pkValue, []);\n\t\t\tupdatesByRow.get(pkValue)?.push({ columnName: update.columnName, value: update.value });\n\t\t}\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 [pkValue, rowUpdates] of updatesByRow.entries()) {\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\trequest.input(\"pkValue\", pkValue);\n\n\t\t\t\tconst result = await request.query(\n\t\t\t\t\t`UPDATE [${tableName}] SET ${setClauses.join(\", \")} WHERE [${primaryKey}] = @pkValue`,\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 ${primaryKey} = ${pkValue} 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\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\tconst pool = getMysqlPool();\n\t\tconst [rows] = await pool.execute<RowDataPacket[]>(`\n\t\t\tSELECT\n\t\t\t s.SCHEMA_NAME AS name,\n\t\t\t CONCAT(ROUND(COALESCE(SUM(t.data_length + t.index_length), 0) / 1024 / 1024, 2), ' MB') AS size,\n\t\t\t CURRENT_USER() AS owner,\n\t\t\t s.DEFAULT_CHARACTER_SET_NAME AS encoding\n\t\t\tFROM information_schema.SCHEMATA s\n\t\t\tLEFT JOIN information_schema.TABLES t ON t.TABLE_SCHEMA = s.SCHEMA_NAME\n\t\t\tGROUP BY s.SCHEMA_NAME, s.DEFAULT_CHARACTER_SET_NAME\n\t\t\tORDER BY s.SCHEMA_NAME\n\t\t`);\n\t\tif (!rows[0])\n\t\t\tthrow new HTTPException(500, { message: \"No databases returned from server\" });\n\t\treturn rows as DatabaseInfoSchemaType[];\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 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, updates, primaryKey } = params;\n\t\tconst pool = getMysqlPool(db);\n\n\t\tconst booleanColumns = await this.getBooleanColumnSet(tableName, db);\n\n\t\tconst updatesByRow = new Map<unknown, Array<{ columnName: string; value: unknown }>>();\n\t\tfor (const update of updates) {\n\t\t\tconst pkValue = update.rowData[primaryKey];\n\t\t\tif (pkValue === undefined || pkValue === null) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Primary key \"${primaryKey}\" not found in row data.`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!updatesByRow.has(pkValue)) updatesByRow.set(pkValue, []);\n\t\t\tupdatesByRow.get(pkValue)?.push({ columnName: update.columnName, value: update.value });\n\t\t}\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 [pkValue, rowUpdates] of updatesByRow.entries()) {\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(pkValue);\n\n\t\t\t\tconst [result] = await connection.execute<ResultSetHeader>(\n\t\t\t\t\t`UPDATE \\`${tableName}\\` SET ${setClauses.join(\", \")} WHERE \\`${primaryKey}\\` = ?`,\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 ${primaryKey} = ${pkValue} 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","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\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} 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\tconst pool = getDbPool();\n\t\tconst { rows } = await pool.query(`\n\t\t\tSELECT\n\t\t\t\td.datname as name,\n\t\t\t\tpg_size_pretty(pg_database_size(d.datname)) as size,\n\t\t\t\tpg_catalog.pg_get_userbyid(d.datdba) as owner,\n\t\t\t\tpg_encoding_to_char(d.encoding) as encoding\n\t\t\tFROM pg_catalog.pg_database d\n\t\t\tWHERE d.datistemplate = false\n\t\t\tORDER BY d.datname;\n\t\t`);\n\t\tif (!rows[0])\n\t\t\tthrow new HTTPException(500, { message: \"No databases returned from database\" });\n\t\treturn rows;\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 = 'public') 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 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 = 'public' 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 = 'public' 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 = 'public' 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 = 'public' AND tablename = $1\n\t\t\t AND indexname NOT IN (SELECT constraint_name FROM information_schema.table_constraints WHERE table_schema = 'public' 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 = 'public' 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 = 'public' AND tc.table_name = $1\n\t\t\t) fk ON c.column_name = fk.column_name\n\t\t\tWHERE c.table_schema = 'public' 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 = 'public') 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 = 'public') 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 = 'public') 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 = 'public') 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 = 'public') 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 = 'public') 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 = 'public') 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 = 'public') 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, updates, primaryKey } = params;\n\t\tconst pool = getDbPool(db);\n\n\t\tconst updatesByRow = new Map<unknown, Array<{ columnName: string; value: unknown }>>();\n\t\tfor (const u of updates) {\n\t\t\tconst pkValue = u.rowData[primaryKey];\n\t\t\tif (pkValue === undefined || pkValue === null)\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Primary key \"${primaryKey}\" not found in row data.`,\n\t\t\t\t});\n\t\t\tif (!updatesByRow.has(pkValue)) updatesByRow.set(pkValue, []);\n\t\t\tupdatesByRow.get(pkValue)?.push({ columnName: u.columnName, value: u.value });\n\t\t}\n\n\t\tawait pool.query(\"BEGIN\");\n\t\ttry {\n\t\t\tlet total = 0;\n\t\t\tfor (const [pkValue, rowUpdates] of updatesByRow.entries()) {\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\tvalues.push(pkValue);\n\t\t\t\tconst result = await pool.query(\n\t\t\t\t\t`UPDATE \"${tableName}\" SET ${setClauses.join(\", \")} WHERE \"${primaryKey}\" = $${values.length} 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 ${primaryKey} = ${pkValue} 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 type {\n\tAddColumnParamsSchemaType,\n\tAddRecordSchemaType,\n\tAlterColumnParamsSchemaType,\n\tBulkInsertRecordsParams,\n\tBulkInsertResult,\n\tCellValue,\n\tColumnInfoSchemaType,\n\tConnectionInfoSchemaType,\n\tDatabaseInfoSchemaType,\n\tDatabaseSchemaType,\n\tDataTypes,\n\tDeleteColumnParamsSchemaType,\n\tDeleteRecordParams,\n\tDeleteRecordResult,\n\tDeleteTableParams,\n\tDeleteTableResult,\n\tExecuteQueryResult,\n\tRenameColumnParamsSchemaType,\n\tTableDataResultSchemaType,\n\tTableInfoSchemaType,\n\tUpdateRecordsSchemaType,\n} from \"@db-studio/shared/types\";\nimport { HTTPException } from \"hono/http-exception\";\nimport type { Redis } from \"ioredis\";\nimport type { GetTableDataParams } from \"@/adapters/adapter.interface.js\";\nimport { BaseAdapter, type NormalizedRow, type QueryBundle } from \"@/adapters/base.adapter.js\";\nimport { getRedisClient, getRedisDefaultDb } from \"@/adapters/connections.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;\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\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 {\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\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\tconst configReply = (await client.call(\"CONFIG\", \"GET\", \"databases\")) as unknown;\n\t\t\tlet total = 16;\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) total = parsed;\n\t\t\t}\n\n\t\t\tconst keyspaceInfo = await client.info(\"keyspace\");\n\t\t\tconst keysPerDb = parseKeyspaceInfo(keyspaceInfo);\n\n\t\t\treturn Array.from({ length: total }, (_, i) => ({\n\t\t\t\tname: String(i),\n\t\t\t\tsize: `${keysPerDb.get(i) ?? 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\")) as unknown;\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 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 } = params;\n\t\t\tconst table = assertRedisTable(tableName);\n\t\t\tconst pkField = 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\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, CellValue>[] }> {\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\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\treturn rows.map((row) => ({\n\t\t\t\tname: row.name,\n\t\t\t\tsize: this.getFileSize(row.file),\n\t\t\t\towner: \"\",\n\t\t\t\tencoding: \"UTF-8\",\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 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 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, updates, primaryKey } = params;\n\t\tconst sqliteDb = getSqliteDb();\n\n\t\tconst updatesByRow = new Map<unknown, Array<{ columnName: string; value: unknown }>>();\n\t\tfor (const u of updates) {\n\t\t\tconst pkValue = u.rowData[primaryKey];\n\t\t\tif (pkValue === undefined || pkValue === null) {\n\t\t\t\tthrow new HTTPException(400, {\n\t\t\t\t\tmessage: `Primary key \"${primaryKey}\" not found in row data.`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!updatesByRow.has(pkValue)) updatesByRow.set(pkValue, []);\n\t\t\tupdatesByRow.get(pkValue)?.push({ columnName: u.columnName, value: u.value });\n\t\t}\n\n\t\tconst doUpdate = sqliteDb.transaction(() => {\n\t\t\tlet total = 0;\n\t\t\tfor (const [pkValue, rowUpdates] of updatesByRow.entries()) {\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\tpkValue,\n\t\t\t\t];\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 \"${primaryKey}\" = ?`)\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 ${primaryKey} = ${pkValue} 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\";\n\n/**\n * Centralized error handler for the application\n */\nexport function handleError(e: Error | unknown, c: Context) {\n\tconsole.error(\"handleError:\", e);\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\t// MySQL-specific error codes\n\t\tconst mysqlError = e as { code?: string; errno?: number };\n\t\tconst isMysqlConnectionError =\n\t\t\tmysqlError.code === \"ECONNREFUSED\" ||\n\t\t\tmysqlError.code === \"ENOTFOUND\" ||\n\t\t\tmysqlError.code === \"ETIMEDOUT\" ||\n\t\t\tmysqlError.code === \"ER_ACCESS_DENIED_ERROR\" ||\n\t\t\tmysqlError.code === \"ER_BAD_HOST_ERROR\" ||\n\t\t\tmysqlError.code === \"ECONNRESET\" ||\n\t\t\tmysqlError.errno === 1045 || // ER_ACCESS_DENIED_ERROR\n\t\t\tmysqlError.errno === 2003 || // Can't connect to MySQL server\n\t\t\tmysqlError.errno === 2002; // Can't connect to local MySQL server\n\n\t\tconst isConnectionError =\n\t\t\tisMysqlConnectionError ||\n\t\t\te.message.includes(\"ECONNREFUSED\") ||\n\t\t\te.message.includes(\"connection refused\") ||\n\t\t\te.message.includes(\"timeout expired\") ||\n\t\t\te.message.includes(\"Connection terminated\") ||\n\t\t\te.message.includes(\"MongoNetworkError\") ||\n\t\t\te.message.includes(\"MongoServerSelectionError\") ||\n\t\t\t(e instanceof DatabaseError && e.code?.startsWith(\"08\")); // PostgreSQL connection exception class\n\n\t\tif (isConnectionError) {\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): string {\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 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 tableNames = tablesList\n\t\t\t.slice(0, maxTables ?? tablesList.length)\n\t\t\t.map((t) => t.tableName);\n\n\t\tconst tablePromises = tableNames.map(async (tableName) => {\n\t\t\tconst [columns, sampleData] = await Promise.all([\n\t\t\t\tadapter.getTableColumns({ 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: 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 } from \"@db-studio/shared/constants\";\nimport { chatSchema } from \"@db-studio/shared/types\";\nimport { zValidator } from \"@hono/zod-validator\";\nimport { Hono } from \"hono\";\nimport { generateSystemPrompt } from \"@/utils/system-prompt-generator.js\";\nimport { getDetailedSchema } from \"@/utils/table-details-schema.js\";\n\nexport const chatRoutes = new Hono()\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\tconst proxyResponse = await fetch(`${DEFAULTS.PROXY_URL}/chat/limit`, {\n\t\t\theaders: {\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},\n\t\t});\n\t\tconst data = await proxyResponse.json();\n\t\treturn c.json(data, proxyResponse.status as 200 | 500);\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 } = c.req.valid(\"json\");\n\t\tconst { db, conversationId } = data;\n\t\tconsole.log(\"POST /chat messages\", messages);\n\n\t\t// Get the database schema and generate system prompt\n\t\tconst schema = await getDetailedSchema(db);\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};\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(`${DEFAULTS.PROXY_URL}/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},\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 | 500,\n\t\t\t);\n\t\t}\n\n\t\t// Stream the SSE response back to the client\n\t\tconst { readable, writable } = new TransformStream();\n\t\tproxyResponse.body?.pipeTo(writable);\n\n\t\treturn new Response(readable, {\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/event-stream\",\n\t\t\t\t\"Cache-Control\": \"no-cache\",\n\t\t\t\tConnection: \"keep-alive\",\n\t\t\t},\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 all databases on the server (name, size, owner, encoding)\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 all 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\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, CellValue>[];\n\tformat: FormatType;\n\ttableName: string;\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 data: CellValue[][] = [\n\t\t\t\tcols,\n\t\t\t\t...(rows?.map((row) => cols?.map((col) => row[col])) ?? []),\n\t\t\t];\n\t\t\tconst worksheet = utils.aoa_to_sheet(data);\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 data: CellValue[][] = [\n\t\t\t\tcols,\n\t\t\t\t...(rows?.map((row) => cols?.map((col) => row[col])) ?? []),\n\t\t\t];\n\t\t\tconst worksheet = utils.aoa_to_sheet(data);\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\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 * 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 { 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 { chatRoutes } from \"@/routes/chat.routes.js\";\nimport { databasesRoutes } from \"@/routes/databases.routes.js\";\nimport { queryRoutes } from \"@/routes/query.routes.js\";\nimport { recordsRoutes } from \"@/routes/records.routes.js\";\nimport { tablesRoutes } from \"@/routes/tables.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.use(\"/*\", cors())\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/**\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 CORS requests\n\t\t */\n\t\t.use(\"*\", async (c, next) => {\n\t\t\tc.header(\"Access-Control-Allow-Origin\", \"*\");\n\t\t\tc.header(\"Access-Control-Allow-Methods\", \"GET, POST, PUT, DELETE, OPTIONS\");\n\t\t\tc.header(\"Access-Control-Allow-Headers\", \"Content-Type\");\n\t\t\tawait next();\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\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 } = c.req.valid(\"param\");\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\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","import { intro, outro } 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 { 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, 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 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 ENV = env ? await loadEnv(env) : await loadEnv();\n\tconst DATABASE_URL = databaseUrl ? databaseUrl : await getDatabaseUrl(ENV, VAR_NAME);\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\t// Import createServer dynamically after setting DATABASE_URL\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\toutro(color.green(`Server running at ${color.cyan(serverUrl)}`));\n};\n\nmain().catch((err) => {\n\tconsole.error(color.red(`❌ Unexpected error: ${err.message}`));\n\tprocess.exit(1);\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(\"-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\treturn program.opts<Args>();\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 { 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(\" MySQL, PostgreSQL\\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\" -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(color.dim(\" • Supported databases: MySQL, PostgreSQL\"));\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","{\n \"name\": \"db-studio\",\n \"type\": \"module\",\n \"version\": \"1.9.6\",\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\\u00fcsam \\ud83e\\udd51 <devhsmq@gmail.com>\",\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\": \"BSL-1.1\",\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 --sourcemap\",\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.dbstudio\",\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.8.0\",\n \"better-sqlite3\": \"^12.9.0\",\n \"commander\": \"^15.0.0\",\n \"dotenv\": \"^17.3.1\",\n \"hono\": \"^4.10.4\",\n \"ioredis\": \"^5.4.1\",\n \"mongodb\": \"^7.1.1\",\n \"mssql\": \"^12.2.0\",\n \"mysql2\": \"^3.18.2\",\n \"pg\": \"^8.13.1\",\n \"picocolors\": \"^1.1.1\",\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 \"@types/better-sqlite3\": \"^7.6.13\",\n \"@types/mssql\": \"^12.3.0\",\n \"@types/node\": \"^26.0.0\",\n \"@types/pg\": \"^8.16.0\",\n \"@vitest/coverage-v8\": \"^4.0.17\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.7.1\",\n \"typescript\": \"^6.0.3\",\n \"vitest\": \"^4.0.17\"\n }\n}\n"],"mappings":"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","names":["init_chat","__esmMin","init_column_types_mysql","__esmMin","init_column_types_pgsql","__esmMin","env","nodeEnv","DEFAULTS","init_defaults","__esmMin","init_links","__esmMin","META","init_meta","__esmMin","init_proxy_limits","__esmMin","init_constants","__esmMin","init_chat","init_column_types_mysql","init_column_types_pgsql","init_defaults","init_links","init_meta","init_proxy_limits","HTTPException","getAdapter","dbType","adapterRegistry","AdapterRegistry","init_adapter_registry","__esmMin","type","adapter","HTTPException","DatabaseError","notImplemented","method","BaseAdapter","init_base_adapter","__esmMin","err","data","cursor","row","out","k","v","params","db","limit","direction","bundle","countRes","total","rawRows","hasMore","rows","nextCursor","prevCursor","e","tableName","sql","_db","_params","Database","Redis","MongoClient","ObjectId","mssql","createMysqlPool","Pool","DatabaseManager","databaseManager","getDbPool","getMysqlPool","getMssqlPool","getDbType","getSqliteDb","getMongoClient","getMongoDbName","getMongoDb","getRedisClient","getRedisDefaultDb","isValidObjectId","coerceObjectId","init_db_manager","__esmMin","url","protocol","databaseUrl","detectedType","defaultPort","error","database","filePath","db","connectionString","poolConfig","pool","err","dbName","config","nextClient","dbIndex","index","existing","options","client","info","path","parsed","pgClosePromises","mysqlClosePromises","mssqlClosePromises","redisClosePromises","value","getDbPool","getMysqlPool","getMssqlPool","getSqliteDb","getMongoClient","getMongoDbName","getMongoDb","getRedisClient","getRedisDefaultDb","init_connections","__esmMin","init_db_manager","database","dbName","dbIndex","parseDatabaseUrl","databaseUrl","url","protocol","defaultPort","init_parse_database_url","__esmMin","buildMatchStage","filters","andConditions","filter","field","value","parseFilterValue","op","escapeRegex","buildSortStage","sort","order","s","encodeMongoCursor","offset","decodeMongoCursor","cursor","parsed","init_mongo_pipeline_builder","__esmMin","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_base_adapter","init_connections","init_db_manager","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","getMongoDbName","admin","urlDefaults","parseDatabaseUrl","serverStatus","mongoDb","collections","results","col","rowCount","tableData","fields","properties","required","field","bsonType","docs","totalDocs","fieldTypes","fieldPresence","key","types","presence","typeList","t","isNullable","schema","documents","columnMap","ensureColumn","columnName","entry","meta","resolvedDefault","existingSchema","reqIndex","newColumnName","data","payload","updates","primaryKey","totalUpdated","pkField","updatesByRow","update","pkValue","updateSet","queryValue","result","primaryKeys","pkColumn","pkValues","pk","records","record","query","startTime","message","duration","z","databaseSchema","DATABASE_TYPES","databaseTypeSchema","currentDatabaseSchema","databaseTypeParamSchema","tableNameSchema","init_database_types","__esmMin","z","addColumnSchema","addColumnParamSchema","addColumnParamsSchema","init_add_column_types","__esmMin","init_database_types","tableNameSchema","databaseSchema","z","addRecordSchema","init_add_record_types","__esmMin","z","deleteColumnQuerySchema","deleteColumnParamSchema","deleteColumnParamsSchema","deleteColumnSuccessResponseSchema","init_delete_column_types","__esmMin","init_database_types","databaseSchema","val","z","alterColumnSchema","alterColumnParamSchema","alterColumnParamsSchema","init_alter_column_types","__esmMin","init_database_types","init_delete_column_types","deleteColumnParamSchema","databaseSchema","init_api_response_types","__esmMin","z","bulkInsertRecordsSchema","init_bulk_insert_records_type","__esmMin","z","messagePart","chatSchema","init_chat_types","__esmMin","init_database_types","databaseSchema","init_cmd_args_types","__esmMin","z","dataTypes","dataTypesSchema","DataTypes","standardizedDataTypes","standardizedDataTypeSchema","columnInfoSchema","init_column_info_types","__esmMin","mapPostgresToDataType","pgType","normalized","DataTypes","standardizeDataTypeLabel","StandardizedDataType","mapMysqlToDataType","mysqlDataType","columnType","fullType","standardizeMysqlDataTypeLabel","mapMssqlToDataType","mssqlDataType","standardizeMssqlDataTypeLabel","mapSqliteToDataType","sqliteType","standardizeSqliteDataTypeLabel","init_column_type","__esmMin","init_column_info_types","z","FOREIGN_KEY_ACTIONS","foreignKeyActionSchema","fieldDataSchema","foreignKeyDataSchema","createTableSchema","init_create_table_types","__esmMin","z","databaseInfoSchema","databaseListSchema","connectionInfoSchema","init_database_list_types","__esmMin","init_database_types","databaseTypeSchema","init_database_schema_type","__esmMin","z","deleteRecordSchema","init_delete_record_types","__esmMin","z","deleteTableQuerySchema","init_delete_table_types","__esmMin","init_database_types","databaseSchema","val","z","executeQuerySchema","init_execute_query_types","__esmMin","z","FORMAT_TYPES","exportTableSchema","init_export_table_types","__esmMin","init_database_types","databaseSchema","init_rate_limit_response_type","__esmMin","z","renameColumnSchema","renameColumnParamSchema","renameColumnParamsSchema","init_rename_column_types","__esmMin","init_database_types","init_delete_column_types","deleteColumnParamSchema","databaseSchema","z","filterSchema","sortDirections","sortSchema","tableDataMetaSchema","tableDataResultSchema","tableDataQuerySchema","init_table_data_types","__esmMin","init_database_types","databaseSchema","val","parsed","z","tableInfoSchema","init_table_info_type","__esmMin","z","tableSchemaResultSchema","init_table_schema_types","__esmMin","z","updateRecordsSchema","init_update_recors_types","__esmMin","types_exports","__export","DATABASE_TYPES","DataTypes","FOREIGN_KEY_ACTIONS","FORMAT_TYPES","StandardizedDataType","addColumnParamSchema","addColumnParamsSchema","addColumnSchema","addRecordSchema","alterColumnParamSchema","alterColumnParamsSchema","alterColumnSchema","bulkInsertRecordsSchema","chatSchema","columnInfoSchema","connectionInfoSchema","createTableSchema","currentDatabaseSchema","dataTypesSchema","databaseInfoSchema","databaseListSchema","databaseSchema","databaseTypeParamSchema","databaseTypeSchema","deleteColumnParamSchema","deleteColumnParamsSchema","deleteColumnQuerySchema","deleteColumnSuccessResponseSchema","deleteRecordSchema","deleteTableQuerySchema","executeQuerySchema","exportTableSchema","fieldDataSchema","filterSchema","foreignKeyActionSchema","foreignKeyDataSchema","mapMssqlToDataType","mapMysqlToDataType","mapPostgresToDataType","mapSqliteToDataType","renameColumnParamSchema","renameColumnParamsSchema","renameColumnSchema","sortDirections","sortSchema","standardizeDataTypeLabel","standardizeMssqlDataTypeLabel","standardizeMysqlDataTypeLabel","standardizeSqliteDataTypeLabel","standardizedDataTypeSchema","tableDataMetaSchema","tableDataQuerySchema","tableDataResultSchema","tableInfoSchema","tableNameSchema","tableSchemaResultSchema","updateRecordsSchema","init_types","__esmMin","init_add_column_types","init_add_record_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_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_rate_limit_response_type","init_rename_column_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","HTTPException","MSSQL_FK_VIOLATION","MSSQL_FK_DEPENDENCY","MsSqlAdapter","init_mssql_adapter","__esmMin","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","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","updates","primaryKey","updatesByRow","update","pkValue","transaction","rowUpdates","setClauses","u","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","HTTPException","MYSQL_FK_VIOLATION","MYSQL_FK_DEPENDENCY","MySqlAdapter","init_mysql_adapter","__esmMin","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","createTableSql","r","isEnum","standardizeMysqlDataTypeLabel","columnName","columnType","defaultValue","isPrimaryKey","isNullable","isUnique","isIdentity","isArray","colRows","colDef","result","colRow","newColumnName","newColRows","data","booleanColumns","columns","value","i","c","updates","primaryKey","updatesByRow","update","pkValue","rowUpdates","setClauses","u","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","init_pg_query_builder","__esmMin","HTTPException","PgAdapter","init_pg_adapter","__esmMin","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","existsRows","columns","constraints","indexes","formatType","data_type","udt_name","character_maximum_length","numeric_precision","numeric_scale","lines","colDefs","constraintMap","c","arr","constraintDefs","cols","first","colNames","idx","r","parsedEnumValues","standardizeDataTypeLabel","columnName","columnType","defaultValue","isPrimaryKey","isNullable","isUnique","isIdentity","isArray","colRows","client","newColumnName","colExistsQuery","curRows","nextRows","placeholders","_","i","updates","primaryKey","updatesByRow","u","pkValue","rowUpdates","setClauses","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","v","x","idx","rows","section","line","entry","id","fields","fieldsObj","HTTPException","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","isRedisTable","assertRedisTable","parseDbIndex","encodeScanCursor","decodeScanCursor","columnInfo","KEY_COL","TTL_COL","TABLE_COLUMNS","SCHEMA_DESCRIPTIONS","RedisAdapter","init_redis_adapter","__esmMin","init_base_adapter","init_connections","init_redis_command_shaper","name","tableName","db","getRedisDefaultDb","env","cursor","overrides","BaseAdapter","_params","rawRows","row","nativeType","_universalType","client","getRedisClient","configReply","total","keyspaceInfo","keysPerDb","_","serverInfo","clientsInfo","server","clients","maxclients","opts","dbIndex","counts","e","table","params","limit","direction","sort","filters","redisType","scanCursor","decoded","collectedKeys","rounds","scanComplete","next","batch","pageKeys","overflow","rows","hasNextPage","nextCursor","keys","ttlPipeline","key","ttlResults","valuePipeline","valueResults","ttl","raw","cached","pipeline","results","updates","primaryKey","pkField","updatesByKey","u","keyStr","existing","updatedCount","primaryKeys","pk","deletedCount","records","errors","successCount","record","allKeys","c","flat","field","val","entries","args","query","startTime","argv","tokenizeCommand","cmd","rest","message","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","statSync","HTTPException","SqliteAdapter","init_sqlite_adapter","__esmMin","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","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","updates","primaryKey","updatesByRow","u","pkValue","doUpdate","rowUpdates","setClauses","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_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","issue","mysqlError","init_error_handler","__esmMin","generateSystemPrompt","schema","dbTypeLower","dbTypeLabel","formatSchemaForPrompt","output","table","col","pkIndicator","fkIndicator","nullable","rel","init_system_prompt_generator","__esmMin","convertColumnInfo","col","column","extractRelationships","tables","relationships","table","toTable","toColumn","stringifySampleValue","value","getSampleData","adapter","tableName","db","row","key","getDatabaseSchema","options","dbType","getDbType","includeSampleData","maxTables","getAdapter","tablesList","tablePromises","t","columns","sampleData","error","getDetailedSchema","init_table_details_schema","__esmMin","init_adapter_registry","init_db_manager","zValidator","Hono","chatRoutes","init_chat_routes","__esmMin","init_constants","init_types","init_system_prompt_generator","init_table_details_schema","c","proxyResponse","DEFAULTS","data","chatSchema","messages","db","conversationId","schema","getDetailedSchema","systemPrompt","generateSystemPrompt","payload","errorData","readable","writable","Hono","databasesRoutes","init_databases_routes","__esmMin","init_adapter_registry","init_db_manager","c","dbType","getDbType","databases","getAdapter","current","info","zValidator","Hono","queryRoutes","init_query_routes","__esmMin","init_types","init_adapter_registry","databaseSchema","executeQuerySchema","c","query","db","dbType","data","getAdapter","zValidator","Hono","recordsRoutes","init_records_routes","__esmMin","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","data","row","col","worksheet","csvContent","workbook","buffer","init_get_export_file","__esmMin","zValidator","Hono","tablesRoutes","init_tables_routes","__esmMin","init_types","init_adapter_registry","init_get_export_file","databaseSchema","c","db","dbType","tablesList","getAdapter","createTableSchema","body","deleteTableQuerySchema","tableNameSchema","cascade","tableName","result","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","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_constants","init_adapter_registry","init_register","init_error_handler","init_chat_routes","init_databases_routes","init_query_routes","init_records_routes","init_tables_routes","DEFAULTS","__dirname","bundledWebDistPath","localWebDistPath","bundledIndexPath","localIndexPath","type","adapterRegistry","registerAdapters","app","_","next","c","handleError","databasesRoutes","chatRoutes","result","rawType","dbType","tablesRoutes","recordsRoutes","queryRoutes","init_constants","intro","outro","serve","color","program","args","readFile","resolve","cancel","isCancel","note","select","spinner","text","parseDotenv","color","getDatabaseUrl","env","varName","envVarName","s","choice","customPath","value","customEnvPath","content","parsed","e","error","dbUrl","access","readFile","dirname","resolve","parseDotenv","findEnvPath","startDir","dir","envPath","parent","loadEnv","env","content","err","init_meta","intro","outro","color","showHelp","META","init_constants","intro","note","outro","color","showStatus","env","databaseUrl","varName","intro","color","envVarName","DEFAULTS","foundUrl","ENV","loadEnv","outro","note","intro","outro","color","package_default","showVersion","intro","color","outro","package_default","main","env","port","databaseUrl","varName","status","help","version","args","showHelp","showVersion","showStatus","intro","color","PORT","DEFAULTS","HOST","VAR_NAME","ENV","loadEnv","DATABASE_URL","getDatabaseUrl","createServer","app","serve","serverUrl","outro","err"]}
|