@libredb/studio 0.9.7

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.
Files changed (572) hide show
  1. package/.claude/settings.local.json +127 -0
  2. package/.cursorrules +426 -0
  3. package/.devin/wiki.json +143 -0
  4. package/.dockerignore +80 -0
  5. package/.env.example +159 -0
  6. package/.github/ISSUE_TEMPLATE/bug_report.md +49 -0
  7. package/.github/ISSUE_TEMPLATE/feature_request.md +29 -0
  8. package/.github/PULL_REQUEST_TEMPLATE.md +57 -0
  9. package/.github/workflows/ci.yml +185 -0
  10. package/.github/workflows/codeql.yml +57 -0
  11. package/.github/workflows/docker-build-push.yml +118 -0
  12. package/.github/workflows/helm-release.yml +113 -0
  13. package/CLAUDE.md +265 -0
  14. package/CODE_OF_CONDUCT.md +124 -0
  15. package/CONTRIBUTING.md +154 -0
  16. package/Dockerfile +73 -0
  17. package/LICENSE +21 -0
  18. package/README.md +614 -0
  19. package/SECURITY.md +107 -0
  20. package/artifacthub-repo.yml +4 -0
  21. package/bun.lock +1714 -0
  22. package/bunfig.toml +3 -0
  23. package/charts/libredb-studio/.helmignore +11 -0
  24. package/charts/libredb-studio/Chart.lock +6 -0
  25. package/charts/libredb-studio/Chart.yaml +50 -0
  26. package/charts/libredb-studio/README.md +206 -0
  27. package/charts/libredb-studio/templates/NOTES.txt +59 -0
  28. package/charts/libredb-studio/templates/_helpers.tpl +135 -0
  29. package/charts/libredb-studio/templates/configmap.yaml +37 -0
  30. package/charts/libredb-studio/templates/deployment.yaml +184 -0
  31. package/charts/libredb-studio/templates/hpa.yaml +32 -0
  32. package/charts/libredb-studio/templates/ingress.yaml +41 -0
  33. package/charts/libredb-studio/templates/networkpolicy.yaml +50 -0
  34. package/charts/libredb-studio/templates/pdb.yaml +18 -0
  35. package/charts/libredb-studio/templates/pvc.yaml +23 -0
  36. package/charts/libredb-studio/templates/secret.yaml +30 -0
  37. package/charts/libredb-studio/templates/seed-configmap.yaml +11 -0
  38. package/charts/libredb-studio/templates/service.yaml +22 -0
  39. package/charts/libredb-studio/templates/serviceaccount.yaml +13 -0
  40. package/charts/libredb-studio/values.schema.json +246 -0
  41. package/charts/libredb-studio/values.yaml +286 -0
  42. package/components.json +22 -0
  43. package/conductor/code_styleguides/typescript.md +43 -0
  44. package/conductor/product-guidelines.md +43 -0
  45. package/conductor/product.md +3 -0
  46. package/conductor/setup_state.json +1 -0
  47. package/conductor/tech-stack.md +39 -0
  48. package/conductor/tracks/enhance_postgres_monitoring_20251227/metadata.json +8 -0
  49. package/conductor/tracks/enhance_postgres_monitoring_20251227/plan.md +44 -0
  50. package/conductor/tracks/enhance_postgres_monitoring_20251227/spec.md +31 -0
  51. package/conductor/tracks.md +8 -0
  52. package/conductor/workflow.md +333 -0
  53. package/database-compose.yml +55 -0
  54. package/docker/postgres-init/01-extensions.sql +10 -0
  55. package/docker/postgres-init/02-sample-data.sql +585 -0
  56. package/docker/postgres.yml +68 -0
  57. package/docker-compose.yml +38 -0
  58. package/docs/AI_PLAN.md +74 -0
  59. package/docs/API_DOCS.md +875 -0
  60. package/docs/ARCHITECTURE.md +218 -0
  61. package/docs/DATABASE_PROVIDERS.md +358 -0
  62. package/docs/FEATURES.md +116 -0
  63. package/docs/HELM_CHART.md +252 -0
  64. package/docs/LOGIN_PAGE.md +178 -0
  65. package/docs/MONACO_EDITOR_PERFORMANCE.md +315 -0
  66. package/docs/OIDC_ARCH.md +681 -0
  67. package/docs/OIDC_SETUP.md +322 -0
  68. package/docs/POSTGRES_METRICS.md +516 -0
  69. package/docs/QUERY_OPTIMIZATION.md +370 -0
  70. package/docs/SEED_CONNECTIONS.md +468 -0
  71. package/docs/SQL_ALIAS_COMPLETION.md +190 -0
  72. package/docs/STORAGE_ARCHITECTURE.md +565 -0
  73. package/docs/STORAGE_QUICK_SETUP.md +419 -0
  74. package/docs/TECHNICAL_PLAN.md +36 -0
  75. package/docs/THEMING.md +345 -0
  76. package/docs/adding-a-new-database-provider.md +642 -0
  77. package/docs/backlogs/000-PLATFORM_DATA_SYNC_DATABASE.md +360 -0
  78. package/docs/backlogs/001-INLINE_DATA_EDITING.md +118 -0
  79. package/docs/backlogs/002-DATA_IMPORT.md +215 -0
  80. package/docs/backlogs/003-QUERY_TIME_MACHINE.md +183 -0
  81. package/docs/backlogs/004-AI_DATA_STORYTELLER.md +292 -0
  82. package/docs/backlogs/005-QUERY_PLAYGROUND.md +352 -0
  83. package/docs/backlogs/006-DATA_MASKING.md +418 -0
  84. package/docs/enterprise-features.md +718 -0
  85. package/docs/kubernetes-helm-chart-artifacthub-plan.md +803 -0
  86. package/docs/medium-koyeb-article-en.md +215 -0
  87. package/docs/plans/test-plans.md +445 -0
  88. package/docs/releases/RELEASE.V0.3.0.md +22 -0
  89. package/docs/releases/RELEASE.V0.4.0.md +154 -0
  90. package/docs/releases/RELEASE.V0.5.0.md +252 -0
  91. package/docs/releases/RELEASE_v0.5.6.md +145 -0
  92. package/docs/releases/RELEASE_v0.6.1.md +303 -0
  93. package/docs/releases/RELEASE_v0.6.7.md +292 -0
  94. package/docs/releases/RELEASE_v0.7.0.md +332 -0
  95. package/docs/releases/RELEASE_v0.8.0.md +521 -0
  96. package/docs/sampledb/titanic.sql +1379 -0
  97. package/docs/superpowers/plans/2026-03-25-seed-connections.md +1362 -0
  98. package/docs/superpowers/specs/2026-03-25-seed-connections-design.md +590 -0
  99. package/e2e/admin-dashboard.spec.ts +64 -0
  100. package/e2e/connection-management.spec.ts +58 -0
  101. package/e2e/export.spec.ts +34 -0
  102. package/e2e/login.spec.ts +85 -0
  103. package/e2e/query-execution.spec.ts +35 -0
  104. package/e2e/tab-management.spec.ts +64 -0
  105. package/eslint.config.mjs +28 -0
  106. package/fly.toml +43 -0
  107. package/next.config.ts +32 -0
  108. package/package.json +130 -0
  109. package/playwright.config.ts +34 -0
  110. package/postcss.config.mjs +7 -0
  111. package/public/favicon-32x32.png +0 -0
  112. package/public/favicon.ico +0 -0
  113. package/public/file.svg +1 -0
  114. package/public/globe.svg +1 -0
  115. package/public/logo.svg +32 -0
  116. package/public/next.svg +1 -0
  117. package/public/screenshots/code-generator.png +0 -0
  118. package/public/screenshots/connection-modal.png +0 -0
  119. package/public/screenshots/data-profiler.png +0 -0
  120. package/public/screenshots/erd-diagram.png +0 -0
  121. package/public/screenshots/hero-editor.png +0 -0
  122. package/public/screenshots/nl2sql.png +0 -0
  123. package/public/vercel.svg +1 -0
  124. package/public/window.svg +1 -0
  125. package/render.yaml +58 -0
  126. package/scripts/merge-lcov.mjs +239 -0
  127. package/sonar-project.properties +16 -0
  128. package/src/app/admin/error.tsx +46 -0
  129. package/src/app/admin/page.tsx +10 -0
  130. package/src/app/api/admin/audit/route.ts +52 -0
  131. package/src/app/api/admin/fleet-health/route.ts +81 -0
  132. package/src/app/api/ai/autopilot/route.ts +105 -0
  133. package/src/app/api/ai/chat/route.ts +132 -0
  134. package/src/app/api/ai/describe-schema/route.ts +52 -0
  135. package/src/app/api/ai/explain/route.ts +86 -0
  136. package/src/app/api/ai/impact/route.ts +97 -0
  137. package/src/app/api/ai/index-advisor/route.ts +98 -0
  138. package/src/app/api/ai/nl2sql/route.ts +87 -0
  139. package/src/app/api/ai/query-safety/route.ts +87 -0
  140. package/src/app/api/auth/login/route.ts +62 -0
  141. package/src/app/api/auth/logout/route.ts +25 -0
  142. package/src/app/api/auth/me/route.ts +10 -0
  143. package/src/app/api/auth/oidc/callback/route.ts +82 -0
  144. package/src/app/api/auth/oidc/login/route.ts +43 -0
  145. package/src/app/api/connections/managed/route.ts +35 -0
  146. package/src/app/api/db/cancel/route.ts +42 -0
  147. package/src/app/api/db/disconnect/route.ts +28 -0
  148. package/src/app/api/db/health/route.ts +49 -0
  149. package/src/app/api/db/maintenance/route.ts +72 -0
  150. package/src/app/api/db/monitoring/route.ts +62 -0
  151. package/src/app/api/db/multi-query/route.ts +116 -0
  152. package/src/app/api/db/pool-stats/route.ts +37 -0
  153. package/src/app/api/db/profile/route.ts +144 -0
  154. package/src/app/api/db/provider-meta/route.ts +49 -0
  155. package/src/app/api/db/query/route.ts +50 -0
  156. package/src/app/api/db/schema/route.ts +47 -0
  157. package/src/app/api/db/schema-snapshot/route.ts +42 -0
  158. package/src/app/api/db/test-connection/route.ts +55 -0
  159. package/src/app/api/db/transaction/route.ts +111 -0
  160. package/src/app/api/storage/[collection]/route.ts +67 -0
  161. package/src/app/api/storage/config/route.ts +17 -0
  162. package/src/app/api/storage/migrate/route.ts +45 -0
  163. package/src/app/api/storage/route.ts +32 -0
  164. package/src/app/error.tsx +49 -0
  165. package/src/app/global-error.tsx +55 -0
  166. package/src/app/globals.css +146 -0
  167. package/src/app/icon.svg +42 -0
  168. package/src/app/layout.tsx +34 -0
  169. package/src/app/login/login-form.tsx +301 -0
  170. package/src/app/login/page.tsx +11 -0
  171. package/src/app/monitoring/page.tsx +8 -0
  172. package/src/app/not-found.tsx +29 -0
  173. package/src/app/page.tsx +5 -0
  174. package/src/components/AIAutopilotPanel.tsx +238 -0
  175. package/src/components/CodeGenerator.tsx +271 -0
  176. package/src/components/CommandPalette.tsx +227 -0
  177. package/src/components/ConnectionModal.tsx +759 -0
  178. package/src/components/CreateTableModal.tsx +281 -0
  179. package/src/components/DataCharts.tsx +962 -0
  180. package/src/components/DataImportModal.tsx +582 -0
  181. package/src/components/DataProfiler.tsx +335 -0
  182. package/src/components/DatabaseDocs.tsx +251 -0
  183. package/src/components/MaskingSettings.tsx +414 -0
  184. package/src/components/MobileNav.tsx +50 -0
  185. package/src/components/NL2SQLPanel.tsx +281 -0
  186. package/src/components/PivotTable.tsx +257 -0
  187. package/src/components/QueryEditor.tsx +760 -0
  188. package/src/components/QueryHistory.tsx +344 -0
  189. package/src/components/QuerySafetyDialog.tsx +290 -0
  190. package/src/components/ResultsGrid.tsx +644 -0
  191. package/src/components/SaveQueryModal.tsx +104 -0
  192. package/src/components/SavedQueries.tsx +128 -0
  193. package/src/components/SchemaDiagram.tsx +473 -0
  194. package/src/components/SchemaDiff.tsx +473 -0
  195. package/src/components/SnapshotTimeline.tsx +116 -0
  196. package/src/components/Studio.tsx +639 -0
  197. package/src/components/TestDataGenerator.tsx +261 -0
  198. package/src/components/VisualExplain.tsx +820 -0
  199. package/src/components/admin/AdminDashboard.tsx +163 -0
  200. package/src/components/admin/tabs/AuditTab.tsx +531 -0
  201. package/src/components/admin/tabs/MonitoringEmbed.tsx +11 -0
  202. package/src/components/admin/tabs/OperationsTab.tsx +646 -0
  203. package/src/components/admin/tabs/OverviewTab.tsx +1328 -0
  204. package/src/components/admin/tabs/SecurityTab.tsx +284 -0
  205. package/src/components/community-section.tsx +92 -0
  206. package/src/components/icons/db-icons.tsx +84 -0
  207. package/src/components/libredb-logo.tsx +61 -0
  208. package/src/components/monitoring/MonitoringDashboard.tsx +345 -0
  209. package/src/components/monitoring/tabs/MetricChart.tsx +82 -0
  210. package/src/components/monitoring/tabs/OverviewTab.tsx +263 -0
  211. package/src/components/monitoring/tabs/PerformanceTab.tsx +254 -0
  212. package/src/components/monitoring/tabs/PoolTab.tsx +174 -0
  213. package/src/components/monitoring/tabs/QueriesTab.tsx +287 -0
  214. package/src/components/monitoring/tabs/SessionsTab.tsx +316 -0
  215. package/src/components/monitoring/tabs/StorageTab.tsx +335 -0
  216. package/src/components/monitoring/tabs/TablesTab.tsx +300 -0
  217. package/src/components/results-grid/ResultCard.tsx +111 -0
  218. package/src/components/results-grid/RowDetailSheet.tsx +178 -0
  219. package/src/components/results-grid/StatsBar.tsx +201 -0
  220. package/src/components/results-grid/index.ts +1 -0
  221. package/src/components/results-grid/utils.ts +23 -0
  222. package/src/components/schema-explorer/ColumnList.tsx +53 -0
  223. package/src/components/schema-explorer/SchemaExplorer.tsx +182 -0
  224. package/src/components/schema-explorer/TableItem.tsx +210 -0
  225. package/src/components/schema-explorer/index.ts +1 -0
  226. package/src/components/sidebar/ConnectionItem.tsx +105 -0
  227. package/src/components/sidebar/ConnectionsList.tsx +62 -0
  228. package/src/components/sidebar/Sidebar.tsx +130 -0
  229. package/src/components/sidebar/index.ts +2 -0
  230. package/src/components/studio/BottomPanel.tsx +286 -0
  231. package/src/components/studio/QueryToolbar.tsx +180 -0
  232. package/src/components/studio/StudioDesktopHeader.tsx +114 -0
  233. package/src/components/studio/StudioMobileHeader.tsx +340 -0
  234. package/src/components/studio/StudioTabBar.tsx +82 -0
  235. package/src/components/studio/index.ts +5 -0
  236. package/src/components/ui/accordion.tsx +66 -0
  237. package/src/components/ui/alert-dialog.tsx +157 -0
  238. package/src/components/ui/alert.tsx +66 -0
  239. package/src/components/ui/aspect-ratio.tsx +11 -0
  240. package/src/components/ui/avatar.tsx +53 -0
  241. package/src/components/ui/badge.tsx +46 -0
  242. package/src/components/ui/breadcrumb.tsx +109 -0
  243. package/src/components/ui/button-group.tsx +83 -0
  244. package/src/components/ui/button.tsx +60 -0
  245. package/src/components/ui/calendar.tsx +216 -0
  246. package/src/components/ui/card.tsx +92 -0
  247. package/src/components/ui/carousel.tsx +241 -0
  248. package/src/components/ui/chart.tsx +357 -0
  249. package/src/components/ui/checkbox.tsx +32 -0
  250. package/src/components/ui/collapsible.tsx +33 -0
  251. package/src/components/ui/command.tsx +184 -0
  252. package/src/components/ui/context-menu.tsx +252 -0
  253. package/src/components/ui/dialog.tsx +143 -0
  254. package/src/components/ui/drawer.tsx +135 -0
  255. package/src/components/ui/dropdown-menu.tsx +257 -0
  256. package/src/components/ui/empty.tsx +104 -0
  257. package/src/components/ui/field.tsx +248 -0
  258. package/src/components/ui/form.tsx +167 -0
  259. package/src/components/ui/hover-card.tsx +44 -0
  260. package/src/components/ui/input-group.tsx +170 -0
  261. package/src/components/ui/input-otp.tsx +77 -0
  262. package/src/components/ui/input.tsx +21 -0
  263. package/src/components/ui/item.tsx +193 -0
  264. package/src/components/ui/kbd.tsx +28 -0
  265. package/src/components/ui/label.tsx +24 -0
  266. package/src/components/ui/menubar.tsx +276 -0
  267. package/src/components/ui/navigation-menu.tsx +168 -0
  268. package/src/components/ui/pagination.tsx +127 -0
  269. package/src/components/ui/popover.tsx +48 -0
  270. package/src/components/ui/progress.tsx +31 -0
  271. package/src/components/ui/radio-group.tsx +45 -0
  272. package/src/components/ui/resizable.tsx +56 -0
  273. package/src/components/ui/scroll-area.tsx +58 -0
  274. package/src/components/ui/select.tsx +187 -0
  275. package/src/components/ui/separator.tsx +28 -0
  276. package/src/components/ui/sheet.tsx +139 -0
  277. package/src/components/ui/sidebar.tsx +726 -0
  278. package/src/components/ui/skeleton.tsx +13 -0
  279. package/src/components/ui/slider.tsx +63 -0
  280. package/src/components/ui/sonner.tsx +40 -0
  281. package/src/components/ui/spinner.tsx +16 -0
  282. package/src/components/ui/switch.tsx +31 -0
  283. package/src/components/ui/table.tsx +116 -0
  284. package/src/components/ui/tabs.tsx +66 -0
  285. package/src/components/ui/textarea.tsx +18 -0
  286. package/src/components/ui/toggle-group.tsx +83 -0
  287. package/src/components/ui/toggle.tsx +47 -0
  288. package/src/components/ui/tooltip.tsx +61 -0
  289. package/src/exports/components.ts +15 -0
  290. package/src/exports/index.ts +4 -0
  291. package/src/exports/providers.ts +4 -0
  292. package/src/exports/types.ts +26 -0
  293. package/src/hooks/use-ai-chat.ts +182 -0
  294. package/src/hooks/use-all-connections.ts +66 -0
  295. package/src/hooks/use-api-call.ts +71 -0
  296. package/src/hooks/use-auth.ts +51 -0
  297. package/src/hooks/use-connection-form.ts +349 -0
  298. package/src/hooks/use-connection-manager.ts +169 -0
  299. package/src/hooks/use-connection-payload.ts +15 -0
  300. package/src/hooks/use-inline-editing.ts +109 -0
  301. package/src/hooks/use-mobile.ts +20 -0
  302. package/src/hooks/use-monitoring-data.ts +270 -0
  303. package/src/hooks/use-provider-metadata.ts +62 -0
  304. package/src/hooks/use-query-execution.ts +478 -0
  305. package/src/hooks/use-storage-sync.ts +259 -0
  306. package/src/hooks/use-tab-manager.ts +231 -0
  307. package/src/hooks/use-toast.ts +20 -0
  308. package/src/hooks/use-transaction-control.ts +64 -0
  309. package/src/lib/api/error-codes.ts +30 -0
  310. package/src/lib/api/errors.ts +236 -0
  311. package/src/lib/api/with-error-handler.ts +41 -0
  312. package/src/lib/audit.ts +105 -0
  313. package/src/lib/auth.ts +87 -0
  314. package/src/lib/connection-string-parser.ts +172 -0
  315. package/src/lib/data-masking.ts +385 -0
  316. package/src/lib/db/base-provider.ts +325 -0
  317. package/src/lib/db/errors.ts +317 -0
  318. package/src/lib/db/factory.ts +324 -0
  319. package/src/lib/db/index.ts +123 -0
  320. package/src/lib/db/providers/document/index.ts +6 -0
  321. package/src/lib/db/providers/document/mongodb.ts +992 -0
  322. package/src/lib/db/providers/keyvalue/redis.ts +554 -0
  323. package/src/lib/db/providers/sql/index.ts +11 -0
  324. package/src/lib/db/providers/sql/mssql.ts +1065 -0
  325. package/src/lib/db/providers/sql/mysql.ts +978 -0
  326. package/src/lib/db/providers/sql/oracle.ts +1044 -0
  327. package/src/lib/db/providers/sql/postgres.ts +1179 -0
  328. package/src/lib/db/providers/sql/sql-base.ts +174 -0
  329. package/src/lib/db/providers/sql/sqlite.ts +721 -0
  330. package/src/lib/db/types.ts +437 -0
  331. package/src/lib/db/utils/pool-manager.ts +287 -0
  332. package/src/lib/db/utils/query-limiter.ts +239 -0
  333. package/src/lib/db-ui-config.ts +86 -0
  334. package/src/lib/editor/mongodb-completions.ts +172 -0
  335. package/src/lib/editor/sql-completions.ts +280 -0
  336. package/src/lib/llm/base-provider.ts +117 -0
  337. package/src/lib/llm/factory.ts +102 -0
  338. package/src/lib/llm/index.ts +90 -0
  339. package/src/lib/llm/providers/custom.ts +181 -0
  340. package/src/lib/llm/providers/gemini.ts +126 -0
  341. package/src/lib/llm/providers/ollama.ts +154 -0
  342. package/src/lib/llm/providers/openai.ts +146 -0
  343. package/src/lib/llm/types.ts +173 -0
  344. package/src/lib/llm/utils/config.ts +187 -0
  345. package/src/lib/llm/utils/retry.ts +119 -0
  346. package/src/lib/llm/utils/streaming.ts +202 -0
  347. package/src/lib/logger.ts +127 -0
  348. package/src/lib/monitoring-thresholds.ts +44 -0
  349. package/src/lib/oidc.ts +262 -0
  350. package/src/lib/query-generators.ts +61 -0
  351. package/src/lib/schema-diff/diff-engine.ts +273 -0
  352. package/src/lib/schema-diff/migration-generator.ts +208 -0
  353. package/src/lib/schema-diff/types.ts +55 -0
  354. package/src/lib/seed/config-loader.ts +79 -0
  355. package/src/lib/seed/connection-filter.ts +49 -0
  356. package/src/lib/seed/credential-resolver.ts +62 -0
  357. package/src/lib/seed/index.ts +40 -0
  358. package/src/lib/seed/resolve-connection.ts +57 -0
  359. package/src/lib/seed/types.ts +69 -0
  360. package/src/lib/sql/alias-extractor.ts +267 -0
  361. package/src/lib/sql/index.ts +8 -0
  362. package/src/lib/sql/statement-splitter.ts +167 -0
  363. package/src/lib/sql/types.ts +40 -0
  364. package/src/lib/ssh/tunnel.ts +142 -0
  365. package/src/lib/storage/factory.ts +84 -0
  366. package/src/lib/storage/index.ts +14 -0
  367. package/src/lib/storage/local-storage.ts +99 -0
  368. package/src/lib/storage/providers/postgres.ts +225 -0
  369. package/src/lib/storage/providers/sqlite.ts +153 -0
  370. package/src/lib/storage/storage-facade.ts +272 -0
  371. package/src/lib/storage/types.ts +75 -0
  372. package/src/lib/time-series-buffer.ts +58 -0
  373. package/src/lib/types.ts +173 -0
  374. package/src/lib/utils.ts +6 -0
  375. package/src/proxy.ts +104 -0
  376. package/src/types/db-drivers.d.ts +23 -0
  377. package/src/types/html2canvas.d.ts +9 -0
  378. package/tests/api/admin/audit.test.ts +178 -0
  379. package/tests/api/admin/fleet-health.test.ts +183 -0
  380. package/tests/api/ai/autopilot.test.ts +174 -0
  381. package/tests/api/ai/chat.test.ts +250 -0
  382. package/tests/api/ai/describe-schema.test.ts +266 -0
  383. package/tests/api/ai/explain.test.ts +199 -0
  384. package/tests/api/ai/impact.test.ts +168 -0
  385. package/tests/api/ai/index-advisor.test.ts +171 -0
  386. package/tests/api/ai/nl2sql.test.ts +202 -0
  387. package/tests/api/ai/query-safety.test.ts +196 -0
  388. package/tests/api/auth/login.test.ts +170 -0
  389. package/tests/api/auth/logout.test.ts +140 -0
  390. package/tests/api/auth/me.test.ts +73 -0
  391. package/tests/api/auth/oidc-callback.test.ts +215 -0
  392. package/tests/api/auth/oidc-login.test.ts +127 -0
  393. package/tests/api/db/cancel.test.ts +198 -0
  394. package/tests/api/db/disconnect.test.ts +124 -0
  395. package/tests/api/db/health.test.ts +222 -0
  396. package/tests/api/db/maintenance.test.ts +263 -0
  397. package/tests/api/db/monitoring.test.ts +221 -0
  398. package/tests/api/db/multi-query.test.ts +316 -0
  399. package/tests/api/db/pool-stats.test.ts +135 -0
  400. package/tests/api/db/profile.test.ts +330 -0
  401. package/tests/api/db/provider-meta.test.ts +193 -0
  402. package/tests/api/db/query.test.ts +314 -0
  403. package/tests/api/db/schema-snapshot.test.ts +170 -0
  404. package/tests/api/db/schema.test.ts +191 -0
  405. package/tests/api/db/test-connection.test.ts +185 -0
  406. package/tests/api/db/transaction.test.ts +314 -0
  407. package/tests/api/proxy.test.ts +191 -0
  408. package/tests/api/seed/managed-route.test.ts +113 -0
  409. package/tests/api/storage/config.test.ts +42 -0
  410. package/tests/api/storage/storage-routes.test.ts +309 -0
  411. package/tests/components/AIAutopilotPanel.test.tsx +756 -0
  412. package/tests/components/AdminPage.test.tsx +33 -0
  413. package/tests/components/CodeGenerator.test.tsx +182 -0
  414. package/tests/components/CommandPalette.test.tsx +428 -0
  415. package/tests/components/CommunitySection.test.tsx +91 -0
  416. package/tests/components/ConnectionModal.mobile.test.tsx +284 -0
  417. package/tests/components/ConnectionModal.test.tsx +570 -0
  418. package/tests/components/CreateTableModal.test.tsx +383 -0
  419. package/tests/components/DataCharts.test.tsx +739 -0
  420. package/tests/components/DataImportModal.test.tsx +751 -0
  421. package/tests/components/DataProfiler.test.tsx +589 -0
  422. package/tests/components/DatabaseDocs.test.tsx +353 -0
  423. package/tests/components/LoginPage.test.tsx +163 -0
  424. package/tests/components/LoginPageOIDC.test.tsx +92 -0
  425. package/tests/components/MaskingSettings.test.tsx +498 -0
  426. package/tests/components/MobileNav.test.tsx +30 -0
  427. package/tests/components/MonitoringPage.test.tsx +32 -0
  428. package/tests/components/NL2SQLPanel.test.tsx +621 -0
  429. package/tests/components/Page.test.tsx +33 -0
  430. package/tests/components/PivotTable.test.tsx +350 -0
  431. package/tests/components/QueryEditor.test.tsx +1730 -0
  432. package/tests/components/QueryHistory.test.tsx +572 -0
  433. package/tests/components/QuerySafetyDialog.test.tsx +586 -0
  434. package/tests/components/ResultsGrid.test.tsx +804 -0
  435. package/tests/components/RootLayout.test.tsx +83 -0
  436. package/tests/components/SaveQueryModal.test.tsx +25 -0
  437. package/tests/components/SavedQueries.test.tsx +43 -0
  438. package/tests/components/SchemaDiagram.test.tsx +1034 -0
  439. package/tests/components/SchemaDiff.test.tsx +906 -0
  440. package/tests/components/SnapshotTimeline.test.tsx +174 -0
  441. package/tests/components/Studio.test.tsx +1030 -0
  442. package/tests/components/TestDataGenerator.test.tsx +291 -0
  443. package/tests/components/VisualExplain.test.tsx +704 -0
  444. package/tests/components/admin/AdminDashboard.test.tsx +205 -0
  445. package/tests/components/admin/AuditTab.test.tsx +220 -0
  446. package/tests/components/admin/MonitoringEmbed.test.tsx +58 -0
  447. package/tests/components/admin/OperationsTab.test.tsx +975 -0
  448. package/tests/components/admin/OverviewTab.test.tsx +254 -0
  449. package/tests/components/admin/SecurityTab.test.tsx +467 -0
  450. package/tests/components/monitoring/MetricChart.test.tsx +111 -0
  451. package/tests/components/monitoring/MonitoringDashboard.test.tsx +259 -0
  452. package/tests/components/monitoring/OverviewTab.test.tsx +78 -0
  453. package/tests/components/monitoring/PerformanceTab.test.tsx +87 -0
  454. package/tests/components/monitoring/PoolTab.test.tsx +42 -0
  455. package/tests/components/monitoring/QueriesTab.test.tsx +80 -0
  456. package/tests/components/monitoring/SessionsTab.test.tsx +154 -0
  457. package/tests/components/monitoring/StorageTab.test.tsx +127 -0
  458. package/tests/components/monitoring/TablesTab.test.tsx +153 -0
  459. package/tests/components/results-grid/ResultCard.test.tsx +105 -0
  460. package/tests/components/results-grid/RowDetailSheet.test.tsx +308 -0
  461. package/tests/components/results-grid/StatsBar.test.tsx +162 -0
  462. package/tests/components/schema-explorer/ColumnList.test.tsx +151 -0
  463. package/tests/components/schema-explorer/SchemaExplorer.test.tsx +461 -0
  464. package/tests/components/schema-explorer/TableItem.test.tsx +415 -0
  465. package/tests/components/sidebar/ConnectionItem.test.tsx +201 -0
  466. package/tests/components/sidebar/ConnectionsList.test.tsx +176 -0
  467. package/tests/components/sidebar/Sidebar.test.tsx +187 -0
  468. package/tests/components/studio/BottomPanel.test.tsx +383 -0
  469. package/tests/components/studio/QueryToolbar.test.tsx +321 -0
  470. package/tests/components/studio/StudioDesktopHeader.test.tsx +377 -0
  471. package/tests/components/studio/StudioMobileHeader.test.tsx +198 -0
  472. package/tests/components/studio/StudioTabBar.test.tsx +331 -0
  473. package/tests/fixtures/connections.ts +96 -0
  474. package/tests/fixtures/masking-configs.ts +86 -0
  475. package/tests/fixtures/query-results.ts +71 -0
  476. package/tests/fixtures/schemas.ts +64 -0
  477. package/tests/fixtures/seed-connections/invalid-config.yaml +7 -0
  478. package/tests/fixtures/seed-connections/minimal-config.yaml +8 -0
  479. package/tests/fixtures/seed-connections/mixed-credentials.yaml +23 -0
  480. package/tests/fixtures/seed-connections/multi-role-config.yaml +30 -0
  481. package/tests/fixtures/seed-connections/valid-config.json +15 -0
  482. package/tests/fixtures/seed-connections/valid-config.yaml +51 -0
  483. package/tests/helpers/mock-fetch.ts +59 -0
  484. package/tests/helpers/mock-monaco.ts +112 -0
  485. package/tests/helpers/mock-navigation.ts +28 -0
  486. package/tests/helpers/mock-next.ts +80 -0
  487. package/tests/helpers/mock-provider.ts +133 -0
  488. package/tests/helpers/mock-sonner.ts +29 -0
  489. package/tests/helpers/render-with-providers.tsx +19 -0
  490. package/tests/hooks/use-ai-chat.test.ts +600 -0
  491. package/tests/hooks/use-auth.test.ts +371 -0
  492. package/tests/hooks/use-connection-form.test.ts +743 -0
  493. package/tests/hooks/use-connection-manager.test.ts +466 -0
  494. package/tests/hooks/use-inline-editing.test.ts +321 -0
  495. package/tests/hooks/use-mobile.test.ts +177 -0
  496. package/tests/hooks/use-monitoring-data.test.ts +819 -0
  497. package/tests/hooks/use-provider-metadata.test.ts +228 -0
  498. package/tests/hooks/use-query-execution.test.ts +1212 -0
  499. package/tests/hooks/use-tab-manager.test.ts +756 -0
  500. package/tests/hooks/use-toast.test.ts +74 -0
  501. package/tests/hooks/use-transaction-control.test.ts +211 -0
  502. package/tests/integration/db/mongodb-provider.test.ts +698 -0
  503. package/tests/integration/db/mssql-provider.test.ts +840 -0
  504. package/tests/integration/db/mysql-provider.test.ts +872 -0
  505. package/tests/integration/db/oracle-provider.test.ts +843 -0
  506. package/tests/integration/db/postgres-provider.test.ts +1382 -0
  507. package/tests/integration/db/redis-provider.test.ts +526 -0
  508. package/tests/integration/db/sqlite-provider.test.ts +480 -0
  509. package/tests/integration/seed/seed-pipeline.test.ts +102 -0
  510. package/tests/isolated/factory-singleton.test.ts +150 -0
  511. package/tests/isolated/use-storage-sync.test.ts +389 -0
  512. package/tests/run-components.sh +196 -0
  513. package/tests/setup-dom.ts +58 -0
  514. package/tests/setup.ts +40 -0
  515. package/tests/unit/api-errors.test.ts +210 -0
  516. package/tests/unit/code-generator-functions.test.ts +271 -0
  517. package/tests/unit/components/column-list.test.tsx +190 -0
  518. package/tests/unit/components/data-import-modal.test.tsx +441 -0
  519. package/tests/unit/components/studio-mobile-header.test.tsx +327 -0
  520. package/tests/unit/data-charts-functions.test.ts +496 -0
  521. package/tests/unit/data-import-functions.test.ts +320 -0
  522. package/tests/unit/data-import-utils.test.ts +125 -0
  523. package/tests/unit/db/base-provider.test.ts +517 -0
  524. package/tests/unit/db/errors.test.ts +403 -0
  525. package/tests/unit/db/factory.test.ts +436 -0
  526. package/tests/unit/db/pool-manager.test.ts +440 -0
  527. package/tests/unit/db/query-limiter.test.ts +387 -0
  528. package/tests/unit/db/sql-base.test.ts +438 -0
  529. package/tests/unit/lib/api/error-codes.test.ts +39 -0
  530. package/tests/unit/lib/audit.test.ts +326 -0
  531. package/tests/unit/lib/auth.test.ts +146 -0
  532. package/tests/unit/lib/connection-string-parser.test.ts +424 -0
  533. package/tests/unit/lib/data-masking.test.ts +583 -0
  534. package/tests/unit/lib/db-icons.test.tsx +41 -0
  535. package/tests/unit/lib/monitoring-thresholds.test.ts +133 -0
  536. package/tests/unit/lib/oidc.test.ts +509 -0
  537. package/tests/unit/lib/query-generators.test.ts +127 -0
  538. package/tests/unit/lib/storage/factory.test.ts +71 -0
  539. package/tests/unit/lib/storage/local-storage.test.ts +114 -0
  540. package/tests/unit/lib/storage/providers/postgres.test.ts +312 -0
  541. package/tests/unit/lib/storage/providers/sqlite.test.ts +232 -0
  542. package/tests/unit/lib/storage/storage-facade-extended.test.ts +331 -0
  543. package/tests/unit/lib/storage/storage-facade.test.ts +184 -0
  544. package/tests/unit/lib/storage.test.ts +317 -0
  545. package/tests/unit/lib/time-series-buffer.test.ts +212 -0
  546. package/tests/unit/lib/utils.test.ts +24 -0
  547. package/tests/unit/llm/base-provider.test.ts +238 -0
  548. package/tests/unit/llm/config.test.ts +262 -0
  549. package/tests/unit/llm/custom-provider.test.ts +281 -0
  550. package/tests/unit/llm/gemini-provider.test.ts +248 -0
  551. package/tests/unit/llm/llm-factory.test.ts +155 -0
  552. package/tests/unit/llm/ollama-provider.test.ts +288 -0
  553. package/tests/unit/llm/openai-provider.test.ts +324 -0
  554. package/tests/unit/llm/retry.test.ts +180 -0
  555. package/tests/unit/llm/streaming.test.ts +355 -0
  556. package/tests/unit/logger.test.ts +198 -0
  557. package/tests/unit/mongodb-completions.test.ts +516 -0
  558. package/tests/unit/pivot-table-functions.test.ts +76 -0
  559. package/tests/unit/query-cancelled-error.test.ts +81 -0
  560. package/tests/unit/schema-diff/diff-engine.test.ts +367 -0
  561. package/tests/unit/schema-diff/migration-generator.test.ts +513 -0
  562. package/tests/unit/seed/config-loader.test.ts +73 -0
  563. package/tests/unit/seed/connection-filter.test.ts +91 -0
  564. package/tests/unit/seed/credential-resolver.test.ts +85 -0
  565. package/tests/unit/seed/index.test.ts +72 -0
  566. package/tests/unit/seed/resolve-connection.test.ts +74 -0
  567. package/tests/unit/seed/types.test.ts +129 -0
  568. package/tests/unit/sql/alias-extractor.test.ts +444 -0
  569. package/tests/unit/sql/statement-splitter.test.ts +348 -0
  570. package/tests/unit/sql-completions.test.ts +463 -0
  571. package/tests/unit/ssh-tunnel.test.ts +465 -0
  572. package/tsconfig.json +42 -0
