@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.
- package/.claude/settings.local.json +127 -0
- package/.cursorrules +426 -0
- package/.devin/wiki.json +143 -0
- package/.dockerignore +80 -0
- package/.env.example +159 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +49 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +29 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +57 -0
- package/.github/workflows/ci.yml +185 -0
- package/.github/workflows/codeql.yml +57 -0
- package/.github/workflows/docker-build-push.yml +118 -0
- package/.github/workflows/helm-release.yml +113 -0
- package/CLAUDE.md +265 -0
- package/CODE_OF_CONDUCT.md +124 -0
- package/CONTRIBUTING.md +154 -0
- package/Dockerfile +73 -0
- package/LICENSE +21 -0
- package/README.md +614 -0
- package/SECURITY.md +107 -0
- package/artifacthub-repo.yml +4 -0
- package/bun.lock +1714 -0
- package/bunfig.toml +3 -0
- package/charts/libredb-studio/.helmignore +11 -0
- package/charts/libredb-studio/Chart.lock +6 -0
- package/charts/libredb-studio/Chart.yaml +50 -0
- package/charts/libredb-studio/README.md +206 -0
- package/charts/libredb-studio/templates/NOTES.txt +59 -0
- package/charts/libredb-studio/templates/_helpers.tpl +135 -0
- package/charts/libredb-studio/templates/configmap.yaml +37 -0
- package/charts/libredb-studio/templates/deployment.yaml +184 -0
- package/charts/libredb-studio/templates/hpa.yaml +32 -0
- package/charts/libredb-studio/templates/ingress.yaml +41 -0
- package/charts/libredb-studio/templates/networkpolicy.yaml +50 -0
- package/charts/libredb-studio/templates/pdb.yaml +18 -0
- package/charts/libredb-studio/templates/pvc.yaml +23 -0
- package/charts/libredb-studio/templates/secret.yaml +30 -0
- package/charts/libredb-studio/templates/seed-configmap.yaml +11 -0
- package/charts/libredb-studio/templates/service.yaml +22 -0
- package/charts/libredb-studio/templates/serviceaccount.yaml +13 -0
- package/charts/libredb-studio/values.schema.json +246 -0
- package/charts/libredb-studio/values.yaml +286 -0
- package/components.json +22 -0
- package/conductor/code_styleguides/typescript.md +43 -0
- package/conductor/product-guidelines.md +43 -0
- package/conductor/product.md +3 -0
- package/conductor/setup_state.json +1 -0
- package/conductor/tech-stack.md +39 -0
- package/conductor/tracks/enhance_postgres_monitoring_20251227/metadata.json +8 -0
- package/conductor/tracks/enhance_postgres_monitoring_20251227/plan.md +44 -0
- package/conductor/tracks/enhance_postgres_monitoring_20251227/spec.md +31 -0
- package/conductor/tracks.md +8 -0
- package/conductor/workflow.md +333 -0
- package/database-compose.yml +55 -0
- package/docker/postgres-init/01-extensions.sql +10 -0
- package/docker/postgres-init/02-sample-data.sql +585 -0
- package/docker/postgres.yml +68 -0
- package/docker-compose.yml +38 -0
- package/docs/AI_PLAN.md +74 -0
- package/docs/API_DOCS.md +875 -0
- package/docs/ARCHITECTURE.md +218 -0
- package/docs/DATABASE_PROVIDERS.md +358 -0
- package/docs/FEATURES.md +116 -0
- package/docs/HELM_CHART.md +252 -0
- package/docs/LOGIN_PAGE.md +178 -0
- package/docs/MONACO_EDITOR_PERFORMANCE.md +315 -0
- package/docs/OIDC_ARCH.md +681 -0
- package/docs/OIDC_SETUP.md +322 -0
- package/docs/POSTGRES_METRICS.md +516 -0
- package/docs/QUERY_OPTIMIZATION.md +370 -0
- package/docs/SEED_CONNECTIONS.md +468 -0
- package/docs/SQL_ALIAS_COMPLETION.md +190 -0
- package/docs/STORAGE_ARCHITECTURE.md +565 -0
- package/docs/STORAGE_QUICK_SETUP.md +419 -0
- package/docs/TECHNICAL_PLAN.md +36 -0
- package/docs/THEMING.md +345 -0
- package/docs/adding-a-new-database-provider.md +642 -0
- package/docs/backlogs/000-PLATFORM_DATA_SYNC_DATABASE.md +360 -0
- package/docs/backlogs/001-INLINE_DATA_EDITING.md +118 -0
- package/docs/backlogs/002-DATA_IMPORT.md +215 -0
- package/docs/backlogs/003-QUERY_TIME_MACHINE.md +183 -0
- package/docs/backlogs/004-AI_DATA_STORYTELLER.md +292 -0
- package/docs/backlogs/005-QUERY_PLAYGROUND.md +352 -0
- package/docs/backlogs/006-DATA_MASKING.md +418 -0
- package/docs/enterprise-features.md +718 -0
- package/docs/kubernetes-helm-chart-artifacthub-plan.md +803 -0
- package/docs/medium-koyeb-article-en.md +215 -0
- package/docs/plans/test-plans.md +445 -0
- package/docs/releases/RELEASE.V0.3.0.md +22 -0
- package/docs/releases/RELEASE.V0.4.0.md +154 -0
- package/docs/releases/RELEASE.V0.5.0.md +252 -0
- package/docs/releases/RELEASE_v0.5.6.md +145 -0
- package/docs/releases/RELEASE_v0.6.1.md +303 -0
- package/docs/releases/RELEASE_v0.6.7.md +292 -0
- package/docs/releases/RELEASE_v0.7.0.md +332 -0
- package/docs/releases/RELEASE_v0.8.0.md +521 -0
- package/docs/sampledb/titanic.sql +1379 -0
- package/docs/superpowers/plans/2026-03-25-seed-connections.md +1362 -0
- package/docs/superpowers/specs/2026-03-25-seed-connections-design.md +590 -0
- package/e2e/admin-dashboard.spec.ts +64 -0
- package/e2e/connection-management.spec.ts +58 -0
- package/e2e/export.spec.ts +34 -0
- package/e2e/login.spec.ts +85 -0
- package/e2e/query-execution.spec.ts +35 -0
- package/e2e/tab-management.spec.ts +64 -0
- package/eslint.config.mjs +28 -0
- package/fly.toml +43 -0
- package/next.config.ts +32 -0
- package/package.json +130 -0
- package/playwright.config.ts +34 -0
- package/postcss.config.mjs +7 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/file.svg +1 -0
- package/public/globe.svg +1 -0
- package/public/logo.svg +32 -0
- package/public/next.svg +1 -0
- package/public/screenshots/code-generator.png +0 -0
- package/public/screenshots/connection-modal.png +0 -0
- package/public/screenshots/data-profiler.png +0 -0
- package/public/screenshots/erd-diagram.png +0 -0
- package/public/screenshots/hero-editor.png +0 -0
- package/public/screenshots/nl2sql.png +0 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
- package/render.yaml +58 -0
- package/scripts/merge-lcov.mjs +239 -0
- package/sonar-project.properties +16 -0
- package/src/app/admin/error.tsx +46 -0
- package/src/app/admin/page.tsx +10 -0
- package/src/app/api/admin/audit/route.ts +52 -0
- package/src/app/api/admin/fleet-health/route.ts +81 -0
- package/src/app/api/ai/autopilot/route.ts +105 -0
- package/src/app/api/ai/chat/route.ts +132 -0
- package/src/app/api/ai/describe-schema/route.ts +52 -0
- package/src/app/api/ai/explain/route.ts +86 -0
- package/src/app/api/ai/impact/route.ts +97 -0
- package/src/app/api/ai/index-advisor/route.ts +98 -0
- package/src/app/api/ai/nl2sql/route.ts +87 -0
- package/src/app/api/ai/query-safety/route.ts +87 -0
- package/src/app/api/auth/login/route.ts +62 -0
- package/src/app/api/auth/logout/route.ts +25 -0
- package/src/app/api/auth/me/route.ts +10 -0
- package/src/app/api/auth/oidc/callback/route.ts +82 -0
- package/src/app/api/auth/oidc/login/route.ts +43 -0
- package/src/app/api/connections/managed/route.ts +35 -0
- package/src/app/api/db/cancel/route.ts +42 -0
- package/src/app/api/db/disconnect/route.ts +28 -0
- package/src/app/api/db/health/route.ts +49 -0
- package/src/app/api/db/maintenance/route.ts +72 -0
- package/src/app/api/db/monitoring/route.ts +62 -0
- package/src/app/api/db/multi-query/route.ts +116 -0
- package/src/app/api/db/pool-stats/route.ts +37 -0
- package/src/app/api/db/profile/route.ts +144 -0
- package/src/app/api/db/provider-meta/route.ts +49 -0
- package/src/app/api/db/query/route.ts +50 -0
- package/src/app/api/db/schema/route.ts +47 -0
- package/src/app/api/db/schema-snapshot/route.ts +42 -0
- package/src/app/api/db/test-connection/route.ts +55 -0
- package/src/app/api/db/transaction/route.ts +111 -0
- package/src/app/api/storage/[collection]/route.ts +67 -0
- package/src/app/api/storage/config/route.ts +17 -0
- package/src/app/api/storage/migrate/route.ts +45 -0
- package/src/app/api/storage/route.ts +32 -0
- package/src/app/error.tsx +49 -0
- package/src/app/global-error.tsx +55 -0
- package/src/app/globals.css +146 -0
- package/src/app/icon.svg +42 -0
- package/src/app/layout.tsx +34 -0
- package/src/app/login/login-form.tsx +301 -0
- package/src/app/login/page.tsx +11 -0
- package/src/app/monitoring/page.tsx +8 -0
- package/src/app/not-found.tsx +29 -0
- package/src/app/page.tsx +5 -0
- package/src/components/AIAutopilotPanel.tsx +238 -0
- package/src/components/CodeGenerator.tsx +271 -0
- package/src/components/CommandPalette.tsx +227 -0
- package/src/components/ConnectionModal.tsx +759 -0
- package/src/components/CreateTableModal.tsx +281 -0
- package/src/components/DataCharts.tsx +962 -0
- package/src/components/DataImportModal.tsx +582 -0
- package/src/components/DataProfiler.tsx +335 -0
- package/src/components/DatabaseDocs.tsx +251 -0
- package/src/components/MaskingSettings.tsx +414 -0
- package/src/components/MobileNav.tsx +50 -0
- package/src/components/NL2SQLPanel.tsx +281 -0
- package/src/components/PivotTable.tsx +257 -0
- package/src/components/QueryEditor.tsx +760 -0
- package/src/components/QueryHistory.tsx +344 -0
- package/src/components/QuerySafetyDialog.tsx +290 -0
- package/src/components/ResultsGrid.tsx +644 -0
- package/src/components/SaveQueryModal.tsx +104 -0
- package/src/components/SavedQueries.tsx +128 -0
- package/src/components/SchemaDiagram.tsx +473 -0
- package/src/components/SchemaDiff.tsx +473 -0
- package/src/components/SnapshotTimeline.tsx +116 -0
- package/src/components/Studio.tsx +639 -0
- package/src/components/TestDataGenerator.tsx +261 -0
- package/src/components/VisualExplain.tsx +820 -0
- package/src/components/admin/AdminDashboard.tsx +163 -0
- package/src/components/admin/tabs/AuditTab.tsx +531 -0
- package/src/components/admin/tabs/MonitoringEmbed.tsx +11 -0
- package/src/components/admin/tabs/OperationsTab.tsx +646 -0
- package/src/components/admin/tabs/OverviewTab.tsx +1328 -0
- package/src/components/admin/tabs/SecurityTab.tsx +284 -0
- package/src/components/community-section.tsx +92 -0
- package/src/components/icons/db-icons.tsx +84 -0
- package/src/components/libredb-logo.tsx +61 -0
- package/src/components/monitoring/MonitoringDashboard.tsx +345 -0
- package/src/components/monitoring/tabs/MetricChart.tsx +82 -0
- package/src/components/monitoring/tabs/OverviewTab.tsx +263 -0
- package/src/components/monitoring/tabs/PerformanceTab.tsx +254 -0
- package/src/components/monitoring/tabs/PoolTab.tsx +174 -0
- package/src/components/monitoring/tabs/QueriesTab.tsx +287 -0
- package/src/components/monitoring/tabs/SessionsTab.tsx +316 -0
- package/src/components/monitoring/tabs/StorageTab.tsx +335 -0
- package/src/components/monitoring/tabs/TablesTab.tsx +300 -0
- package/src/components/results-grid/ResultCard.tsx +111 -0
- package/src/components/results-grid/RowDetailSheet.tsx +178 -0
- package/src/components/results-grid/StatsBar.tsx +201 -0
- package/src/components/results-grid/index.ts +1 -0
- package/src/components/results-grid/utils.ts +23 -0
- package/src/components/schema-explorer/ColumnList.tsx +53 -0
- package/src/components/schema-explorer/SchemaExplorer.tsx +182 -0
- package/src/components/schema-explorer/TableItem.tsx +210 -0
- package/src/components/schema-explorer/index.ts +1 -0
- package/src/components/sidebar/ConnectionItem.tsx +105 -0
- package/src/components/sidebar/ConnectionsList.tsx +62 -0
- package/src/components/sidebar/Sidebar.tsx +130 -0
- package/src/components/sidebar/index.ts +2 -0
- package/src/components/studio/BottomPanel.tsx +286 -0
- package/src/components/studio/QueryToolbar.tsx +180 -0
- package/src/components/studio/StudioDesktopHeader.tsx +114 -0
- package/src/components/studio/StudioMobileHeader.tsx +340 -0
- package/src/components/studio/StudioTabBar.tsx +82 -0
- package/src/components/studio/index.ts +5 -0
- package/src/components/ui/accordion.tsx +66 -0
- package/src/components/ui/alert-dialog.tsx +157 -0
- package/src/components/ui/alert.tsx +66 -0
- package/src/components/ui/aspect-ratio.tsx +11 -0
- package/src/components/ui/avatar.tsx +53 -0
- package/src/components/ui/badge.tsx +46 -0
- package/src/components/ui/breadcrumb.tsx +109 -0
- package/src/components/ui/button-group.tsx +83 -0
- package/src/components/ui/button.tsx +60 -0
- package/src/components/ui/calendar.tsx +216 -0
- package/src/components/ui/card.tsx +92 -0
- package/src/components/ui/carousel.tsx +241 -0
- package/src/components/ui/chart.tsx +357 -0
- package/src/components/ui/checkbox.tsx +32 -0
- package/src/components/ui/collapsible.tsx +33 -0
- package/src/components/ui/command.tsx +184 -0
- package/src/components/ui/context-menu.tsx +252 -0
- package/src/components/ui/dialog.tsx +143 -0
- package/src/components/ui/drawer.tsx +135 -0
- package/src/components/ui/dropdown-menu.tsx +257 -0
- package/src/components/ui/empty.tsx +104 -0
- package/src/components/ui/field.tsx +248 -0
- package/src/components/ui/form.tsx +167 -0
- package/src/components/ui/hover-card.tsx +44 -0
- package/src/components/ui/input-group.tsx +170 -0
- package/src/components/ui/input-otp.tsx +77 -0
- package/src/components/ui/input.tsx +21 -0
- package/src/components/ui/item.tsx +193 -0
- package/src/components/ui/kbd.tsx +28 -0
- package/src/components/ui/label.tsx +24 -0
- package/src/components/ui/menubar.tsx +276 -0
- package/src/components/ui/navigation-menu.tsx +168 -0
- package/src/components/ui/pagination.tsx +127 -0
- package/src/components/ui/popover.tsx +48 -0
- package/src/components/ui/progress.tsx +31 -0
- package/src/components/ui/radio-group.tsx +45 -0
- package/src/components/ui/resizable.tsx +56 -0
- package/src/components/ui/scroll-area.tsx +58 -0
- package/src/components/ui/select.tsx +187 -0
- package/src/components/ui/separator.tsx +28 -0
- package/src/components/ui/sheet.tsx +139 -0
- package/src/components/ui/sidebar.tsx +726 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/slider.tsx +63 -0
- package/src/components/ui/sonner.tsx +40 -0
- package/src/components/ui/spinner.tsx +16 -0
- package/src/components/ui/switch.tsx +31 -0
- package/src/components/ui/table.tsx +116 -0
- package/src/components/ui/tabs.tsx +66 -0
- package/src/components/ui/textarea.tsx +18 -0
- package/src/components/ui/toggle-group.tsx +83 -0
- package/src/components/ui/toggle.tsx +47 -0
- package/src/components/ui/tooltip.tsx +61 -0
- package/src/exports/components.ts +15 -0
- package/src/exports/index.ts +4 -0
- package/src/exports/providers.ts +4 -0
- package/src/exports/types.ts +26 -0
- package/src/hooks/use-ai-chat.ts +182 -0
- package/src/hooks/use-all-connections.ts +66 -0
- package/src/hooks/use-api-call.ts +71 -0
- package/src/hooks/use-auth.ts +51 -0
- package/src/hooks/use-connection-form.ts +349 -0
- package/src/hooks/use-connection-manager.ts +169 -0
- package/src/hooks/use-connection-payload.ts +15 -0
- package/src/hooks/use-inline-editing.ts +109 -0
- package/src/hooks/use-mobile.ts +20 -0
- package/src/hooks/use-monitoring-data.ts +270 -0
- package/src/hooks/use-provider-metadata.ts +62 -0
- package/src/hooks/use-query-execution.ts +478 -0
- package/src/hooks/use-storage-sync.ts +259 -0
- package/src/hooks/use-tab-manager.ts +231 -0
- package/src/hooks/use-toast.ts +20 -0
- package/src/hooks/use-transaction-control.ts +64 -0
- package/src/lib/api/error-codes.ts +30 -0
- package/src/lib/api/errors.ts +236 -0
- package/src/lib/api/with-error-handler.ts +41 -0
- package/src/lib/audit.ts +105 -0
- package/src/lib/auth.ts +87 -0
- package/src/lib/connection-string-parser.ts +172 -0
- package/src/lib/data-masking.ts +385 -0
- package/src/lib/db/base-provider.ts +325 -0
- package/src/lib/db/errors.ts +317 -0
- package/src/lib/db/factory.ts +324 -0
- package/src/lib/db/index.ts +123 -0
- package/src/lib/db/providers/document/index.ts +6 -0
- package/src/lib/db/providers/document/mongodb.ts +992 -0
- package/src/lib/db/providers/keyvalue/redis.ts +554 -0
- package/src/lib/db/providers/sql/index.ts +11 -0
- package/src/lib/db/providers/sql/mssql.ts +1065 -0
- package/src/lib/db/providers/sql/mysql.ts +978 -0
- package/src/lib/db/providers/sql/oracle.ts +1044 -0
- package/src/lib/db/providers/sql/postgres.ts +1179 -0
- package/src/lib/db/providers/sql/sql-base.ts +174 -0
- package/src/lib/db/providers/sql/sqlite.ts +721 -0
- package/src/lib/db/types.ts +437 -0
- package/src/lib/db/utils/pool-manager.ts +287 -0
- package/src/lib/db/utils/query-limiter.ts +239 -0
- package/src/lib/db-ui-config.ts +86 -0
- package/src/lib/editor/mongodb-completions.ts +172 -0
- package/src/lib/editor/sql-completions.ts +280 -0
- package/src/lib/llm/base-provider.ts +117 -0
- package/src/lib/llm/factory.ts +102 -0
- package/src/lib/llm/index.ts +90 -0
- package/src/lib/llm/providers/custom.ts +181 -0
- package/src/lib/llm/providers/gemini.ts +126 -0
- package/src/lib/llm/providers/ollama.ts +154 -0
- package/src/lib/llm/providers/openai.ts +146 -0
- package/src/lib/llm/types.ts +173 -0
- package/src/lib/llm/utils/config.ts +187 -0
- package/src/lib/llm/utils/retry.ts +119 -0
- package/src/lib/llm/utils/streaming.ts +202 -0
- package/src/lib/logger.ts +127 -0
- package/src/lib/monitoring-thresholds.ts +44 -0
- package/src/lib/oidc.ts +262 -0
- package/src/lib/query-generators.ts +61 -0
- package/src/lib/schema-diff/diff-engine.ts +273 -0
- package/src/lib/schema-diff/migration-generator.ts +208 -0
- package/src/lib/schema-diff/types.ts +55 -0
- package/src/lib/seed/config-loader.ts +79 -0
- package/src/lib/seed/connection-filter.ts +49 -0
- package/src/lib/seed/credential-resolver.ts +62 -0
- package/src/lib/seed/index.ts +40 -0
- package/src/lib/seed/resolve-connection.ts +57 -0
- package/src/lib/seed/types.ts +69 -0
- package/src/lib/sql/alias-extractor.ts +267 -0
- package/src/lib/sql/index.ts +8 -0
- package/src/lib/sql/statement-splitter.ts +167 -0
- package/src/lib/sql/types.ts +40 -0
- package/src/lib/ssh/tunnel.ts +142 -0
- package/src/lib/storage/factory.ts +84 -0
- package/src/lib/storage/index.ts +14 -0
- package/src/lib/storage/local-storage.ts +99 -0
- package/src/lib/storage/providers/postgres.ts +225 -0
- package/src/lib/storage/providers/sqlite.ts +153 -0
- package/src/lib/storage/storage-facade.ts +272 -0
- package/src/lib/storage/types.ts +75 -0
- package/src/lib/time-series-buffer.ts +58 -0
- package/src/lib/types.ts +173 -0
- package/src/lib/utils.ts +6 -0
- package/src/proxy.ts +104 -0
- package/src/types/db-drivers.d.ts +23 -0
- package/src/types/html2canvas.d.ts +9 -0
- package/tests/api/admin/audit.test.ts +178 -0
- package/tests/api/admin/fleet-health.test.ts +183 -0
- package/tests/api/ai/autopilot.test.ts +174 -0
- package/tests/api/ai/chat.test.ts +250 -0
- package/tests/api/ai/describe-schema.test.ts +266 -0
- package/tests/api/ai/explain.test.ts +199 -0
- package/tests/api/ai/impact.test.ts +168 -0
- package/tests/api/ai/index-advisor.test.ts +171 -0
- package/tests/api/ai/nl2sql.test.ts +202 -0
- package/tests/api/ai/query-safety.test.ts +196 -0
- package/tests/api/auth/login.test.ts +170 -0
- package/tests/api/auth/logout.test.ts +140 -0
- package/tests/api/auth/me.test.ts +73 -0
- package/tests/api/auth/oidc-callback.test.ts +215 -0
- package/tests/api/auth/oidc-login.test.ts +127 -0
- package/tests/api/db/cancel.test.ts +198 -0
- package/tests/api/db/disconnect.test.ts +124 -0
- package/tests/api/db/health.test.ts +222 -0
- package/tests/api/db/maintenance.test.ts +263 -0
- package/tests/api/db/monitoring.test.ts +221 -0
- package/tests/api/db/multi-query.test.ts +316 -0
- package/tests/api/db/pool-stats.test.ts +135 -0
- package/tests/api/db/profile.test.ts +330 -0
- package/tests/api/db/provider-meta.test.ts +193 -0
- package/tests/api/db/query.test.ts +314 -0
- package/tests/api/db/schema-snapshot.test.ts +170 -0
- package/tests/api/db/schema.test.ts +191 -0
- package/tests/api/db/test-connection.test.ts +185 -0
- package/tests/api/db/transaction.test.ts +314 -0
- package/tests/api/proxy.test.ts +191 -0
- package/tests/api/seed/managed-route.test.ts +113 -0
- package/tests/api/storage/config.test.ts +42 -0
- package/tests/api/storage/storage-routes.test.ts +309 -0
- package/tests/components/AIAutopilotPanel.test.tsx +756 -0
- package/tests/components/AdminPage.test.tsx +33 -0
- package/tests/components/CodeGenerator.test.tsx +182 -0
- package/tests/components/CommandPalette.test.tsx +428 -0
- package/tests/components/CommunitySection.test.tsx +91 -0
- package/tests/components/ConnectionModal.mobile.test.tsx +284 -0
- package/tests/components/ConnectionModal.test.tsx +570 -0
- package/tests/components/CreateTableModal.test.tsx +383 -0
- package/tests/components/DataCharts.test.tsx +739 -0
- package/tests/components/DataImportModal.test.tsx +751 -0
- package/tests/components/DataProfiler.test.tsx +589 -0
- package/tests/components/DatabaseDocs.test.tsx +353 -0
- package/tests/components/LoginPage.test.tsx +163 -0
- package/tests/components/LoginPageOIDC.test.tsx +92 -0
- package/tests/components/MaskingSettings.test.tsx +498 -0
- package/tests/components/MobileNav.test.tsx +30 -0
- package/tests/components/MonitoringPage.test.tsx +32 -0
- package/tests/components/NL2SQLPanel.test.tsx +621 -0
- package/tests/components/Page.test.tsx +33 -0
- package/tests/components/PivotTable.test.tsx +350 -0
- package/tests/components/QueryEditor.test.tsx +1730 -0
- package/tests/components/QueryHistory.test.tsx +572 -0
- package/tests/components/QuerySafetyDialog.test.tsx +586 -0
- package/tests/components/ResultsGrid.test.tsx +804 -0
- package/tests/components/RootLayout.test.tsx +83 -0
- package/tests/components/SaveQueryModal.test.tsx +25 -0
- package/tests/components/SavedQueries.test.tsx +43 -0
- package/tests/components/SchemaDiagram.test.tsx +1034 -0
- package/tests/components/SchemaDiff.test.tsx +906 -0
- package/tests/components/SnapshotTimeline.test.tsx +174 -0
- package/tests/components/Studio.test.tsx +1030 -0
- package/tests/components/TestDataGenerator.test.tsx +291 -0
- package/tests/components/VisualExplain.test.tsx +704 -0
- package/tests/components/admin/AdminDashboard.test.tsx +205 -0
- package/tests/components/admin/AuditTab.test.tsx +220 -0
- package/tests/components/admin/MonitoringEmbed.test.tsx +58 -0
- package/tests/components/admin/OperationsTab.test.tsx +975 -0
- package/tests/components/admin/OverviewTab.test.tsx +254 -0
- package/tests/components/admin/SecurityTab.test.tsx +467 -0
- package/tests/components/monitoring/MetricChart.test.tsx +111 -0
- package/tests/components/monitoring/MonitoringDashboard.test.tsx +259 -0
- package/tests/components/monitoring/OverviewTab.test.tsx +78 -0
- package/tests/components/monitoring/PerformanceTab.test.tsx +87 -0
- package/tests/components/monitoring/PoolTab.test.tsx +42 -0
- package/tests/components/monitoring/QueriesTab.test.tsx +80 -0
- package/tests/components/monitoring/SessionsTab.test.tsx +154 -0
- package/tests/components/monitoring/StorageTab.test.tsx +127 -0
- package/tests/components/monitoring/TablesTab.test.tsx +153 -0
- package/tests/components/results-grid/ResultCard.test.tsx +105 -0
- package/tests/components/results-grid/RowDetailSheet.test.tsx +308 -0
- package/tests/components/results-grid/StatsBar.test.tsx +162 -0
- package/tests/components/schema-explorer/ColumnList.test.tsx +151 -0
- package/tests/components/schema-explorer/SchemaExplorer.test.tsx +461 -0
- package/tests/components/schema-explorer/TableItem.test.tsx +415 -0
- package/tests/components/sidebar/ConnectionItem.test.tsx +201 -0
- package/tests/components/sidebar/ConnectionsList.test.tsx +176 -0
- package/tests/components/sidebar/Sidebar.test.tsx +187 -0
- package/tests/components/studio/BottomPanel.test.tsx +383 -0
- package/tests/components/studio/QueryToolbar.test.tsx +321 -0
- package/tests/components/studio/StudioDesktopHeader.test.tsx +377 -0
- package/tests/components/studio/StudioMobileHeader.test.tsx +198 -0
- package/tests/components/studio/StudioTabBar.test.tsx +331 -0
- package/tests/fixtures/connections.ts +96 -0
- package/tests/fixtures/masking-configs.ts +86 -0
- package/tests/fixtures/query-results.ts +71 -0
- package/tests/fixtures/schemas.ts +64 -0
- package/tests/fixtures/seed-connections/invalid-config.yaml +7 -0
- package/tests/fixtures/seed-connections/minimal-config.yaml +8 -0
- package/tests/fixtures/seed-connections/mixed-credentials.yaml +23 -0
- package/tests/fixtures/seed-connections/multi-role-config.yaml +30 -0
- package/tests/fixtures/seed-connections/valid-config.json +15 -0
- package/tests/fixtures/seed-connections/valid-config.yaml +51 -0
- package/tests/helpers/mock-fetch.ts +59 -0
- package/tests/helpers/mock-monaco.ts +112 -0
- package/tests/helpers/mock-navigation.ts +28 -0
- package/tests/helpers/mock-next.ts +80 -0
- package/tests/helpers/mock-provider.ts +133 -0
- package/tests/helpers/mock-sonner.ts +29 -0
- package/tests/helpers/render-with-providers.tsx +19 -0
- package/tests/hooks/use-ai-chat.test.ts +600 -0
- package/tests/hooks/use-auth.test.ts +371 -0
- package/tests/hooks/use-connection-form.test.ts +743 -0
- package/tests/hooks/use-connection-manager.test.ts +466 -0
- package/tests/hooks/use-inline-editing.test.ts +321 -0
- package/tests/hooks/use-mobile.test.ts +177 -0
- package/tests/hooks/use-monitoring-data.test.ts +819 -0
- package/tests/hooks/use-provider-metadata.test.ts +228 -0
- package/tests/hooks/use-query-execution.test.ts +1212 -0
- package/tests/hooks/use-tab-manager.test.ts +756 -0
- package/tests/hooks/use-toast.test.ts +74 -0
- package/tests/hooks/use-transaction-control.test.ts +211 -0
- package/tests/integration/db/mongodb-provider.test.ts +698 -0
- package/tests/integration/db/mssql-provider.test.ts +840 -0
- package/tests/integration/db/mysql-provider.test.ts +872 -0
- package/tests/integration/db/oracle-provider.test.ts +843 -0
- package/tests/integration/db/postgres-provider.test.ts +1382 -0
- package/tests/integration/db/redis-provider.test.ts +526 -0
- package/tests/integration/db/sqlite-provider.test.ts +480 -0
- package/tests/integration/seed/seed-pipeline.test.ts +102 -0
- package/tests/isolated/factory-singleton.test.ts +150 -0
- package/tests/isolated/use-storage-sync.test.ts +389 -0
- package/tests/run-components.sh +196 -0
- package/tests/setup-dom.ts +58 -0
- package/tests/setup.ts +40 -0
- package/tests/unit/api-errors.test.ts +210 -0
- package/tests/unit/code-generator-functions.test.ts +271 -0
- package/tests/unit/components/column-list.test.tsx +190 -0
- package/tests/unit/components/data-import-modal.test.tsx +441 -0
- package/tests/unit/components/studio-mobile-header.test.tsx +327 -0
- package/tests/unit/data-charts-functions.test.ts +496 -0
- package/tests/unit/data-import-functions.test.ts +320 -0
- package/tests/unit/data-import-utils.test.ts +125 -0
- package/tests/unit/db/base-provider.test.ts +517 -0
- package/tests/unit/db/errors.test.ts +403 -0
- package/tests/unit/db/factory.test.ts +436 -0
- package/tests/unit/db/pool-manager.test.ts +440 -0
- package/tests/unit/db/query-limiter.test.ts +387 -0
- package/tests/unit/db/sql-base.test.ts +438 -0
- package/tests/unit/lib/api/error-codes.test.ts +39 -0
- package/tests/unit/lib/audit.test.ts +326 -0
- package/tests/unit/lib/auth.test.ts +146 -0
- package/tests/unit/lib/connection-string-parser.test.ts +424 -0
- package/tests/unit/lib/data-masking.test.ts +583 -0
- package/tests/unit/lib/db-icons.test.tsx +41 -0
- package/tests/unit/lib/monitoring-thresholds.test.ts +133 -0
- package/tests/unit/lib/oidc.test.ts +509 -0
- package/tests/unit/lib/query-generators.test.ts +127 -0
- package/tests/unit/lib/storage/factory.test.ts +71 -0
- package/tests/unit/lib/storage/local-storage.test.ts +114 -0
- package/tests/unit/lib/storage/providers/postgres.test.ts +312 -0
- package/tests/unit/lib/storage/providers/sqlite.test.ts +232 -0
- package/tests/unit/lib/storage/storage-facade-extended.test.ts +331 -0
- package/tests/unit/lib/storage/storage-facade.test.ts +184 -0
- package/tests/unit/lib/storage.test.ts +317 -0
- package/tests/unit/lib/time-series-buffer.test.ts +212 -0
- package/tests/unit/lib/utils.test.ts +24 -0
- package/tests/unit/llm/base-provider.test.ts +238 -0
- package/tests/unit/llm/config.test.ts +262 -0
- package/tests/unit/llm/custom-provider.test.ts +281 -0
- package/tests/unit/llm/gemini-provider.test.ts +248 -0
- package/tests/unit/llm/llm-factory.test.ts +155 -0
- package/tests/unit/llm/ollama-provider.test.ts +288 -0
- package/tests/unit/llm/openai-provider.test.ts +324 -0
- package/tests/unit/llm/retry.test.ts +180 -0
- package/tests/unit/llm/streaming.test.ts +355 -0
- package/tests/unit/logger.test.ts +198 -0
- package/tests/unit/mongodb-completions.test.ts +516 -0
- package/tests/unit/pivot-table-functions.test.ts +76 -0
- package/tests/unit/query-cancelled-error.test.ts +81 -0
- package/tests/unit/schema-diff/diff-engine.test.ts +367 -0
- package/tests/unit/schema-diff/migration-generator.test.ts +513 -0
- package/tests/unit/seed/config-loader.test.ts +73 -0
- package/tests/unit/seed/connection-filter.test.ts +91 -0
- package/tests/unit/seed/credential-resolver.test.ts +85 -0
- package/tests/unit/seed/index.test.ts +72 -0
- package/tests/unit/seed/resolve-connection.test.ts +74 -0
- package/tests/unit/seed/types.test.ts +129 -0
- package/tests/unit/sql/alias-extractor.test.ts +444 -0
- package/tests/unit/sql/statement-splitter.test.ts +348 -0
- package/tests/unit/sql-completions.test.ts +463 -0
- package/tests/unit/ssh-tunnel.test.ts +465 -0
- 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
|
+
}
|