@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,437 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Provider Types & Interfaces
|
|
3
|
+
* Strategy Pattern implementation for multi-database support
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Re-export common types from main types file
|
|
7
|
+
export type {
|
|
8
|
+
DatabaseType,
|
|
9
|
+
DatabaseConnection,
|
|
10
|
+
TableSchema,
|
|
11
|
+
ColumnSchema,
|
|
12
|
+
IndexSchema,
|
|
13
|
+
ForeignKeySchema,
|
|
14
|
+
QueryResult,
|
|
15
|
+
} from '../types';
|
|
16
|
+
|
|
17
|
+
import type {
|
|
18
|
+
DatabaseType,
|
|
19
|
+
DatabaseConnection,
|
|
20
|
+
TableSchema,
|
|
21
|
+
QueryResult,
|
|
22
|
+
} from '../types';
|
|
23
|
+
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// Pool Configuration
|
|
26
|
+
// ============================================================================
|
|
27
|
+
|
|
28
|
+
export interface PoolConfig {
|
|
29
|
+
/** Minimum number of connections in pool (default: 2) */
|
|
30
|
+
min: number;
|
|
31
|
+
/** Maximum number of connections in pool (default: 10) */
|
|
32
|
+
max: number;
|
|
33
|
+
/** Close idle connections after this time in ms (default: 30000) */
|
|
34
|
+
idleTimeout: number;
|
|
35
|
+
/** Wait for connection timeout in ms (default: 60000) */
|
|
36
|
+
acquireTimeout: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const DEFAULT_POOL_CONFIG: PoolConfig = {
|
|
40
|
+
min: 2,
|
|
41
|
+
max: 10,
|
|
42
|
+
idleTimeout: 30000,
|
|
43
|
+
acquireTimeout: 60000,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/** Query timeout in milliseconds (default: 60 seconds) */
|
|
47
|
+
export const DEFAULT_QUERY_TIMEOUT = 60000;
|
|
48
|
+
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// Health Information
|
|
51
|
+
// ============================================================================
|
|
52
|
+
|
|
53
|
+
export interface SlowQuery {
|
|
54
|
+
query: string;
|
|
55
|
+
calls: number;
|
|
56
|
+
avgTime: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ActiveSession {
|
|
60
|
+
pid: number | string;
|
|
61
|
+
user: string;
|
|
62
|
+
database: string;
|
|
63
|
+
state: string;
|
|
64
|
+
query: string;
|
|
65
|
+
duration: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface HealthInfo {
|
|
69
|
+
activeConnections: number;
|
|
70
|
+
databaseSize: string;
|
|
71
|
+
cacheHitRatio: string;
|
|
72
|
+
slowQueries: SlowQuery[];
|
|
73
|
+
activeSessions: ActiveSession[];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// Maintenance Operations
|
|
78
|
+
// ============================================================================
|
|
79
|
+
|
|
80
|
+
export type MaintenanceType = 'vacuum' | 'analyze' | 'reindex' | 'kill' | 'optimize' | 'check';
|
|
81
|
+
|
|
82
|
+
export interface MaintenanceResult {
|
|
83
|
+
success: boolean;
|
|
84
|
+
executionTime: number;
|
|
85
|
+
message: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ============================================================================
|
|
89
|
+
// Provider Capabilities & Labels
|
|
90
|
+
// ============================================================================
|
|
91
|
+
|
|
92
|
+
export interface ProviderCapabilities {
|
|
93
|
+
queryLanguage: 'sql' | 'json';
|
|
94
|
+
supportsExplain: boolean;
|
|
95
|
+
supportsExternalQueryLimiting: boolean;
|
|
96
|
+
supportsCreateTable: boolean;
|
|
97
|
+
supportsMaintenance: boolean;
|
|
98
|
+
maintenanceOperations: MaintenanceType[];
|
|
99
|
+
supportsConnectionString: boolean;
|
|
100
|
+
defaultPort: number | null;
|
|
101
|
+
schemaRefreshPattern: string;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface ProviderLabels {
|
|
105
|
+
entityName: string;
|
|
106
|
+
entityNamePlural: string;
|
|
107
|
+
rowName: string;
|
|
108
|
+
rowNamePlural: string;
|
|
109
|
+
selectAction: string;
|
|
110
|
+
generateAction: string;
|
|
111
|
+
analyzeAction: string;
|
|
112
|
+
vacuumAction: string;
|
|
113
|
+
searchPlaceholder: string;
|
|
114
|
+
analyzeGlobalLabel: string;
|
|
115
|
+
analyzeGlobalTitle: string;
|
|
116
|
+
analyzeGlobalDesc: string;
|
|
117
|
+
vacuumGlobalLabel: string;
|
|
118
|
+
vacuumGlobalTitle: string;
|
|
119
|
+
vacuumGlobalDesc: string;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface PreparedQuery {
|
|
123
|
+
query: string;
|
|
124
|
+
wasLimited: boolean;
|
|
125
|
+
limit: number;
|
|
126
|
+
offset: number;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface QueryPrepareOptions {
|
|
130
|
+
limit?: number;
|
|
131
|
+
offset?: number;
|
|
132
|
+
unlimited?: boolean;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ============================================================================
|
|
136
|
+
// Provider Interface (Strategy Pattern)
|
|
137
|
+
// ============================================================================
|
|
138
|
+
|
|
139
|
+
export interface DatabaseProvider {
|
|
140
|
+
/** Database type identifier */
|
|
141
|
+
readonly type: DatabaseType;
|
|
142
|
+
|
|
143
|
+
/** Connection configuration */
|
|
144
|
+
readonly config: DatabaseConnection;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Initialize connection pool or single connection
|
|
148
|
+
*/
|
|
149
|
+
connect(): Promise<void>;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Close all connections and cleanup resources
|
|
153
|
+
*/
|
|
154
|
+
disconnect(): Promise<void>;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Check if provider is currently connected
|
|
158
|
+
*/
|
|
159
|
+
isConnected(): boolean;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Execute a SQL query
|
|
163
|
+
* @param sql - SQL query string
|
|
164
|
+
* @param params - Optional query parameters for prepared statements
|
|
165
|
+
* @returns Query result with rows, fields, and execution time
|
|
166
|
+
*/
|
|
167
|
+
query(sql: string, params?: unknown[]): Promise<QueryResult>;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Get full database schema
|
|
171
|
+
* @returns Array of table schemas with columns, indexes, and foreign keys
|
|
172
|
+
*/
|
|
173
|
+
getSchema(): Promise<TableSchema[]>;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Get list of table names
|
|
177
|
+
*/
|
|
178
|
+
getTables(): Promise<string[]>;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Get health and performance metrics
|
|
182
|
+
*/
|
|
183
|
+
getHealth(): Promise<HealthInfo>;
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Get comprehensive monitoring data
|
|
187
|
+
* @param options - What to include in the monitoring data
|
|
188
|
+
*/
|
|
189
|
+
getMonitoringData(options?: MonitoringOptions): Promise<MonitoringData>;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Get database overview metrics
|
|
193
|
+
*/
|
|
194
|
+
getOverview(): Promise<DatabaseOverview>;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Get performance metrics
|
|
198
|
+
*/
|
|
199
|
+
getPerformanceMetrics(): Promise<PerformanceMetrics>;
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Get slow query statistics
|
|
203
|
+
* @param options - Query options (limit)
|
|
204
|
+
*/
|
|
205
|
+
getSlowQueries(options?: { limit?: number }): Promise<SlowQueryStats[]>;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Get active sessions with details
|
|
209
|
+
* @param options - Query options (limit)
|
|
210
|
+
*/
|
|
211
|
+
getActiveSessions(options?: { limit?: number }): Promise<ActiveSessionDetails[]>;
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Get table statistics
|
|
215
|
+
* @param options - Query options (schema filter)
|
|
216
|
+
*/
|
|
217
|
+
getTableStats(options?: { schema?: string }): Promise<TableStats[]>;
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Get index statistics
|
|
221
|
+
* @param options - Query options (schema filter)
|
|
222
|
+
*/
|
|
223
|
+
getIndexStats(options?: { schema?: string }): Promise<IndexStats[]>;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Get storage/tablespace statistics
|
|
227
|
+
*/
|
|
228
|
+
getStorageStats(): Promise<StorageStats[]>;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Run maintenance operations
|
|
232
|
+
* @param type - Type of maintenance operation
|
|
233
|
+
* @param target - Optional target (table name or process ID)
|
|
234
|
+
*/
|
|
235
|
+
runMaintenance(type: MaintenanceType, target?: string): Promise<MaintenanceResult>;
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Validate provider configuration
|
|
239
|
+
* @throws DatabaseConfigError if configuration is invalid
|
|
240
|
+
*/
|
|
241
|
+
validate(): void;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Get provider capabilities (query language, supported features, etc.)
|
|
245
|
+
*/
|
|
246
|
+
getCapabilities(): ProviderCapabilities;
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Get UI labels for this provider (entity names, action labels, etc.)
|
|
250
|
+
*/
|
|
251
|
+
getLabels(): ProviderLabels;
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Prepare a query for execution (apply limits, analyze query type, etc.)
|
|
255
|
+
*/
|
|
256
|
+
prepareQuery(query: string, options?: QueryPrepareOptions): PreparedQuery;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// ============================================================================
|
|
260
|
+
// Provider Configuration Options
|
|
261
|
+
// ============================================================================
|
|
262
|
+
|
|
263
|
+
export interface ProviderOptions {
|
|
264
|
+
/** Connection pool configuration */
|
|
265
|
+
pool?: Partial<PoolConfig>;
|
|
266
|
+
/** Query timeout in milliseconds */
|
|
267
|
+
queryTimeout?: number;
|
|
268
|
+
/** Enable SSL/TLS connection */
|
|
269
|
+
ssl?: boolean | { rejectUnauthorized: boolean };
|
|
270
|
+
/** Connection timezone */
|
|
271
|
+
timezone?: string;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// ============================================================================
|
|
275
|
+
// Internal Types
|
|
276
|
+
// ============================================================================
|
|
277
|
+
|
|
278
|
+
export interface ConnectionState {
|
|
279
|
+
connected: boolean;
|
|
280
|
+
lastConnected?: Date;
|
|
281
|
+
lastError?: Error;
|
|
282
|
+
activeQueries: number;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// ============================================================================
|
|
286
|
+
// Monitoring Types (Extended)
|
|
287
|
+
// ============================================================================
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Database overview metrics
|
|
291
|
+
*/
|
|
292
|
+
export interface DatabaseOverview {
|
|
293
|
+
version: string;
|
|
294
|
+
uptime: string;
|
|
295
|
+
startTime?: Date;
|
|
296
|
+
activeConnections: number;
|
|
297
|
+
maxConnections: number;
|
|
298
|
+
databaseSize: string;
|
|
299
|
+
databaseSizeBytes: number;
|
|
300
|
+
tableCount: number;
|
|
301
|
+
indexCount: number;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Performance metrics for the database
|
|
306
|
+
*/
|
|
307
|
+
export interface PerformanceMetrics {
|
|
308
|
+
/** Cache hit ratio as percentage (0-100) */
|
|
309
|
+
cacheHitRatio: number;
|
|
310
|
+
/** Transactions per second */
|
|
311
|
+
transactionsPerSecond?: number;
|
|
312
|
+
/** Queries per second */
|
|
313
|
+
queriesPerSecond?: number;
|
|
314
|
+
/** Buffer pool usage as percentage (0-100) */
|
|
315
|
+
bufferPoolUsage?: number;
|
|
316
|
+
/** Number of deadlocks */
|
|
317
|
+
deadlocks?: number;
|
|
318
|
+
/** Checkpoint write time */
|
|
319
|
+
checkpointWriteTime?: string;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Slow query with detailed statistics
|
|
324
|
+
*/
|
|
325
|
+
export interface SlowQueryStats {
|
|
326
|
+
queryId?: string;
|
|
327
|
+
query: string;
|
|
328
|
+
calls: number;
|
|
329
|
+
totalTime: number;
|
|
330
|
+
avgTime: number;
|
|
331
|
+
minTime?: number;
|
|
332
|
+
maxTime?: number;
|
|
333
|
+
rows: number;
|
|
334
|
+
sharedBlksHit?: number;
|
|
335
|
+
sharedBlksRead?: number;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Active session with detailed information
|
|
340
|
+
*/
|
|
341
|
+
export interface ActiveSessionDetails {
|
|
342
|
+
pid: number | string;
|
|
343
|
+
user: string;
|
|
344
|
+
database: string;
|
|
345
|
+
applicationName?: string;
|
|
346
|
+
clientAddr?: string;
|
|
347
|
+
state: string;
|
|
348
|
+
query: string;
|
|
349
|
+
queryStart?: Date;
|
|
350
|
+
duration: string;
|
|
351
|
+
durationMs: number;
|
|
352
|
+
waitEventType?: string;
|
|
353
|
+
waitEvent?: string;
|
|
354
|
+
blocked?: boolean;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Table statistics
|
|
359
|
+
*/
|
|
360
|
+
export interface TableStats {
|
|
361
|
+
schemaName: string;
|
|
362
|
+
tableName: string;
|
|
363
|
+
rowCount: number;
|
|
364
|
+
liveRowCount?: number;
|
|
365
|
+
deadRowCount?: number;
|
|
366
|
+
tableSize: string;
|
|
367
|
+
tableSizeBytes: number;
|
|
368
|
+
indexSize?: string;
|
|
369
|
+
indexSizeBytes?: number;
|
|
370
|
+
totalSize: string;
|
|
371
|
+
totalSizeBytes: number;
|
|
372
|
+
lastVacuum?: Date;
|
|
373
|
+
lastAnalyze?: Date;
|
|
374
|
+
bloatRatio?: number;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Index statistics
|
|
379
|
+
*/
|
|
380
|
+
export interface IndexStats {
|
|
381
|
+
schemaName: string;
|
|
382
|
+
tableName: string;
|
|
383
|
+
indexName: string;
|
|
384
|
+
indexType?: string;
|
|
385
|
+
columns: string[];
|
|
386
|
+
isUnique: boolean;
|
|
387
|
+
isPrimary: boolean;
|
|
388
|
+
indexSize: string;
|
|
389
|
+
indexSizeBytes: number;
|
|
390
|
+
scans: number;
|
|
391
|
+
usageRatio?: number;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Storage statistics
|
|
396
|
+
*/
|
|
397
|
+
export interface StorageStats {
|
|
398
|
+
name: string;
|
|
399
|
+
location?: string;
|
|
400
|
+
size: string;
|
|
401
|
+
sizeBytes: number;
|
|
402
|
+
usagePercent?: number;
|
|
403
|
+
walSize?: string;
|
|
404
|
+
walSizeBytes?: number;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Comprehensive monitoring data combining all metrics
|
|
409
|
+
*/
|
|
410
|
+
export interface MonitoringData {
|
|
411
|
+
timestamp: Date;
|
|
412
|
+
overview: DatabaseOverview;
|
|
413
|
+
performance: PerformanceMetrics;
|
|
414
|
+
slowQueries: SlowQueryStats[];
|
|
415
|
+
activeSessions: ActiveSessionDetails[];
|
|
416
|
+
tables?: TableStats[];
|
|
417
|
+
indexes?: IndexStats[];
|
|
418
|
+
storage?: StorageStats[];
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Options for monitoring queries
|
|
423
|
+
*/
|
|
424
|
+
export interface MonitoringOptions {
|
|
425
|
+
/** Include table statistics */
|
|
426
|
+
includeTables?: boolean;
|
|
427
|
+
/** Include index statistics */
|
|
428
|
+
includeIndexes?: boolean;
|
|
429
|
+
/** Include storage/tablespace info */
|
|
430
|
+
includeStorage?: boolean;
|
|
431
|
+
/** Limit for slow queries (default: 10) */
|
|
432
|
+
slowQueryLimit?: number;
|
|
433
|
+
/** Limit for active sessions (default: 50) */
|
|
434
|
+
sessionLimit?: number;
|
|
435
|
+
/** Schema filter (default: 'public' for PostgreSQL) */
|
|
436
|
+
schemaFilter?: string;
|
|
437
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection Pool Manager
|
|
3
|
+
* Abstract pool management utilities for database providers
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { type PoolConfig, DEFAULT_POOL_CONFIG, type DatabaseType } from '../types';
|
|
7
|
+
import { TimeoutError } from '../errors';
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Pool Statistics
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
export interface PoolStats {
|
|
14
|
+
/** Total connections in pool */
|
|
15
|
+
total: number;
|
|
16
|
+
/** Currently idle connections */
|
|
17
|
+
idle: number;
|
|
18
|
+
/** Currently active/busy connections */
|
|
19
|
+
active: number;
|
|
20
|
+
/** Connections waiting in queue */
|
|
21
|
+
waiting: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// Pool Manager Interface
|
|
26
|
+
// ============================================================================
|
|
27
|
+
|
|
28
|
+
export interface PoolManager<T> {
|
|
29
|
+
/** Acquire a connection from the pool */
|
|
30
|
+
acquire(): Promise<T>;
|
|
31
|
+
/** Release a connection back to the pool */
|
|
32
|
+
release(connection: T): void;
|
|
33
|
+
/** Get pool statistics */
|
|
34
|
+
getStats(): PoolStats;
|
|
35
|
+
/** Drain all connections and close pool */
|
|
36
|
+
drain(): Promise<void>;
|
|
37
|
+
/** Check if pool is healthy */
|
|
38
|
+
isHealthy(): boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// Pool Configuration Utilities
|
|
43
|
+
// ============================================================================
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Merge user config with defaults
|
|
47
|
+
*/
|
|
48
|
+
export function mergePoolConfig(config?: Partial<PoolConfig>): PoolConfig {
|
|
49
|
+
return {
|
|
50
|
+
...DEFAULT_POOL_CONFIG,
|
|
51
|
+
...config,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Validate pool configuration
|
|
57
|
+
*/
|
|
58
|
+
export function validatePoolConfig(config: PoolConfig): void {
|
|
59
|
+
if (config.min < 0) {
|
|
60
|
+
throw new Error('Pool min must be non-negative');
|
|
61
|
+
}
|
|
62
|
+
if (config.max < 1) {
|
|
63
|
+
throw new Error('Pool max must be at least 1');
|
|
64
|
+
}
|
|
65
|
+
if (config.min > config.max) {
|
|
66
|
+
throw new Error('Pool min cannot be greater than max');
|
|
67
|
+
}
|
|
68
|
+
if (config.idleTimeout < 0) {
|
|
69
|
+
throw new Error('Pool idleTimeout must be non-negative');
|
|
70
|
+
}
|
|
71
|
+
if (config.acquireTimeout < 0) {
|
|
72
|
+
throw new Error('Pool acquireTimeout must be non-negative');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// Timeout Utilities
|
|
78
|
+
// ============================================================================
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Execute a promise with timeout
|
|
82
|
+
*/
|
|
83
|
+
export async function withTimeout<T>(
|
|
84
|
+
promise: Promise<T>,
|
|
85
|
+
timeout: number,
|
|
86
|
+
provider: DatabaseType,
|
|
87
|
+
operation: string
|
|
88
|
+
): Promise<T> {
|
|
89
|
+
let timeoutId: NodeJS.Timeout;
|
|
90
|
+
|
|
91
|
+
const timeoutPromise = new Promise<never>((_, reject) => {
|
|
92
|
+
timeoutId = setTimeout(() => {
|
|
93
|
+
reject(new TimeoutError(
|
|
94
|
+
`${operation} timed out after ${timeout}ms`,
|
|
95
|
+
provider,
|
|
96
|
+
timeout
|
|
97
|
+
));
|
|
98
|
+
}, timeout);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
const result = await Promise.race([promise, timeoutPromise]);
|
|
103
|
+
clearTimeout(timeoutId!);
|
|
104
|
+
return result;
|
|
105
|
+
} catch (error) {
|
|
106
|
+
clearTimeout(timeoutId!);
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Create a cancellable query wrapper
|
|
113
|
+
*/
|
|
114
|
+
export function createCancellableQuery<T>(
|
|
115
|
+
queryFn: (signal?: AbortSignal) => Promise<T>,
|
|
116
|
+
timeout: number,
|
|
117
|
+
provider: DatabaseType
|
|
118
|
+
): { promise: Promise<T>; cancel: () => void } {
|
|
119
|
+
const controller = new AbortController();
|
|
120
|
+
let timeoutId: NodeJS.Timeout;
|
|
121
|
+
|
|
122
|
+
const promise = new Promise<T>((resolve, reject) => {
|
|
123
|
+
timeoutId = setTimeout(() => {
|
|
124
|
+
controller.abort();
|
|
125
|
+
reject(new TimeoutError(
|
|
126
|
+
`Query timed out after ${timeout}ms`,
|
|
127
|
+
provider,
|
|
128
|
+
timeout
|
|
129
|
+
));
|
|
130
|
+
}, timeout);
|
|
131
|
+
|
|
132
|
+
queryFn(controller.signal)
|
|
133
|
+
.then(resolve)
|
|
134
|
+
.catch(reject)
|
|
135
|
+
.finally(() => clearTimeout(timeoutId));
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
promise,
|
|
140
|
+
cancel: () => {
|
|
141
|
+
clearTimeout(timeoutId);
|
|
142
|
+
controller.abort();
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ============================================================================
|
|
148
|
+
// Connection Health Check
|
|
149
|
+
// ============================================================================
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Simple ping-like health check
|
|
153
|
+
*/
|
|
154
|
+
export async function checkConnectionHealth<T>(
|
|
155
|
+
acquireFn: () => Promise<T>,
|
|
156
|
+
releaseFn: (conn: T) => void,
|
|
157
|
+
pingFn: (conn: T) => Promise<void>,
|
|
158
|
+
timeout: number,
|
|
159
|
+
provider: DatabaseType
|
|
160
|
+
): Promise<boolean> {
|
|
161
|
+
try {
|
|
162
|
+
const conn = await withTimeout(
|
|
163
|
+
acquireFn(),
|
|
164
|
+
timeout,
|
|
165
|
+
provider,
|
|
166
|
+
'Connection acquire'
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
await withTimeout(
|
|
171
|
+
pingFn(conn),
|
|
172
|
+
timeout,
|
|
173
|
+
provider,
|
|
174
|
+
'Connection ping'
|
|
175
|
+
);
|
|
176
|
+
return true;
|
|
177
|
+
} finally {
|
|
178
|
+
releaseFn(conn);
|
|
179
|
+
}
|
|
180
|
+
} catch {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ============================================================================
|
|
186
|
+
// Retry Logic
|
|
187
|
+
// ============================================================================
|
|
188
|
+
|
|
189
|
+
export interface RetryOptions {
|
|
190
|
+
maxAttempts?: number;
|
|
191
|
+
initialDelay?: number;
|
|
192
|
+
maxDelay?: number;
|
|
193
|
+
backoffMultiplier?: number;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {
|
|
197
|
+
maxAttempts: 3,
|
|
198
|
+
initialDelay: 1000,
|
|
199
|
+
maxDelay: 10000,
|
|
200
|
+
backoffMultiplier: 2,
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Execute with retry logic and exponential backoff
|
|
205
|
+
*/
|
|
206
|
+
export async function withRetry<T>(
|
|
207
|
+
fn: () => Promise<T>,
|
|
208
|
+
options: RetryOptions = {},
|
|
209
|
+
isRetryable: (error: unknown) => boolean = () => true,
|
|
210
|
+
provider?: DatabaseType
|
|
211
|
+
): Promise<T> {
|
|
212
|
+
const opts = { ...DEFAULT_RETRY_OPTIONS, ...options };
|
|
213
|
+
let lastError: Error | undefined;
|
|
214
|
+
let delay = opts.initialDelay;
|
|
215
|
+
|
|
216
|
+
for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {
|
|
217
|
+
try {
|
|
218
|
+
return await fn();
|
|
219
|
+
} catch (error) {
|
|
220
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
221
|
+
|
|
222
|
+
if (!isRetryable(error) || attempt === opts.maxAttempts) {
|
|
223
|
+
throw error;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
console.error(
|
|
227
|
+
`[DB${provider ? `:${provider}` : ''}] Operation failed (attempt ${attempt}/${opts.maxAttempts}): ${lastError.message}. Retrying in ${delay}ms...`
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
await sleep(delay);
|
|
231
|
+
delay = Math.min(delay * opts.backoffMultiplier, opts.maxDelay);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
throw lastError;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function sleep(ms: number): Promise<void> {
|
|
239
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ============================================================================
|
|
243
|
+
// SQL Utilities
|
|
244
|
+
// ============================================================================
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Escape SQL identifier (table name, column name)
|
|
248
|
+
* Prevents SQL injection in dynamic queries
|
|
249
|
+
*/
|
|
250
|
+
export function escapeIdentifier(identifier: string, provider: DatabaseType): string {
|
|
251
|
+
// Remove any existing quotes and escape internal quotes
|
|
252
|
+
const cleaned = identifier.replace(/["'`]/g, '');
|
|
253
|
+
|
|
254
|
+
switch (provider) {
|
|
255
|
+
case 'postgres':
|
|
256
|
+
return `"${cleaned}"`;
|
|
257
|
+
case 'mysql':
|
|
258
|
+
return `\`${cleaned}\``;
|
|
259
|
+
case 'sqlite':
|
|
260
|
+
return `"${cleaned}"`;
|
|
261
|
+
default:
|
|
262
|
+
return `"${cleaned}"`;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Format bytes to human readable size
|
|
268
|
+
*/
|
|
269
|
+
export function formatBytes(bytes: number): string {
|
|
270
|
+
if (bytes === 0) return '0 B';
|
|
271
|
+
|
|
272
|
+
const k = 1024;
|
|
273
|
+
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
274
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
275
|
+
|
|
276
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Format duration in milliseconds to human readable
|
|
281
|
+
*/
|
|
282
|
+
export function formatDuration(ms: number): string {
|
|
283
|
+
if (ms < 1000) return `${ms}ms`;
|
|
284
|
+
if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`;
|
|
285
|
+
if (ms < 3600000) return `${(ms / 60000).toFixed(2)}m`;
|
|
286
|
+
return `${(ms / 3600000).toFixed(2)}h`;
|
|
287
|
+
}
|