@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,132 @@
1
+ import { NextRequest } from 'next/server';
2
+ import { createLLMProvider } from '@/lib/llm';
3
+ import { createErrorResponse } from '@/lib/api/errors';
4
+
5
+ // ============================================================================
6
+ // System Prompt Builder
7
+ // ============================================================================
8
+
9
+ function buildSystemInstruction(databaseType: string, schemaContext: string, queryLanguage?: string): string {
10
+ if (queryLanguage === 'json') {
11
+ return `You are an Expert Generative AI Engineer and Senior MongoDB Database Administrator specializing in MQL queries, aggregation pipelines, and document database design.
12
+
13
+ ROLE:
14
+ - Senior MongoDB Expert & Database Architect.
15
+ - Expert Gen-AI Engineer for LibreDB Studio.
16
+
17
+ CAPABILITIES:
18
+ - Generate highly optimized MongoDB JSON queries.
19
+ - Analyze collection schemas to provide insights and optimizations.
20
+ - Explain complex MongoDB operations clearly if requested.
21
+ - Ensure security best practices.
22
+
23
+ DATABASE CONTEXT:
24
+ Type: MongoDB
25
+
26
+ COLLECTION INFORMATION (TOP 100 COLLECTIONS BY DOCUMENT COUNT):
27
+ ${schemaContext || 'No specific schema provided. Ask the user for collection details if needed for precise queries.'}
28
+
29
+ QUERY FORMAT:
30
+ LibreDB Studio uses JSON-based queries with this structure:
31
+ {
32
+ "collection": "collection_name",
33
+ "operation": "find|findOne|aggregate|count|distinct|insertOne|insertMany|updateOne|updateMany|deleteOne|deleteMany",
34
+ "filter": {},
35
+ "pipeline": [],
36
+ "update": {},
37
+ "documents": [],
38
+ "options": { "limit": 50, "sort": {}, "projection": {}, "skip": 0 }
39
+ }
40
+
41
+ SUPPORTED OPERATIONS:
42
+ - find: Query documents with filter, projection, sort, limit, skip
43
+ - findOne: Return single document matching filter
44
+ - aggregate: Run aggregation pipeline (use "pipeline" field)
45
+ - count: Count documents matching filter
46
+ - distinct: Get distinct values (use projection to specify field)
47
+ - insertOne/insertMany: Insert documents (use "documents" field)
48
+ - updateOne/updateMany: Update documents (use "filter" + "update" fields)
49
+ - deleteOne/deleteMany: Delete documents matching filter
50
+
51
+ GUIDELINES:
52
+ 1. Return ONLY valid JSON query code unless the user asks for an explanation or advice.
53
+ 2. Wrap JSON queries in markdown code blocks: \`\`\`json ... \`\`\`.
54
+ 3. Use proper MongoDB query operators ($eq, $gt, $lt, $in, $regex, $exists, etc.).
55
+ 4. For aggregation pipelines, use stages: $match, $group, $sort, $project, $lookup, $unwind, $limit, $skip.
56
+ 5. If the schema context is provided, use exact collection and field names.
57
+ 6. Always include reasonable limits for find queries to prevent large result sets.
58
+ `;
59
+ }
60
+
61
+ return `You are an Expert Generative AI Engineer and Senior Database Administrator (DBA) specializing in SQL optimization, schema design, and data engineering.
62
+
63
+ ROLE:
64
+ - Senior SQL Expert & Database Architect.
65
+ - Expert Gen-AI Engineer for LibreDB Studio.
66
+
67
+ CAPABILITIES:
68
+ - Generate highly optimized, production-ready SQL queries.
69
+ - Analyze database schemas to provide insights and optimizations.
70
+ - Explain complex SQL operations clearly if requested.
71
+ - Ensure security best practices (e.g., avoiding dangerous operations unless explicitly confirmed).
72
+
73
+ DATABASE CONTEXT:
74
+ Type: ${databaseType || 'Postgres'}
75
+
76
+ SCHEMA INFORMATION (TOP 100 TABLES BY ROW COUNT):
77
+ ${schemaContext || 'No specific schema provided. Ask the user for table details if needed for precise queries.'}
78
+
79
+ GUIDELINES:
80
+ 1. Return ONLY pure SQL code unless the user asks for an explanation or advice.
81
+ 2. If generating SQL, wrap it in markdown code blocks: \`\`\`sql ... \`\`\`.
82
+ 3. Use standard naming conventions and ensure compatibility with ${databaseType || 'Postgres'}.
83
+ 4. Always prioritize query performance and readability.
84
+ 5. If the schema context is provided, use exact table and column names.
85
+ 6. If you notice potential schema improvements (indexes, normalization), mention them briefly if relevant.
86
+ `;
87
+ }
88
+
89
+ // ============================================================================
90
+ // API Route Handler
91
+ // ============================================================================
92
+
93
+ export async function POST(req: NextRequest) {
94
+ try {
95
+ const { prompt, schemaContext, databaseType, queryLanguage, conversationHistory } = await req.json();
96
+
97
+ // Create provider from environment configuration (async - dynamically loads provider)
98
+ const provider = await createLLMProvider();
99
+
100
+ // Build messages
101
+ const systemInstruction = buildSystemInstruction(databaseType, schemaContext, queryLanguage);
102
+
103
+ // Build message array with optional conversation history for multi-turn
104
+ const messages: { role: 'system' | 'user' | 'assistant'; content: string }[] = [
105
+ { role: 'system', content: systemInstruction },
106
+ ];
107
+
108
+ // Add conversation history if provided (multi-turn support)
109
+ if (conversationHistory?.length) {
110
+ for (const msg of conversationHistory) {
111
+ if (msg.role === 'user' || msg.role === 'assistant') {
112
+ messages.push({ role: msg.role, content: msg.content });
113
+ }
114
+ }
115
+ }
116
+
117
+ // Add the current prompt
118
+ messages.push({ role: 'user', content: prompt });
119
+
120
+ // Stream completion
121
+ const stream = await provider.stream({ messages });
122
+
123
+ return new Response(stream, {
124
+ headers: {
125
+ 'Content-Type': 'text/plain; charset=utf-8',
126
+ 'Transfer-Encoding': 'chunked',
127
+ },
128
+ });
129
+ } catch (error) {
130
+ return createErrorResponse(error, { route: 'api/ai/chat' });
131
+ }
132
+ }
@@ -0,0 +1,52 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { createLLMProvider } from '@/lib/llm';
3
+ import { createErrorResponse } from '@/lib/api/errors';
4
+
5
+ export async function POST(req: NextRequest) {
6
+ try {
7
+ const { schemaContext, databaseType, mode } = await req.json();
8
+
9
+ if (!schemaContext) {
10
+ return NextResponse.json({ error: 'Schema context required' }, { status: 400 });
11
+ }
12
+
13
+ const provider = await createLLMProvider();
14
+
15
+ const systemPrompt = mode === 'table'
16
+ ? `You are a database documentation expert. Given a table schema, generate clear, concise documentation.
17
+
18
+ For each table, provide:
19
+ 1. **Purpose**: What this table stores and its role in the system
20
+ 2. **Key Columns**: Brief description of important columns
21
+ 3. **Relationships**: Detected foreign keys and relationships
22
+ 4. **Usage Notes**: Common query patterns or important constraints
23
+
24
+ Format as markdown. Be concise but informative. Database type: ${databaseType || 'SQL'}.`
25
+ : `You are a database documentation expert. Generate comprehensive database documentation.
26
+
27
+ Given the full schema, provide:
28
+ 1. **Database Overview**: High-level summary of the database's purpose
29
+ 2. **Entity Relationship Summary**: How tables relate to each other
30
+ 3. **Table Descriptions**: Brief purpose of each table (one line each)
31
+ 4. **Data Flow**: How data typically flows through the system
32
+ 5. **Key Observations**: Naming conventions, patterns, potential issues
33
+
34
+ Format as clean markdown. Be concise. Database type: ${databaseType || 'SQL'}.`;
35
+
36
+ const stream = await provider.stream({
37
+ messages: [
38
+ { role: 'system', content: systemPrompt },
39
+ { role: 'user', content: `Generate documentation for:\n\n${schemaContext}` },
40
+ ],
41
+ });
42
+
43
+ return new Response(stream as ReadableStream, {
44
+ headers: {
45
+ 'Content-Type': 'text/plain; charset=utf-8',
46
+ 'Transfer-Encoding': 'chunked',
47
+ },
48
+ });
49
+ } catch (error) {
50
+ return createErrorResponse(error, { route: 'api/ai/describe-schema' });
51
+ }
52
+ }
@@ -0,0 +1,86 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { createLLMProvider } from '@/lib/llm';
3
+ import { createErrorResponse } from '@/lib/api/errors';
4
+
5
+ function buildExplainSystemPrompt(databaseType: string, schemaContext: string): string {
6
+ return `You are an Expert Database Performance Analyst specializing in query optimization for ${databaseType || 'PostgreSQL'}.
7
+
8
+ ROLE: Analyze EXPLAIN plans and provide actionable, plain-language explanations.
9
+
10
+ SCHEMA CONTEXT:
11
+ ${schemaContext || 'No schema context available.'}
12
+
13
+ OUTPUT FORMAT (always follow this structure):
14
+
15
+ ## Plain Language Explanation
16
+ Explain what the query does step-by-step in simple terms anyone can understand. Be specific about which tables, joins, and filters are involved.
17
+
18
+ ## Performance Issues
19
+ List any problems found (sequential scans on large tables, expensive sorts, nested loop issues, row estimate mismatches). For each issue:
20
+ - What the problem is
21
+ - Why it matters
22
+ - How much impact it has
23
+
24
+ ## Recommendations
25
+ Numbered list of concrete, actionable suggestions. Each should include:
26
+ - The specific action (e.g., "Create an index on orders.customer_id")
27
+ - Expected improvement
28
+ - The exact SQL command if applicable
29
+
30
+ ## Optimized Query
31
+ If the query can be rewritten for better performance, provide the optimized version in a SQL code block. If the query is already optimal, say so.
32
+
33
+ GUIDELINES:
34
+ - Be concise but thorough
35
+ - Use plain language, avoid jargon where possible
36
+ - Quantify impact when you can (e.g., "reduces from table scan of ~100K rows to index lookup")
37
+ - If there are no issues, say the query looks good and explain why
38
+ - Format SQL in code blocks with \`\`\`sql
39
+ `;
40
+ }
41
+
42
+ export async function POST(req: NextRequest) {
43
+ try {
44
+ const { query, explainPlan, schemaContext, databaseType } = await req.json();
45
+
46
+ if (!query) {
47
+ return NextResponse.json(
48
+ { error: 'Query is required' },
49
+ { status: 400 }
50
+ );
51
+ }
52
+
53
+ const provider = await createLLMProvider();
54
+ const systemPrompt = buildExplainSystemPrompt(databaseType, schemaContext);
55
+
56
+ const userMessage = `Analyze this SQL query and its EXPLAIN plan:
57
+
58
+ **Original Query:**
59
+ \`\`\`sql
60
+ ${query}
61
+ \`\`\`
62
+
63
+ **EXPLAIN Plan:**
64
+ \`\`\`json
65
+ ${JSON.stringify(explainPlan, null, 2)}
66
+ \`\`\`
67
+
68
+ Provide a plain-language explanation, identify performance issues, give specific recommendations, and suggest an optimized query if possible.`;
69
+
70
+ const stream = await provider.stream({
71
+ messages: [
72
+ { role: 'system', content: systemPrompt },
73
+ { role: 'user', content: userMessage },
74
+ ],
75
+ });
76
+
77
+ return new Response(stream, {
78
+ headers: {
79
+ 'Content-Type': 'text/plain; charset=utf-8',
80
+ 'Transfer-Encoding': 'chunked',
81
+ },
82
+ });
83
+ } catch (error) {
84
+ return createErrorResponse(error, { route: 'api/ai/explain' });
85
+ }
86
+ }
@@ -0,0 +1,97 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { createLLMProvider } from '@/lib/llm';
3
+ import { createErrorResponse } from '@/lib/api/errors';
4
+
5
+ function buildImpactSystemPrompt(databaseType: string, schemaContext: string): string {
6
+ return `You are a Schema Change Impact Analyst for ${databaseType || 'PostgreSQL'}. You analyze DDL statements BEFORE they are executed and predict their impact.
7
+
8
+ DATABASE TYPE: ${databaseType || 'PostgreSQL'}
9
+
10
+ SCHEMA CONTEXT:
11
+ ${schemaContext || 'No schema available.'}
12
+
13
+ ANALYSIS SCOPE:
14
+ 1. **Lock Impact**: Will this statement acquire table locks? For how long? What queries will be blocked?
15
+ 2. **Data Impact**: Will data be lost? How many rows affected? Are there cascade effects?
16
+ 3. **Dependent Objects**: Views, indexes, triggers, functions that depend on the modified object
17
+ 4. **Performance Impact**: Will queries become slower after this change? Will indexes need rebuilding?
18
+ 5. **Rollback Plan**: How to reverse this change if something goes wrong
19
+
20
+ OUTPUT FORMAT (markdown):
21
+
22
+ ## Impact Summary
23
+ One-line: what this DDL does and its risk level (Low/Medium/High/Critical).
24
+
25
+ ## Lock Analysis
26
+ - Lock type acquired (ACCESS EXCLUSIVE, ROW EXCLUSIVE, etc.)
27
+ - Estimated duration for the schema context
28
+ - Affected concurrent queries
29
+
30
+ ## Data Impact
31
+ - Rows affected (estimate)
32
+ - Data loss risk (none/potential/certain)
33
+ - Cascade effects (FK constraints)
34
+
35
+ ## Dependent Objects
36
+ List views, indexes, triggers, stored procedures that reference the modified table/column.
37
+
38
+ ## Validation Queries
39
+ SQL queries the user can run BEFORE applying the change to verify safety:
40
+ \`\`\`sql
41
+ -- Check for NULL values before adding NOT NULL constraint
42
+ SELECT COUNT(*) FROM table WHERE column IS NULL;
43
+ \`\`\`
44
+
45
+ ## Rollback Plan
46
+ \`\`\`sql
47
+ -- Exact SQL to reverse this change
48
+ \`\`\`
49
+
50
+ ## Recommendation
51
+ Whether to proceed, modify, or avoid this change. Suggest safer alternatives if applicable.
52
+
53
+ GUIDELINES:
54
+ - Be specific about ${databaseType} lock behavior
55
+ - For ALTER TABLE on large tables, warn about lock time
56
+ - For DROP operations, list ALL dependent objects
57
+ - For column type changes, check for data truncation risks
58
+ - Always provide a rollback plan
59
+ `;
60
+ }
61
+
62
+ export async function POST(req: NextRequest) {
63
+ try {
64
+ const { query, schemaContext, databaseType } = await req.json();
65
+
66
+ if (!query) {
67
+ return NextResponse.json({ error: 'Query is required' }, { status: 400 });
68
+ }
69
+
70
+ const provider = await createLLMProvider();
71
+ const systemPrompt = buildImpactSystemPrompt(databaseType, schemaContext);
72
+
73
+ const userMessage = `Analyze the impact of this schema change before I execute it:
74
+
75
+ \`\`\`sql
76
+ ${query}
77
+ \`\`\`
78
+
79
+ Provide a comprehensive impact analysis.`;
80
+
81
+ const stream = await provider.stream({
82
+ messages: [
83
+ { role: 'system', content: systemPrompt },
84
+ { role: 'user', content: userMessage },
85
+ ],
86
+ });
87
+
88
+ return new Response(stream, {
89
+ headers: {
90
+ 'Content-Type': 'text/plain; charset=utf-8',
91
+ 'Transfer-Encoding': 'chunked',
92
+ },
93
+ });
94
+ } catch (error) {
95
+ return createErrorResponse(error, { route: 'api/ai/impact' });
96
+ }
97
+ }
@@ -0,0 +1,98 @@
1
+ import { NextRequest } from 'next/server';
2
+ import { createLLMProvider } from '@/lib/llm';
3
+ import { createErrorResponse } from '@/lib/api/errors';
4
+
5
+ function buildIndexAdvisorPrompt(databaseType: string): string {
6
+ return `You are a Database Index Optimization Expert for ${databaseType || 'PostgreSQL'}.
7
+
8
+ You will be given:
9
+ 1. Slow queries with execution statistics
10
+ 2. Current index statistics (scans, usage ratio)
11
+ 3. Table statistics (row counts, sizes)
12
+ 4. Schema information
13
+
14
+ Your job is to provide actionable index recommendations.
15
+
16
+ OUTPUT FORMAT (use markdown):
17
+
18
+ ## Index Analysis Summary
19
+ Brief overview of the indexing health.
20
+
21
+ ## Missing Indexes (Recommended to Create)
22
+ For each recommendation:
23
+ ### Index: \`index_name\`
24
+ - **Table:** table_name
25
+ - **Columns:** column(s) to index
26
+ - **Reason:** Why this index is needed (reference the slow query)
27
+ - **Expected Impact:** How much improvement
28
+ - **SQL:**
29
+ \`\`\`sql
30
+ CREATE INDEX index_name ON table_name (columns);
31
+ \`\`\`
32
+
33
+ ## Unused Indexes (Consider Dropping)
34
+ For each unused index:
35
+ - **Index:** index_name on table_name
36
+ - **Size:** index size
37
+ - **Scans:** 0 (never used)
38
+ - **Recommendation:** DROP or keep (with reason)
39
+
40
+ ## Duplicate / Overlapping Indexes
41
+ If any indexes cover the same columns.
42
+
43
+ ## Quick Wins
44
+ Top 3 most impactful changes, numbered.
45
+
46
+ GUIDELINES:
47
+ - Recommend composite indexes when queries filter on multiple columns
48
+ - Consider partial indexes for filtered queries
49
+ - For ${databaseType}, use appropriate index types (btree, hash, gin, gist)
50
+ - Always name indexes descriptively: idx_tablename_columns
51
+ - Note if ANALYZE/VACUUM should be run first
52
+ `;
53
+ }
54
+
55
+ export async function POST(req: NextRequest) {
56
+ try {
57
+ const { slowQueries, indexStats, tableStats, schemaContext, databaseType } = await req.json();
58
+
59
+ const provider = await createLLMProvider();
60
+ const systemPrompt = buildIndexAdvisorPrompt(databaseType);
61
+
62
+ const parts: string[] = [];
63
+
64
+ if (slowQueries?.length) {
65
+ parts.push('## Slow Queries\n' + JSON.stringify(slowQueries.slice(0, 20), null, 2));
66
+ }
67
+
68
+ if (indexStats?.length) {
69
+ parts.push('## Current Indexes\n' + JSON.stringify(indexStats.slice(0, 50), null, 2));
70
+ }
71
+
72
+ if (tableStats?.length) {
73
+ parts.push('## Table Statistics\n' + JSON.stringify(tableStats.slice(0, 30), null, 2));
74
+ }
75
+
76
+ if (schemaContext) {
77
+ parts.push('## Schema\n' + schemaContext.substring(0, 4000));
78
+ }
79
+
80
+ const userMessage = `Analyze the following database statistics and provide index recommendations:\n\n${parts.join('\n\n')}`;
81
+
82
+ const stream = await provider.stream({
83
+ messages: [
84
+ { role: 'system', content: systemPrompt },
85
+ { role: 'user', content: userMessage },
86
+ ],
87
+ });
88
+
89
+ return new Response(stream, {
90
+ headers: {
91
+ 'Content-Type': 'text/plain; charset=utf-8',
92
+ 'Transfer-Encoding': 'chunked',
93
+ },
94
+ });
95
+ } catch (error) {
96
+ return createErrorResponse(error, { route: 'api/ai/index-advisor' });
97
+ }
98
+ }
@@ -0,0 +1,87 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { createLLMProvider } from '@/lib/llm';
3
+ import { createErrorResponse } from '@/lib/api/errors';
4
+
5
+ function buildNL2SQLPrompt(databaseType: string, schemaContext: string, queryLanguage?: string): string {
6
+ if (queryLanguage === 'json') {
7
+ return `You are an NL-to-MongoDB translator. Convert natural language questions into MongoDB JSON queries for LibreDB Studio.
8
+
9
+ DATABASE: MongoDB
10
+
11
+ COLLECTIONS:
12
+ ${schemaContext || 'No schema available.'}
13
+
14
+ QUERY FORMAT:
15
+ {
16
+ "collection": "collection_name",
17
+ "operation": "find|aggregate|count|distinct",
18
+ "filter": {},
19
+ "pipeline": [],
20
+ "options": { "limit": 50, "sort": {} }
21
+ }
22
+
23
+ RULES:
24
+ 1. Return ONLY a JSON code block with the query
25
+ 2. Use exact collection and field names from the schema
26
+ 3. Add reasonable limits (default 50)
27
+ 4. For complex questions, prefer aggregate with pipeline
28
+ 5. After the JSON block, add a brief one-line explanation starting with "-- "
29
+ `;
30
+ }
31
+
32
+ return `You are an NL-to-SQL translator. Convert natural language questions into ${databaseType || 'PostgreSQL'} SQL queries.
33
+
34
+ DATABASE TYPE: ${databaseType || 'PostgreSQL'}
35
+
36
+ SCHEMA:
37
+ ${schemaContext || 'No schema available.'}
38
+
39
+ RULES:
40
+ 1. Return ONLY a SQL code block with the query
41
+ 2. Use exact table and column names from the schema
42
+ 3. Add reasonable LIMIT (default 50) to prevent large result sets
43
+ 4. Use JOINs when the question implies data from multiple tables
44
+ 5. Handle aggregations (COUNT, SUM, AVG) when asked about totals or averages
45
+ 6. After the SQL block, add a brief one-line explanation starting with "-- "
46
+ 7. If the question is ambiguous, make your best guess and explain your interpretation
47
+ 8. Use standard ${databaseType || 'PostgreSQL'} syntax
48
+ `;
49
+ }
50
+
51
+ export async function POST(req: NextRequest) {
52
+ try {
53
+ const { question, schemaContext, databaseType, queryLanguage, conversationHistory } = await req.json();
54
+
55
+ if (!question) {
56
+ return NextResponse.json({ error: 'Question is required' }, { status: 400 });
57
+ }
58
+
59
+ const provider = await createLLMProvider();
60
+ const systemPrompt = buildNL2SQLPrompt(databaseType, schemaContext, queryLanguage);
61
+
62
+ // Build messages with optional conversation history for multi-turn
63
+ const messages: { role: 'system' | 'user' | 'assistant'; content: string }[] = [
64
+ { role: 'system', content: systemPrompt },
65
+ ];
66
+
67
+ // Add conversation history if provided
68
+ if (conversationHistory?.length) {
69
+ for (const msg of conversationHistory) {
70
+ messages.push({ role: msg.role, content: msg.content });
71
+ }
72
+ }
73
+
74
+ messages.push({ role: 'user', content: question });
75
+
76
+ const stream = await provider.stream({ messages });
77
+
78
+ return new Response(stream, {
79
+ headers: {
80
+ 'Content-Type': 'text/plain; charset=utf-8',
81
+ 'Transfer-Encoding': 'chunked',
82
+ },
83
+ });
84
+ } catch (error) {
85
+ return createErrorResponse(error, { route: 'api/ai/nl2sql' });
86
+ }
87
+ }
@@ -0,0 +1,87 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { createLLMProvider } from '@/lib/llm';
3
+ import { createErrorResponse } from '@/lib/api/errors';
4
+
5
+ function buildSafetySystemPrompt(databaseType: string, schemaContext: string): string {
6
+ return `You are a Database Safety Analyst. Your job is to analyze SQL queries BEFORE they are executed and warn the user about potential dangers.
7
+
8
+ DATABASE TYPE: ${databaseType || 'PostgreSQL'}
9
+
10
+ SCHEMA CONTEXT:
11
+ ${schemaContext || 'No schema available.'}
12
+
13
+ ANALYSIS RULES:
14
+ 1. Check for destructive operations: DROP, TRUNCATE, DELETE without WHERE, UPDATE without WHERE
15
+ 2. Estimate affected row counts based on schema info
16
+ 3. Check for cascade effects (FK constraints)
17
+ 4. Detect risky patterns: Cartesian joins, unbounded deletes, mass updates
18
+ 5. Check for schema modifications that could lock tables
19
+
20
+ OUTPUT FORMAT (always use this JSON structure, wrapped in a code block):
21
+ \`\`\`json
22
+ {
23
+ "riskLevel": "safe" | "low" | "medium" | "high" | "critical",
24
+ "summary": "One-line summary of the risk",
25
+ "warnings": [
26
+ {
27
+ "type": "destructive" | "performance" | "schema" | "data_loss" | "lock",
28
+ "severity": "info" | "warning" | "critical",
29
+ "message": "What the issue is",
30
+ "detail": "Why it matters and estimated impact"
31
+ }
32
+ ],
33
+ "affectedRows": "estimated number or range, e.g. '~12,000' or 'all rows'",
34
+ "cascadeEffects": "Description of cascade effects or 'none'",
35
+ "recommendation": "What the user should do instead or how to make it safer"
36
+ }
37
+ \`\`\`
38
+
39
+ GUIDELINES:
40
+ - Be conservative: when in doubt, flag it
41
+ - For SELECT queries, riskLevel is always "safe"
42
+ - For INSERT, riskLevel is typically "low" unless it's INSERT INTO ... SELECT without limits
43
+ - DELETE without WHERE is ALWAYS "critical"
44
+ - DROP TABLE is ALWAYS "critical"
45
+ - UPDATE without WHERE is ALWAYS "high"
46
+ - TRUNCATE is ALWAYS "high"
47
+ - ALTER TABLE on large tables (>100K rows) is "medium" due to lock time
48
+ - Always return valid JSON in the code block
49
+ `;
50
+ }
51
+
52
+ export async function POST(req: NextRequest) {
53
+ try {
54
+ const { query, schemaContext, databaseType } = await req.json();
55
+
56
+ if (!query) {
57
+ return NextResponse.json({ error: 'Query is required' }, { status: 400 });
58
+ }
59
+
60
+ const provider = await createLLMProvider();
61
+ const systemPrompt = buildSafetySystemPrompt(databaseType, schemaContext);
62
+
63
+ const userMessage = `Analyze this query for safety before execution:
64
+
65
+ \`\`\`sql
66
+ ${query}
67
+ \`\`\`
68
+
69
+ Return your analysis as a JSON code block.`;
70
+
71
+ const stream = await provider.stream({
72
+ messages: [
73
+ { role: 'system', content: systemPrompt },
74
+ { role: 'user', content: userMessage },
75
+ ],
76
+ });
77
+
78
+ return new Response(stream, {
79
+ headers: {
80
+ 'Content-Type': 'text/plain; charset=utf-8',
81
+ 'Transfer-Encoding': 'chunked',
82
+ },
83
+ });
84
+ } catch (error) {
85
+ return createErrorResponse(error, { route: 'api/ai/query-safety' });
86
+ }
87
+ }