@@ -0,0 +1,437 @@
1
+ /**
2
+ * Database Provider Types & Interfaces
3
+ * Strategy Pattern implementation for multi-database support
4
+ */
5
+
6
+ // Re-export common types from main types file
7
+ export type {
8
+ DatabaseType,
9
+ DatabaseConnection,
10
+ TableSchema,
11
+ ColumnSchema,
12
+ IndexSchema,
13
+ ForeignKeySchema,
14
+ QueryResult,
15
+ } from '../types';
16
+
17
+ import type {
18
+ DatabaseType,
19
+ DatabaseConnection,
20
+ TableSchema,
21
+ QueryResult,
22
+ } from '../types';
23
+
24
+ // ============================================================================
25
+ // Pool Configuration
26
+ // ============================================================================
27
+
28
+ export interface PoolConfig {
29
+ /** Minimum number of connections in pool (default: 2) */
30
+ min: number;
31
+ /** Maximum number of connections in pool (default: 10) */
32
+ max: number;
33
+ /** Close idle connections after this time in ms (default: 30000) */
34
+ idleTimeout: number;
35
+ /** Wait for connection timeout in ms (default: 60000) */
36
+ acquireTimeout: number;
37
+ }
38
+
39
+ export const DEFAULT_POOL_CONFIG: PoolConfig = {
40
+ min: 2,
41
+ max: 10,
42
+ idleTimeout: 30000,
43
+ acquireTimeout: 60000,
44
+ };
45
+
46
+ /** Query timeout in milliseconds (default: 60 seconds) */
47
+ export const DEFAULT_QUERY_TIMEOUT = 60000;
48
+
49
+ // ============================================================================
50
+ // Health Information
51
+ // ============================================================================
52
+
53
+ export interface SlowQuery {
54
+ query: string;
55
+ calls: number;
56
+ avgTime: string;
57
+ }
58
+
59
+ export interface ActiveSession {
60
+ pid: number | string;
61
+ user: string;
62
+ database: string;
63
+ state: string;
64
+ query: string;
65
+ duration: string;
66
+ }
67
+
68
+ export interface HealthInfo {
69
+ activeConnections: number;
70
+ databaseSize: string;
71
+ cacheHitRatio: string;
72
+ slowQueries: SlowQuery[];
73
+ activeSessions: ActiveSession[];
74
+ }
75
+
76
+ // ============================================================================
77
+ // Maintenance Operations
78
+ // ============================================================================
79
+
80
+ export type MaintenanceType = 'vacuum' | 'analyze' | 'reindex' | 'kill' | 'optimize' | 'check';
81
+
82
+ export interface MaintenanceResult {
83
+ success: boolean;
84
+ executionTime: number;
85
+ message: string;
86
+ }
87
+
88
+ // ============================================================================
89
+ // Provider Capabilities & Labels
90
+ // ============================================================================
91
+
92
+ export interface ProviderCapabilities {
93
+ queryLanguage: 'sql' | 'json';
94
+ supportsExplain: boolean;
95
+ supportsExternalQueryLimiting: boolean;
96
+ supportsCreateTable: boolean;
97
+ supportsMaintenance: boolean;
98
+ maintenanceOperations: MaintenanceType[];
99
+ supportsConnectionString: boolean;
100
+ defaultPort: number | null;
101
+ schemaRefreshPattern: string;
102
+ }
103
+
104
+ export interface ProviderLabels {
105
+ entityName: string;
106
+ entityNamePlural: string;
107
+ rowName: string;
108
+ rowNamePlural: string;
109
+ selectAction: string;
110
+ generateAction: string;
111
+ analyzeAction: string;
112
+ vacuumAction: string;
113
+ searchPlaceholder: string;
114
+ analyzeGlobalLabel: string;
115
+ analyzeGlobalTitle: string;
116
+ analyzeGlobalDesc: string;
117
+ vacuumGlobalLabel: string;
118
+ vacuumGlobalTitle: string;
119
+ vacuumGlobalDesc: string;
120
+ }
121
+
122
+ export interface PreparedQuery {
123
+ query: string;
124
+ wasLimited: boolean;
125
+ limit: number;
126
+ offset: number;
127
+ }
128
+
129
+ export interface QueryPrepareOptions {
130
+ limit?: number;
131
+ offset?: number;
132
+ unlimited?: boolean;
133
+ }
134
+
135
+ // ============================================================================
136
+ // Provider Interface (Strategy Pattern)
137
+ // ============================================================================
138
+
139
+ export interface DatabaseProvider {
140
+ /** Database type identifier */
141
+ readonly type: DatabaseType;
142
+
143
+ /** Connection configuration */
144
+ readonly config: DatabaseConnection;
145
+
146
+ /**
147
+ * Initialize connection pool or single connection
148
+ */
149
+ connect(): Promise<void>;
150
+
151
+ /**
152
+ * Close all connections and cleanup resources
153
+ */
154
+ disconnect(): Promise<void>;
155
+
156
+ /**
157
+ * Check if provider is currently connected
158
+ */
159
+ isConnected(): boolean;
160
+
161
+ /**
162
+ * Execute a SQL query
163
+ * @param sql - SQL query string
164
+ * @param params - Optional query parameters for prepared statements
165
+ * @returns Query result with rows, fields, and execution time
166
+ */
167
+ query(sql: string, params?: unknown[]): Promise<QueryResult>;
168
+
169
+ /**
170
+ * Get full database schema
171
+ * @returns Array of table schemas with columns, indexes, and foreign keys
172
+ */
173
+ getSchema(): Promise<TableSchema[]>;
174
+
175
+ /**
176
+ * Get list of table names
177
+ */
178
+ getTables(): Promise<string[]>;
179
+
180
+ /**
181
+ * Get health and performance metrics
182
+ */
183
+ getHealth(): Promise<HealthInfo>;
184
+
185
+ /**
186
+ * Get comprehensive monitoring data
187
+ * @param options - What to include in the monitoring data
188
+ */
189
+ getMonitoringData(options?: MonitoringOptions): Promise<MonitoringData>;
190
+
191
+ /**
192
+ * Get database overview metrics
193
+ */
194
+ getOverview(): Promise<DatabaseOverview>;
195
+
196
+ /**
197
+ * Get performance metrics
198
+ */
199
+ getPerformanceMetrics(): Promise<PerformanceMetrics>;
200
+
201
+ /**
202
+ * Get slow query statistics
203
+ * @param options - Query options (limit)
204
+ */
205
+ getSlowQueries(options?: { limit?: number }): Promise<SlowQueryStats[]>;
206
+
207
+ /**
208
+ * Get active sessions with details
209
+ * @param options - Query options (limit)
210
+ */
211
+ getActiveSessions(options?: { limit?: number }): Promise<ActiveSessionDetails[]>;
212
+
213
+ /**
214
+ * Get table statistics
215
+ * @param options - Query options (schema filter)
216
+ */
217
+ getTableStats(options?: { schema?: string }): Promise<TableStats[]>;
218
+
219
+ /**
220
+ * Get index statistics
221
+ * @param options - Query options (schema filter)
222
+ */
223
+ getIndexStats(options?: { schema?: string }): Promise<IndexStats[]>;
224
+
225
+ /**
226
+ * Get storage/tablespace statistics
227
+ */
228
+ getStorageStats(): Promise<StorageStats[]>;
229
+
230
+ /**
231
+ * Run maintenance operations
232
+ * @param type - Type of maintenance operation
233
+ * @param target - Optional target (table name or process ID)
234
+ */
235
+ runMaintenance(type: MaintenanceType, target?: string): Promise<MaintenanceResult>;
236
+
237
+ /**
238
+ * Validate provider configuration
239
+ * @throws DatabaseConfigError if configuration is invalid
240
+ */
241
+ validate(): void;
242
+
243
+ /**
244
+ * Get provider capabilities (query language, supported features, etc.)
245
+ */
246
+ getCapabilities(): ProviderCapabilities;
247
+
248
+ /**
249
+ * Get UI labels for this provider (entity names, action labels, etc.)
250
+ */
251
+ getLabels(): ProviderLabels;
252
+
253
+ /**
254
+ * Prepare a query for execution (apply limits, analyze query type, etc.)
255
+ */
256
+ prepareQuery(query: string, options?: QueryPrepareOptions): PreparedQuery;
257
+ }
258
+
259
+ // ============================================================================
260
+ // Provider Configuration Options
261
+ // ============================================================================
262
+
263
+ export interface ProviderOptions {
264
+ /** Connection pool configuration */
265
+ pool?: Partial<PoolConfig>;
266
+ /** Query timeout in milliseconds */
267
+ queryTimeout?: number;
268
+ /** Enable SSL/TLS connection */
269
+ ssl?: boolean | { rejectUnauthorized: boolean };
270
+ /** Connection timezone */
271
+ timezone?: string;
272
+ }
273
+
274
+ // ============================================================================
275
+ // Internal Types
276
+ // ============================================================================
277
+
278
+ export interface ConnectionState {
279
+ connected: boolean;
280
+ lastConnected?: Date;
281
+ lastError?: Error;
282
+ activeQueries: number;
283
+ }
284
+
285
+ // ============================================================================
286
+ // Monitoring Types (Extended)
287
+ // ============================================================================
288
+
289
+ /**
290
+ * Database overview metrics
291
+ */
292
+ export interface DatabaseOverview {
293
+ version: string;
294
+ uptime: string;
295
+ startTime?: Date;
296
+ activeConnections: number;
297
+ maxConnections: number;
298
+ databaseSize: string;
299
+ databaseSizeBytes: number;
300
+ tableCount: number;
301
+ indexCount: number;
302
+ }
303
+
304
+ /**
305
+ * Performance metrics for the database
306
+ */
307
+ export interface PerformanceMetrics {
308
+ /** Cache hit ratio as percentage (0-100) */
309
+ cacheHitRatio: number;
310
+ /** Transactions per second */
311
+ transactionsPerSecond?: number;
312
+ /** Queries per second */
313
+ queriesPerSecond?: number;
314
+ /** Buffer pool usage as percentage (0-100) */
315
+ bufferPoolUsage?: number;
316
+ /** Number of deadlocks */
317
+ deadlocks?: number;
318
+ /** Checkpoint write time */
319
+ checkpointWriteTime?: string;
320
+ }
321
+
322
+ /**
323
+ * Slow query with detailed statistics
324
+ */
325
+ export interface SlowQueryStats {
326
+ queryId?: string;
327
+ query: string;
328
+ calls: number;
329
+ totalTime: number;
330
+ avgTime: number;
331
+ minTime?: number;
332
+ maxTime?: number;
333
+ rows: number;
334
+ sharedBlksHit?: number;
335
+ sharedBlksRead?: number;
336
+ }
337
+
338
+ /**
339
+ * Active session with detailed information
340
+ */
341
+ export interface ActiveSessionDetails {
342
+ pid: number | string;
343
+ user: string;
344
+ database: string;
345
+ applicationName?: string;
346
+ clientAddr?: string;
347
+ state: string;
348
+ query: string;
349
+ queryStart?: Date;
350
+ duration: string;
351
+ durationMs: number;
352
+ waitEventType?: string;
353
+ waitEvent?: string;
354
+ blocked?: boolean;
355
+ }
356
+
357
+ /**
358
+ * Table statistics
359
+ */
360
+ export interface TableStats {
361
+ schemaName: string;
362
+ tableName: string;
363
+ rowCount: number;
364
+ liveRowCount?: number;
365
+ deadRowCount?: number;
366
+ tableSize: string;
367
+ tableSizeBytes: number;
368
+ indexSize?: string;
369
+ indexSizeBytes?: number;
370
+ totalSize: string;
371
+ totalSizeBytes: number;
372
+ lastVacuum?: Date;
373
+ lastAnalyze?: Date;
374
+ bloatRatio?: number;
375
+ }
376
+
377
+ /**
378
+ * Index statistics
379
+ */
380
+ export interface IndexStats {
381
+ schemaName: string;
382
+ tableName: string;
383
+ indexName: string;
384
+ indexType?: string;
385
+ columns: string[];
386
+ isUnique: boolean;
387
+ isPrimary: boolean;
388
+ indexSize: string;
389
+ indexSizeBytes: number;
390
+ scans: number;
391
+ usageRatio?: number;
392
+ }
393
+
394
+ /**
395
+ * Storage statistics
396
+ */
397
+ export interface StorageStats {
398
+ name: string;
399
+ location?: string;
400
+ size: string;
401
+ sizeBytes: number;
402
+ usagePercent?: number;
403
+ walSize?: string;
404
+ walSizeBytes?: number;
405
+ }
406
+
407
+ /**
408
+ * Comprehensive monitoring data combining all metrics
409
+ */
410
+ export interface MonitoringData {
411
+ timestamp: Date;
412
+ overview: DatabaseOverview;
413
+ performance: PerformanceMetrics;
414
+ slowQueries: SlowQueryStats[];
415
+ activeSessions: ActiveSessionDetails[];
416
+ tables?: TableStats[];
417
+ indexes?: IndexStats[];
418
+ storage?: StorageStats[];
419
+ }
420
+
421
+ /**
422
+ * Options for monitoring queries
423
+ */
424
+ export interface MonitoringOptions {
425
+ /** Include table statistics */
426
+ includeTables?: boolean;
427
+ /** Include index statistics */
428
+ includeIndexes?: boolean;
429
+ /** Include storage/tablespace info */
430
+ includeStorage?: boolean;
431
+ /** Limit for slow queries (default: 10) */
432
+ slowQueryLimit?: number;
433
+ /** Limit for active sessions (default: 50) */
434
+ sessionLimit?: number;
435
+ /** Schema filter (default: 'public' for PostgreSQL) */
436
+ schemaFilter?: string;
437
+ }
@@ -0,0 +1,287 @@
1
+ /**
2
+ * Connection Pool Manager
3
+ * Abstract pool management utilities for database providers
4
+ */
5
+
6
+ import { type PoolConfig, DEFAULT_POOL_CONFIG, type DatabaseType } from '../types';
7
+ import { TimeoutError } from '../errors';
8
+
9
+ // ============================================================================
10
+ // Pool Statistics
11
+ // ============================================================================
12
+
13
+ export interface PoolStats {
14
+ /** Total connections in pool */
15
+ total: number;
16
+ /** Currently idle connections */
17
+ idle: number;
18
+ /** Currently active/busy connections */
19
+ active: number;
20
+ /** Connections waiting in queue */
21
+ waiting: number;
22
+ }
23
+
24
+ // ============================================================================
25
+ // Pool Manager Interface
26
+ // ============================================================================
27
+
28
+ export interface PoolManager<T> {
29
+ /** Acquire a connection from the pool */
30
+ acquire(): Promise<T>;
31
+ /** Release a connection back to the pool */
32
+ release(connection: T): void;
33
+ /** Get pool statistics */
34
+ getStats(): PoolStats;
35
+ /** Drain all connections and close pool */
36
+ drain(): Promise<void>;
37
+ /** Check if pool is healthy */
38
+ isHealthy(): boolean;
39
+ }
40
+
41
+ // ============================================================================
42
+ // Pool Configuration Utilities
43
+ // ============================================================================
44
+
45
+ /**
46
+ * Merge user config with defaults
47
+ */
48
+ export function mergePoolConfig(config?: Partial<PoolConfig>): PoolConfig {
49
+ return {
50
+ ...DEFAULT_POOL_CONFIG,
51
+ ...config,
52
+ };
53
+ }
54
+
55
+ /**
56
+ * Validate pool configuration
57
+ */
58
+ export function validatePoolConfig(config: PoolConfig): void {
59
+ if (config.min < 0) {
60
+ throw new Error('Pool min must be non-negative');
61
+ }
62
+ if (config.max < 1) {
63
+ throw new Error('Pool max must be at least 1');
64
+ }
65
+ if (config.min > config.max) {
66
+ throw new Error('Pool min cannot be greater than max');
67
+ }
68
+ if (config.idleTimeout < 0) {
69
+ throw new Error('Pool idleTimeout must be non-negative');
70
+ }
71
+ if (config.acquireTimeout < 0) {
72
+ throw new Error('Pool acquireTimeout must be non-negative');
73
+ }
74
+ }
75
+
76
+ // ============================================================================
77
+ // Timeout Utilities
78
+ // ============================================================================
79
+
80
+ /**
81
+ * Execute a promise with timeout
82
+ */
83
+ export async function withTimeout<T>(
84
+ promise: Promise<T>,
85
+ timeout: number,
86
+ provider: DatabaseType,
87
+ operation: string
88
+ ): Promise<T> {
89
+ let timeoutId: NodeJS.Timeout;
90
+
91
+ const timeoutPromise = new Promise<never>((_, reject) => {
92
+ timeoutId = setTimeout(() => {
93
+ reject(new TimeoutError(
94
+ `${operation} timed out after ${timeout}ms`,
95
+ provider,
96
+ timeout
97
+ ));
98
+ }, timeout);
99
+ });
100
+
101
+ try {
102
+ const result = await Promise.race([promise, timeoutPromise]);
103
+ clearTimeout(timeoutId!);
104
+ return result;
105
+ } catch (error) {
106
+ clearTimeout(timeoutId!);
107
+ throw error;
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Create a cancellable query wrapper
113
+ */
114
+ export function createCancellableQuery<T>(
115
+ queryFn: (signal?: AbortSignal) => Promise<T>,
116
+ timeout: number,
117
+ provider: DatabaseType
118
+ ): { promise: Promise<T>; cancel: () => void } {
119
+ const controller = new AbortController();
120
+ let timeoutId: NodeJS.Timeout;
121
+
122
+ const promise = new Promise<T>((resolve, reject) => {
123
+ timeoutId = setTimeout(() => {
124
+ controller.abort();
125
+ reject(new TimeoutError(
126
+ `Query timed out after ${timeout}ms`,
127
+ provider,
128
+ timeout
129
+ ));
130
+ }, timeout);
131
+
132
+ queryFn(controller.signal)
133
+ .then(resolve)
134
+ .catch(reject)
135
+ .finally(() => clearTimeout(timeoutId));
136
+ });
137
+
138
+ return {
139
+ promise,
140
+ cancel: () => {
141
+ clearTimeout(timeoutId);
142
+ controller.abort();
143
+ },
144
+ };
145
+ }
146
+
147
+ // ============================================================================
148
+ // Connection Health Check
149
+ // ============================================================================
150
+
151
+ /**
152
+ * Simple ping-like health check
153
+ */
154
+ export async function checkConnectionHealth<T>(
155
+ acquireFn: () => Promise<T>,
156
+ releaseFn: (conn: T) => void,
157
+ pingFn: (conn: T) => Promise<void>,
158
+ timeout: number,
159
+ provider: DatabaseType
160
+ ): Promise<boolean> {
161
+ try {
162
+ const conn = await withTimeout(
163
+ acquireFn(),
164
+ timeout,
165
+ provider,
166
+ 'Connection acquire'
167
+ );
168
+
169
+ try {
170
+ await withTimeout(
171
+ pingFn(conn),
172
+ timeout,
173
+ provider,
174
+ 'Connection ping'
175
+ );
176
+ return true;
177
+ } finally {
178
+ releaseFn(conn);
179
+ }
180
+ } catch {
181
+ return false;
182
+ }
183
+ }
184
+
185
+ // ============================================================================
186
+ // Retry Logic
187
+ // ============================================================================
188
+
189
+ export interface RetryOptions {
190
+ maxAttempts?: number;
191
+ initialDelay?: number;
192
+ maxDelay?: number;
193
+ backoffMultiplier?: number;
194
+ }
195
+
196
+ const DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {
197
+ maxAttempts: 3,
198
+ initialDelay: 1000,
199
+ maxDelay: 10000,
200
+ backoffMultiplier: 2,
201
+ };
202
+
203
+ /**
204
+ * Execute with retry logic and exponential backoff
205
+ */
206
+ export async function withRetry<T>(
207
+ fn: () => Promise<T>,
208
+ options: RetryOptions = {},
209
+ isRetryable: (error: unknown) => boolean = () => true,
210
+ provider?: DatabaseType
211
+ ): Promise<T> {
212
+ const opts = { ...DEFAULT_RETRY_OPTIONS, ...options };
213
+ let lastError: Error | undefined;
214
+ let delay = opts.initialDelay;
215
+
216
+ for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {
217
+ try {
218
+ return await fn();
219
+ } catch (error) {
220
+ lastError = error instanceof Error ? error : new Error(String(error));
221
+
222
+ if (!isRetryable(error) || attempt === opts.maxAttempts) {
223
+ throw error;
224
+ }
225
+
226
+ console.error(
227
+ `[DB${provider ? `:${provider}` : ''}] Operation failed (attempt ${attempt}/${opts.maxAttempts}): ${lastError.message}. Retrying in ${delay}ms...`
228
+ );
229
+
230
+ await sleep(delay);
231
+ delay = Math.min(delay * opts.backoffMultiplier, opts.maxDelay);
232
+ }
233
+ }
234
+
235
+ throw lastError;
236
+ }
237
+
238
+ function sleep(ms: number): Promise<void> {
239
+ return new Promise((resolve) => setTimeout(resolve, ms));
240
+ }
241
+
242
+ // ============================================================================
243
+ // SQL Utilities
244
+ // ============================================================================
245
+
246
+ /**
247
+ * Escape SQL identifier (table name, column name)
248
+ * Prevents SQL injection in dynamic queries
249
+ */
250
+ export function escapeIdentifier(identifier: string, provider: DatabaseType): string {
251
+ // Remove any existing quotes and escape internal quotes
252
+ const cleaned = identifier.replace(/["'`]/g, '');
253
+
254
+ switch (provider) {
255
+ case 'postgres':
256
+ return `"${cleaned}"`;
257
+ case 'mysql':
258
+ return `\`${cleaned}\``;
259
+ case 'sqlite':
260
+ return `"${cleaned}"`;
261
+ default:
262
+ return `"${cleaned}"`;
263
+ }
264
+ }
265
+
266
+ /**
267
+ * Format bytes to human readable size
268
+ */
269
+ export function formatBytes(bytes: number): string {
270
+ if (bytes === 0) return '0 B';
271
+
272
+ const k = 1024;
273
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
274
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
275
+
276
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
277
+ }
278
+
279
+ /**
280
+ * Format duration in milliseconds to human readable
281
+ */
282
+ export function formatDuration(ms: number): string {
283
+ if (ms < 1000) return `${ms}ms`;
284
+ if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`;
285
+ if (ms < 3600000) return `${(ms / 60000).toFixed(2)}m`;
286
+ return `${(ms / 3600000).toFixed(2)}h`;
287
+ }