@libredb/studio 0.9.7 → 0.9.12
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/dist/chunk-34YQUUCM.mjs +319 -0
- package/dist/chunk-34YQUUCM.mjs.map +1 -0
- package/dist/chunk-4LVB3K53.mjs +37 -0
- package/dist/chunk-4LVB3K53.mjs.map +1 -0
- package/dist/chunk-6DRZXXNT.mjs +100 -0
- package/dist/chunk-6DRZXXNT.mjs.map +1 -0
- package/dist/chunk-CZVV3JJB.mjs +160 -0
- package/dist/chunk-CZVV3JJB.mjs.map +1 -0
- package/dist/chunk-D4WVWWWF.js +332 -0
- package/dist/chunk-D4WVWWWF.js.map +1 -0
- package/dist/chunk-DY3KXE44.mjs +3 -0
- package/dist/chunk-DY3KXE44.mjs.map +1 -0
- package/dist/chunk-DZ2UB3C6.mjs +6679 -0
- package/dist/chunk-DZ2UB3C6.mjs.map +1 -0
- package/dist/chunk-FYSE52VB.js +242 -0
- package/dist/chunk-FYSE52VB.js.map +1 -0
- package/dist/chunk-G4WYE6TI.js +4 -0
- package/dist/chunk-G4WYE6TI.js.map +1 -0
- package/dist/chunk-JOGLIOFO.js +1310 -0
- package/dist/chunk-JOGLIOFO.js.map +1 -0
- package/dist/chunk-JZO5KRZN.js +165 -0
- package/dist/chunk-JZO5KRZN.js.map +1 -0
- package/dist/chunk-KV356UXJ.js +253 -0
- package/dist/chunk-KV356UXJ.js.map +1 -0
- package/dist/chunk-PPODO6HX.mjs +237 -0
- package/dist/chunk-PPODO6HX.mjs.map +1 -0
- package/dist/chunk-PTIRB2JO.js +258 -0
- package/dist/chunk-PTIRB2JO.js.map +1 -0
- package/dist/chunk-Q6LRDBK7.js +42 -0
- package/dist/chunk-Q6LRDBK7.js.map +1 -0
- package/dist/chunk-QJP5FZRY.mjs +255 -0
- package/dist/chunk-QJP5FZRY.mjs.map +1 -0
- package/dist/chunk-R3POCJK6.mjs +248 -0
- package/dist/chunk-R3POCJK6.mjs.map +1 -0
- package/dist/chunk-RBVDMLFV.js +6747 -0
- package/dist/chunk-RBVDMLFV.js.map +1 -0
- package/dist/chunk-RCQB4FCE.js +186 -0
- package/dist/chunk-RCQB4FCE.js.map +1 -0
- package/dist/chunk-SR5DRGBX.mjs +174 -0
- package/dist/chunk-SR5DRGBX.mjs.map +1 -0
- package/dist/chunk-VLCRUZX7.js +102 -0
- package/dist/chunk-VLCRUZX7.js.map +1 -0
- package/dist/chunk-VWVRUCQO.mjs +1289 -0
- package/dist/chunk-VWVRUCQO.mjs.map +1 -0
- package/dist/components.d.mts +273 -0
- package/dist/components.d.ts +273 -0
- package/dist/components.js +59 -0
- package/dist/components.js.map +1 -0
- package/dist/components.mjs +6 -0
- package/dist/components.mjs.map +1 -0
- package/dist/custom-BNDOYC5P.js +134 -0
- package/dist/custom-BNDOYC5P.js.map +1 -0
- package/dist/custom-S2EKFMP3.mjs +132 -0
- package/dist/custom-S2EKFMP3.mjs.map +1 -0
- package/dist/gemini-4ASHNK4H.js +81 -0
- package/dist/gemini-4ASHNK4H.js.map +1 -0
- package/dist/gemini-C5RBLQEJ.mjs +79 -0
- package/dist/gemini-C5RBLQEJ.mjs.map +1 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +10 -0
- package/dist/index.mjs.map +1 -0
- package/dist/mongodb-XMZEZA4A.mjs +748 -0
- package/dist/mongodb-XMZEZA4A.mjs.map +1 -0
- package/dist/mongodb-YQJJTLX3.js +750 -0
- package/dist/mongodb-YQJJTLX3.js.map +1 -0
- package/dist/mssql-PMOU4D36.js +916 -0
- package/dist/mssql-PMOU4D36.js.map +1 -0
- package/{src/lib/db/providers/sql/mssql.ts → dist/mssql-ZH5VP2C5.mjs} +268 -423
- package/dist/mssql-ZH5VP2C5.mjs.map +1 -0
- package/{src/lib/db/providers/sql/mysql.ts → dist/mysql-I3WJQXN2.mjs} +277 -428
- package/dist/mysql-I3WJQXN2.mjs.map +1 -0
- package/dist/mysql-Y3MSA5QY.js +833 -0
- package/dist/mysql-Y3MSA5QY.js.map +1 -0
- package/dist/ollama-26BYLVEV.mjs +115 -0
- package/dist/ollama-26BYLVEV.mjs.map +1 -0
- package/dist/ollama-HVWAGKQC.js +117 -0
- package/dist/ollama-HVWAGKQC.js.map +1 -0
- package/dist/openai-4U56KPG7.mjs +111 -0
- package/dist/openai-4U56KPG7.mjs.map +1 -0
- package/dist/openai-AK3R37BS.js +113 -0
- package/dist/openai-AK3R37BS.js.map +1 -0
- package/dist/oracle-L6VEAVXO.js +917 -0
- package/dist/oracle-L6VEAVXO.js.map +1 -0
- package/{src/lib/db/providers/sql/oracle.ts → dist/oracle-P2G7T4P4.mjs} +321 -454
- package/dist/oracle-P2G7T4P4.mjs.map +1 -0
- package/{src/lib/db/providers/sql/postgres.ts → dist/postgres-O5KOQUVP.mjs} +261 -471
- package/dist/postgres-O5KOQUVP.mjs.map +1 -0
- package/dist/postgres-RLCWNFFX.js +971 -0
- package/dist/postgres-RLCWNFFX.js.map +1 -0
- package/dist/providers.d.mts +149 -0
- package/dist/providers.d.ts +149 -0
- package/dist/providers.js +44 -0
- package/dist/providers.js.map +1 -0
- package/dist/providers.mjs +7 -0
- package/dist/providers.mjs.map +1 -0
- package/dist/redis-4WMQOVLX.mjs +435 -0
- package/dist/redis-4WMQOVLX.mjs.map +1 -0
- package/dist/redis-QVQ6YU62.js +441 -0
- package/dist/redis-QVQ6YU62.js.map +1 -0
- package/dist/sqlite-4I2P2OGQ.js +554 -0
- package/dist/sqlite-4I2P2OGQ.js.map +1 -0
- package/dist/sqlite-OA4YJX5S.mjs +531 -0
- package/dist/sqlite-OA4YJX5S.mjs.map +1 -0
- package/dist/types-BJvJfxSY.d.mts +141 -0
- package/dist/types-BJvJfxSY.d.ts +141 -0
- package/dist/types-ClAg_v5k.d.mts +343 -0
- package/dist/types-Der_X8E8.d.ts +343 -0
- package/dist/types.d.mts +2 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/types.mjs +3 -0
- package/dist/types.mjs.map +1 -0
- package/dist/workspace.d.mts +80 -0
- package/dist/workspace.d.ts +80 -0
- package/dist/workspace.js +4182 -0
- package/dist/workspace.js.map +1 -0
- package/dist/workspace.mjs +4155 -0
- package/dist/workspace.mjs.map +1 -0
- package/package.json +60 -5
- package/.claude/settings.local.json +0 -127
- package/.cursorrules +0 -426
- package/.devin/wiki.json +0 -143
- package/.dockerignore +0 -80
- package/.env.example +0 -159
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -49
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -29
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -57
- package/.github/workflows/ci.yml +0 -185
- package/.github/workflows/codeql.yml +0 -57
- package/.github/workflows/docker-build-push.yml +0 -118
- package/.github/workflows/helm-release.yml +0 -113
- package/CLAUDE.md +0 -265
- package/CODE_OF_CONDUCT.md +0 -124
- package/CONTRIBUTING.md +0 -154
- package/Dockerfile +0 -73
- package/SECURITY.md +0 -107
- package/artifacthub-repo.yml +0 -4
- package/bun.lock +0 -1714
- package/bunfig.toml +0 -3
- package/charts/libredb-studio/.helmignore +0 -11
- package/charts/libredb-studio/Chart.lock +0 -6
- package/charts/libredb-studio/Chart.yaml +0 -50
- package/charts/libredb-studio/README.md +0 -206
- package/charts/libredb-studio/templates/NOTES.txt +0 -59
- package/charts/libredb-studio/templates/_helpers.tpl +0 -135
- package/charts/libredb-studio/templates/configmap.yaml +0 -37
- package/charts/libredb-studio/templates/deployment.yaml +0 -184
- package/charts/libredb-studio/templates/hpa.yaml +0 -32
- package/charts/libredb-studio/templates/ingress.yaml +0 -41
- package/charts/libredb-studio/templates/networkpolicy.yaml +0 -50
- package/charts/libredb-studio/templates/pdb.yaml +0 -18
- package/charts/libredb-studio/templates/pvc.yaml +0 -23
- package/charts/libredb-studio/templates/secret.yaml +0 -30
- package/charts/libredb-studio/templates/seed-configmap.yaml +0 -11
- package/charts/libredb-studio/templates/service.yaml +0 -22
- package/charts/libredb-studio/templates/serviceaccount.yaml +0 -13
- package/charts/libredb-studio/values.schema.json +0 -246
- package/charts/libredb-studio/values.yaml +0 -286
- package/components.json +0 -22
- package/conductor/code_styleguides/typescript.md +0 -43
- package/conductor/product-guidelines.md +0 -43
- package/conductor/product.md +0 -3
- package/conductor/setup_state.json +0 -1
- package/conductor/tech-stack.md +0 -39
- package/conductor/tracks/enhance_postgres_monitoring_20251227/metadata.json +0 -8
- package/conductor/tracks/enhance_postgres_monitoring_20251227/plan.md +0 -44
- package/conductor/tracks/enhance_postgres_monitoring_20251227/spec.md +0 -31
- package/conductor/tracks.md +0 -8
- package/conductor/workflow.md +0 -333
- package/database-compose.yml +0 -55
- package/docker/postgres-init/01-extensions.sql +0 -10
- package/docker/postgres-init/02-sample-data.sql +0 -585
- package/docker/postgres.yml +0 -68
- package/docker-compose.yml +0 -38
- package/docs/AI_PLAN.md +0 -74
- package/docs/API_DOCS.md +0 -875
- package/docs/ARCHITECTURE.md +0 -218
- package/docs/DATABASE_PROVIDERS.md +0 -358
- package/docs/FEATURES.md +0 -116
- package/docs/HELM_CHART.md +0 -252
- package/docs/LOGIN_PAGE.md +0 -178
- package/docs/MONACO_EDITOR_PERFORMANCE.md +0 -315
- package/docs/OIDC_ARCH.md +0 -681
- package/docs/OIDC_SETUP.md +0 -322
- package/docs/POSTGRES_METRICS.md +0 -516
- package/docs/QUERY_OPTIMIZATION.md +0 -370
- package/docs/SEED_CONNECTIONS.md +0 -468
- package/docs/SQL_ALIAS_COMPLETION.md +0 -190
- package/docs/STORAGE_ARCHITECTURE.md +0 -565
- package/docs/STORAGE_QUICK_SETUP.md +0 -419
- package/docs/TECHNICAL_PLAN.md +0 -36
- package/docs/THEMING.md +0 -345
- package/docs/adding-a-new-database-provider.md +0 -642
- package/docs/backlogs/000-PLATFORM_DATA_SYNC_DATABASE.md +0 -360
- package/docs/backlogs/001-INLINE_DATA_EDITING.md +0 -118
- package/docs/backlogs/002-DATA_IMPORT.md +0 -215
- package/docs/backlogs/003-QUERY_TIME_MACHINE.md +0 -183
- package/docs/backlogs/004-AI_DATA_STORYTELLER.md +0 -292
- package/docs/backlogs/005-QUERY_PLAYGROUND.md +0 -352
- package/docs/backlogs/006-DATA_MASKING.md +0 -418
- package/docs/enterprise-features.md +0 -718
- package/docs/kubernetes-helm-chart-artifacthub-plan.md +0 -803
- package/docs/medium-koyeb-article-en.md +0 -215
- package/docs/plans/test-plans.md +0 -445
- package/docs/releases/RELEASE.V0.3.0.md +0 -22
- package/docs/releases/RELEASE.V0.4.0.md +0 -154
- package/docs/releases/RELEASE.V0.5.0.md +0 -252
- package/docs/releases/RELEASE_v0.5.6.md +0 -145
- package/docs/releases/RELEASE_v0.6.1.md +0 -303
- package/docs/releases/RELEASE_v0.6.7.md +0 -292
- package/docs/releases/RELEASE_v0.7.0.md +0 -332
- package/docs/releases/RELEASE_v0.8.0.md +0 -521
- package/docs/sampledb/titanic.sql +0 -1379
- package/docs/superpowers/plans/2026-03-25-seed-connections.md +0 -1362
- package/docs/superpowers/specs/2026-03-25-seed-connections-design.md +0 -590
- package/e2e/admin-dashboard.spec.ts +0 -64
- package/e2e/connection-management.spec.ts +0 -58
- package/e2e/export.spec.ts +0 -34
- package/e2e/login.spec.ts +0 -85
- package/e2e/query-execution.spec.ts +0 -35
- package/e2e/tab-management.spec.ts +0 -64
- package/eslint.config.mjs +0 -28
- package/fly.toml +0 -43
- package/next.config.ts +0 -32
- package/playwright.config.ts +0 -34
- package/postcss.config.mjs +0 -7
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/file.svg +0 -1
- package/public/globe.svg +0 -1
- package/public/logo.svg +0 -32
- package/public/next.svg +0 -1
- 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 +0 -1
- package/public/window.svg +0 -1
- package/render.yaml +0 -58
- package/scripts/merge-lcov.mjs +0 -239
- package/sonar-project.properties +0 -16
- package/src/app/admin/error.tsx +0 -46
- package/src/app/admin/page.tsx +0 -10
- package/src/app/api/admin/audit/route.ts +0 -52
- package/src/app/api/admin/fleet-health/route.ts +0 -81
- package/src/app/api/ai/autopilot/route.ts +0 -105
- package/src/app/api/ai/chat/route.ts +0 -132
- package/src/app/api/ai/describe-schema/route.ts +0 -52
- package/src/app/api/ai/explain/route.ts +0 -86
- package/src/app/api/ai/impact/route.ts +0 -97
- package/src/app/api/ai/index-advisor/route.ts +0 -98
- package/src/app/api/ai/nl2sql/route.ts +0 -87
- package/src/app/api/ai/query-safety/route.ts +0 -87
- package/src/app/api/auth/login/route.ts +0 -62
- package/src/app/api/auth/logout/route.ts +0 -25
- package/src/app/api/auth/me/route.ts +0 -10
- package/src/app/api/auth/oidc/callback/route.ts +0 -82
- package/src/app/api/auth/oidc/login/route.ts +0 -43
- package/src/app/api/connections/managed/route.ts +0 -35
- package/src/app/api/db/cancel/route.ts +0 -42
- package/src/app/api/db/disconnect/route.ts +0 -28
- package/src/app/api/db/health/route.ts +0 -49
- package/src/app/api/db/maintenance/route.ts +0 -72
- package/src/app/api/db/monitoring/route.ts +0 -62
- package/src/app/api/db/multi-query/route.ts +0 -116
- package/src/app/api/db/pool-stats/route.ts +0 -37
- package/src/app/api/db/profile/route.ts +0 -144
- package/src/app/api/db/provider-meta/route.ts +0 -49
- package/src/app/api/db/query/route.ts +0 -50
- package/src/app/api/db/schema/route.ts +0 -47
- package/src/app/api/db/schema-snapshot/route.ts +0 -42
- package/src/app/api/db/test-connection/route.ts +0 -55
- package/src/app/api/db/transaction/route.ts +0 -111
- package/src/app/api/storage/[collection]/route.ts +0 -67
- package/src/app/api/storage/config/route.ts +0 -17
- package/src/app/api/storage/migrate/route.ts +0 -45
- package/src/app/api/storage/route.ts +0 -32
- package/src/app/error.tsx +0 -49
- package/src/app/global-error.tsx +0 -55
- package/src/app/globals.css +0 -146
- package/src/app/icon.svg +0 -42
- package/src/app/layout.tsx +0 -34
- package/src/app/login/login-form.tsx +0 -301
- package/src/app/login/page.tsx +0 -11
- package/src/app/monitoring/page.tsx +0 -8
- package/src/app/not-found.tsx +0 -29
- package/src/app/page.tsx +0 -5
- package/src/components/AIAutopilotPanel.tsx +0 -238
- package/src/components/CodeGenerator.tsx +0 -271
- package/src/components/CommandPalette.tsx +0 -227
- package/src/components/ConnectionModal.tsx +0 -759
- package/src/components/CreateTableModal.tsx +0 -281
- package/src/components/DataCharts.tsx +0 -962
- package/src/components/DataImportModal.tsx +0 -582
- package/src/components/DataProfiler.tsx +0 -335
- package/src/components/DatabaseDocs.tsx +0 -251
- package/src/components/MaskingSettings.tsx +0 -414
- package/src/components/MobileNav.tsx +0 -50
- package/src/components/NL2SQLPanel.tsx +0 -281
- package/src/components/PivotTable.tsx +0 -257
- package/src/components/QueryEditor.tsx +0 -760
- package/src/components/QueryHistory.tsx +0 -344
- package/src/components/QuerySafetyDialog.tsx +0 -290
- package/src/components/ResultsGrid.tsx +0 -644
- package/src/components/SaveQueryModal.tsx +0 -104
- package/src/components/SavedQueries.tsx +0 -128
- package/src/components/SchemaDiagram.tsx +0 -473
- package/src/components/SchemaDiff.tsx +0 -473
- package/src/components/SnapshotTimeline.tsx +0 -116
- package/src/components/Studio.tsx +0 -639
- package/src/components/TestDataGenerator.tsx +0 -261
- package/src/components/VisualExplain.tsx +0 -820
- package/src/components/admin/AdminDashboard.tsx +0 -163
- package/src/components/admin/tabs/AuditTab.tsx +0 -531
- package/src/components/admin/tabs/MonitoringEmbed.tsx +0 -11
- package/src/components/admin/tabs/OperationsTab.tsx +0 -646
- package/src/components/admin/tabs/OverviewTab.tsx +0 -1328
- package/src/components/admin/tabs/SecurityTab.tsx +0 -284
- package/src/components/community-section.tsx +0 -92
- package/src/components/icons/db-icons.tsx +0 -84
- package/src/components/libredb-logo.tsx +0 -61
- package/src/components/monitoring/MonitoringDashboard.tsx +0 -345
- package/src/components/monitoring/tabs/MetricChart.tsx +0 -82
- package/src/components/monitoring/tabs/OverviewTab.tsx +0 -263
- package/src/components/monitoring/tabs/PerformanceTab.tsx +0 -254
- package/src/components/monitoring/tabs/PoolTab.tsx +0 -174
- package/src/components/monitoring/tabs/QueriesTab.tsx +0 -287
- package/src/components/monitoring/tabs/SessionsTab.tsx +0 -316
- package/src/components/monitoring/tabs/StorageTab.tsx +0 -335
- package/src/components/monitoring/tabs/TablesTab.tsx +0 -300
- package/src/components/results-grid/ResultCard.tsx +0 -111
- package/src/components/results-grid/RowDetailSheet.tsx +0 -178
- package/src/components/results-grid/StatsBar.tsx +0 -201
- package/src/components/results-grid/index.ts +0 -1
- package/src/components/results-grid/utils.ts +0 -23
- package/src/components/schema-explorer/ColumnList.tsx +0 -53
- package/src/components/schema-explorer/SchemaExplorer.tsx +0 -182
- package/src/components/schema-explorer/TableItem.tsx +0 -210
- package/src/components/schema-explorer/index.ts +0 -1
- package/src/components/sidebar/ConnectionItem.tsx +0 -105
- package/src/components/sidebar/ConnectionsList.tsx +0 -62
- package/src/components/sidebar/Sidebar.tsx +0 -130
- package/src/components/sidebar/index.ts +0 -2
- package/src/components/studio/BottomPanel.tsx +0 -286
- package/src/components/studio/QueryToolbar.tsx +0 -180
- package/src/components/studio/StudioDesktopHeader.tsx +0 -114
- package/src/components/studio/StudioMobileHeader.tsx +0 -340
- package/src/components/studio/StudioTabBar.tsx +0 -82
- package/src/components/studio/index.ts +0 -5
- package/src/components/ui/accordion.tsx +0 -66
- package/src/components/ui/alert-dialog.tsx +0 -157
- package/src/components/ui/alert.tsx +0 -66
- package/src/components/ui/aspect-ratio.tsx +0 -11
- package/src/components/ui/avatar.tsx +0 -53
- package/src/components/ui/badge.tsx +0 -46
- package/src/components/ui/breadcrumb.tsx +0 -109
- package/src/components/ui/button-group.tsx +0 -83
- package/src/components/ui/button.tsx +0 -60
- package/src/components/ui/calendar.tsx +0 -216
- package/src/components/ui/card.tsx +0 -92
- package/src/components/ui/carousel.tsx +0 -241
- package/src/components/ui/chart.tsx +0 -357
- package/src/components/ui/checkbox.tsx +0 -32
- package/src/components/ui/collapsible.tsx +0 -33
- package/src/components/ui/command.tsx +0 -184
- package/src/components/ui/context-menu.tsx +0 -252
- package/src/components/ui/dialog.tsx +0 -143
- package/src/components/ui/drawer.tsx +0 -135
- package/src/components/ui/dropdown-menu.tsx +0 -257
- package/src/components/ui/empty.tsx +0 -104
- package/src/components/ui/field.tsx +0 -248
- package/src/components/ui/form.tsx +0 -167
- package/src/components/ui/hover-card.tsx +0 -44
- package/src/components/ui/input-group.tsx +0 -170
- package/src/components/ui/input-otp.tsx +0 -77
- package/src/components/ui/input.tsx +0 -21
- package/src/components/ui/item.tsx +0 -193
- package/src/components/ui/kbd.tsx +0 -28
- package/src/components/ui/label.tsx +0 -24
- package/src/components/ui/menubar.tsx +0 -276
- package/src/components/ui/navigation-menu.tsx +0 -168
- package/src/components/ui/pagination.tsx +0 -127
- package/src/components/ui/popover.tsx +0 -48
- package/src/components/ui/progress.tsx +0 -31
- package/src/components/ui/radio-group.tsx +0 -45
- package/src/components/ui/resizable.tsx +0 -56
- package/src/components/ui/scroll-area.tsx +0 -58
- package/src/components/ui/select.tsx +0 -187
- package/src/components/ui/separator.tsx +0 -28
- package/src/components/ui/sheet.tsx +0 -139
- package/src/components/ui/sidebar.tsx +0 -726
- package/src/components/ui/skeleton.tsx +0 -13
- package/src/components/ui/slider.tsx +0 -63
- package/src/components/ui/sonner.tsx +0 -40
- package/src/components/ui/spinner.tsx +0 -16
- package/src/components/ui/switch.tsx +0 -31
- package/src/components/ui/table.tsx +0 -116
- package/src/components/ui/tabs.tsx +0 -66
- package/src/components/ui/textarea.tsx +0 -18
- package/src/components/ui/toggle-group.tsx +0 -83
- package/src/components/ui/toggle.tsx +0 -47
- package/src/components/ui/tooltip.tsx +0 -61
- package/src/exports/components.ts +0 -15
- package/src/exports/index.ts +0 -4
- package/src/exports/providers.ts +0 -4
- package/src/exports/types.ts +0 -26
- package/src/hooks/use-ai-chat.ts +0 -182
- package/src/hooks/use-all-connections.ts +0 -66
- package/src/hooks/use-api-call.ts +0 -71
- package/src/hooks/use-auth.ts +0 -51
- package/src/hooks/use-connection-form.ts +0 -349
- package/src/hooks/use-connection-manager.ts +0 -169
- package/src/hooks/use-connection-payload.ts +0 -15
- package/src/hooks/use-inline-editing.ts +0 -109
- package/src/hooks/use-mobile.ts +0 -20
- package/src/hooks/use-monitoring-data.ts +0 -270
- package/src/hooks/use-provider-metadata.ts +0 -62
- package/src/hooks/use-query-execution.ts +0 -478
- package/src/hooks/use-storage-sync.ts +0 -259
- package/src/hooks/use-tab-manager.ts +0 -231
- package/src/hooks/use-toast.ts +0 -20
- package/src/hooks/use-transaction-control.ts +0 -64
- package/src/lib/api/error-codes.ts +0 -30
- package/src/lib/api/errors.ts +0 -236
- package/src/lib/api/with-error-handler.ts +0 -41
- package/src/lib/audit.ts +0 -105
- package/src/lib/auth.ts +0 -87
- package/src/lib/connection-string-parser.ts +0 -172
- package/src/lib/data-masking.ts +0 -385
- package/src/lib/db/base-provider.ts +0 -325
- package/src/lib/db/errors.ts +0 -317
- package/src/lib/db/factory.ts +0 -324
- package/src/lib/db/index.ts +0 -123
- package/src/lib/db/providers/document/index.ts +0 -6
- package/src/lib/db/providers/document/mongodb.ts +0 -992
- package/src/lib/db/providers/keyvalue/redis.ts +0 -554
- package/src/lib/db/providers/sql/index.ts +0 -11
- package/src/lib/db/providers/sql/sql-base.ts +0 -174
- package/src/lib/db/providers/sql/sqlite.ts +0 -721
- package/src/lib/db/types.ts +0 -437
- package/src/lib/db/utils/pool-manager.ts +0 -287
- package/src/lib/db/utils/query-limiter.ts +0 -239
- package/src/lib/db-ui-config.ts +0 -86
- package/src/lib/editor/mongodb-completions.ts +0 -172
- package/src/lib/editor/sql-completions.ts +0 -280
- package/src/lib/llm/base-provider.ts +0 -117
- package/src/lib/llm/factory.ts +0 -102
- package/src/lib/llm/index.ts +0 -90
- package/src/lib/llm/providers/custom.ts +0 -181
- package/src/lib/llm/providers/gemini.ts +0 -126
- package/src/lib/llm/providers/ollama.ts +0 -154
- package/src/lib/llm/providers/openai.ts +0 -146
- package/src/lib/llm/types.ts +0 -173
- package/src/lib/llm/utils/config.ts +0 -187
- package/src/lib/llm/utils/retry.ts +0 -119
- package/src/lib/llm/utils/streaming.ts +0 -202
- package/src/lib/logger.ts +0 -127
- package/src/lib/monitoring-thresholds.ts +0 -44
- package/src/lib/oidc.ts +0 -262
- package/src/lib/query-generators.ts +0 -61
- package/src/lib/schema-diff/diff-engine.ts +0 -273
- package/src/lib/schema-diff/migration-generator.ts +0 -208
- package/src/lib/schema-diff/types.ts +0 -55
- package/src/lib/seed/config-loader.ts +0 -79
- package/src/lib/seed/connection-filter.ts +0 -49
- package/src/lib/seed/credential-resolver.ts +0 -62
- package/src/lib/seed/index.ts +0 -40
- package/src/lib/seed/resolve-connection.ts +0 -57
- package/src/lib/seed/types.ts +0 -69
- package/src/lib/sql/alias-extractor.ts +0 -267
- package/src/lib/sql/index.ts +0 -8
- package/src/lib/sql/statement-splitter.ts +0 -167
- package/src/lib/sql/types.ts +0 -40
- package/src/lib/ssh/tunnel.ts +0 -142
- package/src/lib/storage/factory.ts +0 -84
- package/src/lib/storage/index.ts +0 -14
- package/src/lib/storage/local-storage.ts +0 -99
- package/src/lib/storage/providers/postgres.ts +0 -225
- package/src/lib/storage/providers/sqlite.ts +0 -153
- package/src/lib/storage/storage-facade.ts +0 -272
- package/src/lib/storage/types.ts +0 -75
- package/src/lib/time-series-buffer.ts +0 -58
- package/src/lib/types.ts +0 -173
- package/src/lib/utils.ts +0 -6
- package/src/proxy.ts +0 -104
- package/src/types/db-drivers.d.ts +0 -23
- package/src/types/html2canvas.d.ts +0 -9
- package/tests/api/admin/audit.test.ts +0 -178
- package/tests/api/admin/fleet-health.test.ts +0 -183
- package/tests/api/ai/autopilot.test.ts +0 -174
- package/tests/api/ai/chat.test.ts +0 -250
- package/tests/api/ai/describe-schema.test.ts +0 -266
- package/tests/api/ai/explain.test.ts +0 -199
- package/tests/api/ai/impact.test.ts +0 -168
- package/tests/api/ai/index-advisor.test.ts +0 -171
- package/tests/api/ai/nl2sql.test.ts +0 -202
- package/tests/api/ai/query-safety.test.ts +0 -196
- package/tests/api/auth/login.test.ts +0 -170
- package/tests/api/auth/logout.test.ts +0 -140
- package/tests/api/auth/me.test.ts +0 -73
- package/tests/api/auth/oidc-callback.test.ts +0 -215
- package/tests/api/auth/oidc-login.test.ts +0 -127
- package/tests/api/db/cancel.test.ts +0 -198
- package/tests/api/db/disconnect.test.ts +0 -124
- package/tests/api/db/health.test.ts +0 -222
- package/tests/api/db/maintenance.test.ts +0 -263
- package/tests/api/db/monitoring.test.ts +0 -221
- package/tests/api/db/multi-query.test.ts +0 -316
- package/tests/api/db/pool-stats.test.ts +0 -135
- package/tests/api/db/profile.test.ts +0 -330
- package/tests/api/db/provider-meta.test.ts +0 -193
- package/tests/api/db/query.test.ts +0 -314
- package/tests/api/db/schema-snapshot.test.ts +0 -170
- package/tests/api/db/schema.test.ts +0 -191
- package/tests/api/db/test-connection.test.ts +0 -185
- package/tests/api/db/transaction.test.ts +0 -314
- package/tests/api/proxy.test.ts +0 -191
- package/tests/api/seed/managed-route.test.ts +0 -113
- package/tests/api/storage/config.test.ts +0 -42
- package/tests/api/storage/storage-routes.test.ts +0 -309
- package/tests/components/AIAutopilotPanel.test.tsx +0 -756
- package/tests/components/AdminPage.test.tsx +0 -33
- package/tests/components/CodeGenerator.test.tsx +0 -182
- package/tests/components/CommandPalette.test.tsx +0 -428
- package/tests/components/CommunitySection.test.tsx +0 -91
- package/tests/components/ConnectionModal.mobile.test.tsx +0 -284
- package/tests/components/ConnectionModal.test.tsx +0 -570
- package/tests/components/CreateTableModal.test.tsx +0 -383
- package/tests/components/DataCharts.test.tsx +0 -739
- package/tests/components/DataImportModal.test.tsx +0 -751
- package/tests/components/DataProfiler.test.tsx +0 -589
- package/tests/components/DatabaseDocs.test.tsx +0 -353
- package/tests/components/LoginPage.test.tsx +0 -163
- package/tests/components/LoginPageOIDC.test.tsx +0 -92
- package/tests/components/MaskingSettings.test.tsx +0 -498
- package/tests/components/MobileNav.test.tsx +0 -30
- package/tests/components/MonitoringPage.test.tsx +0 -32
- package/tests/components/NL2SQLPanel.test.tsx +0 -621
- package/tests/components/Page.test.tsx +0 -33
- package/tests/components/PivotTable.test.tsx +0 -350
- package/tests/components/QueryEditor.test.tsx +0 -1730
- package/tests/components/QueryHistory.test.tsx +0 -572
- package/tests/components/QuerySafetyDialog.test.tsx +0 -586
- package/tests/components/ResultsGrid.test.tsx +0 -804
- package/tests/components/RootLayout.test.tsx +0 -83
- package/tests/components/SaveQueryModal.test.tsx +0 -25
- package/tests/components/SavedQueries.test.tsx +0 -43
- package/tests/components/SchemaDiagram.test.tsx +0 -1034
- package/tests/components/SchemaDiff.test.tsx +0 -906
- package/tests/components/SnapshotTimeline.test.tsx +0 -174
- package/tests/components/Studio.test.tsx +0 -1030
- package/tests/components/TestDataGenerator.test.tsx +0 -291
- package/tests/components/VisualExplain.test.tsx +0 -704
- package/tests/components/admin/AdminDashboard.test.tsx +0 -205
- package/tests/components/admin/AuditTab.test.tsx +0 -220
- package/tests/components/admin/MonitoringEmbed.test.tsx +0 -58
- package/tests/components/admin/OperationsTab.test.tsx +0 -975
- package/tests/components/admin/OverviewTab.test.tsx +0 -254
- package/tests/components/admin/SecurityTab.test.tsx +0 -467
- package/tests/components/monitoring/MetricChart.test.tsx +0 -111
- package/tests/components/monitoring/MonitoringDashboard.test.tsx +0 -259
- package/tests/components/monitoring/OverviewTab.test.tsx +0 -78
- package/tests/components/monitoring/PerformanceTab.test.tsx +0 -87
- package/tests/components/monitoring/PoolTab.test.tsx +0 -42
- package/tests/components/monitoring/QueriesTab.test.tsx +0 -80
- package/tests/components/monitoring/SessionsTab.test.tsx +0 -154
- package/tests/components/monitoring/StorageTab.test.tsx +0 -127
- package/tests/components/monitoring/TablesTab.test.tsx +0 -153
- package/tests/components/results-grid/ResultCard.test.tsx +0 -105
- package/tests/components/results-grid/RowDetailSheet.test.tsx +0 -308
- package/tests/components/results-grid/StatsBar.test.tsx +0 -162
- package/tests/components/schema-explorer/ColumnList.test.tsx +0 -151
- package/tests/components/schema-explorer/SchemaExplorer.test.tsx +0 -461
- package/tests/components/schema-explorer/TableItem.test.tsx +0 -415
- package/tests/components/sidebar/ConnectionItem.test.tsx +0 -201
- package/tests/components/sidebar/ConnectionsList.test.tsx +0 -176
- package/tests/components/sidebar/Sidebar.test.tsx +0 -187
- package/tests/components/studio/BottomPanel.test.tsx +0 -383
- package/tests/components/studio/QueryToolbar.test.tsx +0 -321
- package/tests/components/studio/StudioDesktopHeader.test.tsx +0 -377
- package/tests/components/studio/StudioMobileHeader.test.tsx +0 -198
- package/tests/components/studio/StudioTabBar.test.tsx +0 -331
- package/tests/fixtures/connections.ts +0 -96
- package/tests/fixtures/masking-configs.ts +0 -86
- package/tests/fixtures/query-results.ts +0 -71
- package/tests/fixtures/schemas.ts +0 -64
- package/tests/fixtures/seed-connections/invalid-config.yaml +0 -7
- package/tests/fixtures/seed-connections/minimal-config.yaml +0 -8
- package/tests/fixtures/seed-connections/mixed-credentials.yaml +0 -23
- package/tests/fixtures/seed-connections/multi-role-config.yaml +0 -30
- package/tests/fixtures/seed-connections/valid-config.json +0 -15
- package/tests/fixtures/seed-connections/valid-config.yaml +0 -51
- package/tests/helpers/mock-fetch.ts +0 -59
- package/tests/helpers/mock-monaco.ts +0 -112
- package/tests/helpers/mock-navigation.ts +0 -28
- package/tests/helpers/mock-next.ts +0 -80
- package/tests/helpers/mock-provider.ts +0 -133
- package/tests/helpers/mock-sonner.ts +0 -29
- package/tests/helpers/render-with-providers.tsx +0 -19
- package/tests/hooks/use-ai-chat.test.ts +0 -600
- package/tests/hooks/use-auth.test.ts +0 -371
- package/tests/hooks/use-connection-form.test.ts +0 -743
- package/tests/hooks/use-connection-manager.test.ts +0 -466
- package/tests/hooks/use-inline-editing.test.ts +0 -321
- package/tests/hooks/use-mobile.test.ts +0 -177
- package/tests/hooks/use-monitoring-data.test.ts +0 -819
- package/tests/hooks/use-provider-metadata.test.ts +0 -228
- package/tests/hooks/use-query-execution.test.ts +0 -1212
- package/tests/hooks/use-tab-manager.test.ts +0 -756
- package/tests/hooks/use-toast.test.ts +0 -74
- package/tests/hooks/use-transaction-control.test.ts +0 -211
- package/tests/integration/db/mongodb-provider.test.ts +0 -698
- package/tests/integration/db/mssql-provider.test.ts +0 -840
- package/tests/integration/db/mysql-provider.test.ts +0 -872
- package/tests/integration/db/oracle-provider.test.ts +0 -843
- package/tests/integration/db/postgres-provider.test.ts +0 -1382
- package/tests/integration/db/redis-provider.test.ts +0 -526
- package/tests/integration/db/sqlite-provider.test.ts +0 -480
- package/tests/integration/seed/seed-pipeline.test.ts +0 -102
- package/tests/isolated/factory-singleton.test.ts +0 -150
- package/tests/isolated/use-storage-sync.test.ts +0 -389
- package/tests/run-components.sh +0 -196
- package/tests/setup-dom.ts +0 -58
- package/tests/setup.ts +0 -40
- package/tests/unit/api-errors.test.ts +0 -210
- package/tests/unit/code-generator-functions.test.ts +0 -271
- package/tests/unit/components/column-list.test.tsx +0 -190
- package/tests/unit/components/data-import-modal.test.tsx +0 -441
- package/tests/unit/components/studio-mobile-header.test.tsx +0 -327
- package/tests/unit/data-charts-functions.test.ts +0 -496
- package/tests/unit/data-import-functions.test.ts +0 -320
- package/tests/unit/data-import-utils.test.ts +0 -125
- package/tests/unit/db/base-provider.test.ts +0 -517
- package/tests/unit/db/errors.test.ts +0 -403
- package/tests/unit/db/factory.test.ts +0 -436
- package/tests/unit/db/pool-manager.test.ts +0 -440
- package/tests/unit/db/query-limiter.test.ts +0 -387
- package/tests/unit/db/sql-base.test.ts +0 -438
- package/tests/unit/lib/api/error-codes.test.ts +0 -39
- package/tests/unit/lib/audit.test.ts +0 -326
- package/tests/unit/lib/auth.test.ts +0 -146
- package/tests/unit/lib/connection-string-parser.test.ts +0 -424
- package/tests/unit/lib/data-masking.test.ts +0 -583
- package/tests/unit/lib/db-icons.test.tsx +0 -41
- package/tests/unit/lib/monitoring-thresholds.test.ts +0 -133
- package/tests/unit/lib/oidc.test.ts +0 -509
- package/tests/unit/lib/query-generators.test.ts +0 -127
- package/tests/unit/lib/storage/factory.test.ts +0 -71
- package/tests/unit/lib/storage/local-storage.test.ts +0 -114
- package/tests/unit/lib/storage/providers/postgres.test.ts +0 -312
- package/tests/unit/lib/storage/providers/sqlite.test.ts +0 -232
- package/tests/unit/lib/storage/storage-facade-extended.test.ts +0 -331
- package/tests/unit/lib/storage/storage-facade.test.ts +0 -184
- package/tests/unit/lib/storage.test.ts +0 -317
- package/tests/unit/lib/time-series-buffer.test.ts +0 -212
- package/tests/unit/lib/utils.test.ts +0 -24
- package/tests/unit/llm/base-provider.test.ts +0 -238
- package/tests/unit/llm/config.test.ts +0 -262
- package/tests/unit/llm/custom-provider.test.ts +0 -281
- package/tests/unit/llm/gemini-provider.test.ts +0 -248
- package/tests/unit/llm/llm-factory.test.ts +0 -155
- package/tests/unit/llm/ollama-provider.test.ts +0 -288
- package/tests/unit/llm/openai-provider.test.ts +0 -324
- package/tests/unit/llm/retry.test.ts +0 -180
- package/tests/unit/llm/streaming.test.ts +0 -355
- package/tests/unit/logger.test.ts +0 -198
- package/tests/unit/mongodb-completions.test.ts +0 -516
- package/tests/unit/pivot-table-functions.test.ts +0 -76
- package/tests/unit/query-cancelled-error.test.ts +0 -81
- package/tests/unit/schema-diff/diff-engine.test.ts +0 -367
- package/tests/unit/schema-diff/migration-generator.test.ts +0 -513
- package/tests/unit/seed/config-loader.test.ts +0 -73
- package/tests/unit/seed/connection-filter.test.ts +0 -91
- package/tests/unit/seed/credential-resolver.test.ts +0 -85
- package/tests/unit/seed/index.test.ts +0 -72
- package/tests/unit/seed/resolve-connection.test.ts +0 -74
- package/tests/unit/seed/types.test.ts +0 -129
- package/tests/unit/sql/alias-extractor.test.ts +0 -444
- package/tests/unit/sql/statement-splitter.test.ts +0 -348
- package/tests/unit/sql-completions.test.ts +0 -463
- package/tests/unit/ssh-tunnel.test.ts +0 -465
- package/tsconfig.json +0 -42
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// src/lib/api/error-codes.ts
|
|
2
|
+
var ApiErrorCode = {
|
|
3
|
+
// Database errors
|
|
4
|
+
QUERY_CANCELLED: "QUERY_CANCELLED",
|
|
5
|
+
QUERY_ERROR: "QUERY_ERROR",
|
|
6
|
+
CONFIG_ERROR: "CONFIG_ERROR",
|
|
7
|
+
AUTH_ERROR: "AUTH_ERROR",
|
|
8
|
+
TIMEOUT_ERROR: "TIMEOUT_ERROR",
|
|
9
|
+
CONNECTION_ERROR: "CONNECTION_ERROR",
|
|
10
|
+
POOL_EXHAUSTED: "POOL_EXHAUSTED"};
|
|
11
|
+
|
|
12
|
+
// src/lib/db/errors.ts
|
|
13
|
+
var DatabaseError = class _DatabaseError extends Error {
|
|
14
|
+
constructor(message, provider, code, query) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.provider = provider;
|
|
17
|
+
this.code = code;
|
|
18
|
+
this.query = query;
|
|
19
|
+
this.name = "DatabaseError";
|
|
20
|
+
Object.setPrototypeOf(this, _DatabaseError.prototype);
|
|
21
|
+
}
|
|
22
|
+
toJSON() {
|
|
23
|
+
return {
|
|
24
|
+
name: this.name,
|
|
25
|
+
message: this.message,
|
|
26
|
+
provider: this.provider,
|
|
27
|
+
code: this.code,
|
|
28
|
+
// Don't expose full query in production for security
|
|
29
|
+
query: this.query ? this.query.substring(0, 100) + "..." : void 0
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
var DatabaseConfigError = class _DatabaseConfigError extends DatabaseError {
|
|
34
|
+
constructor(message, provider) {
|
|
35
|
+
super(message, provider, ApiErrorCode.CONFIG_ERROR);
|
|
36
|
+
this.name = "DatabaseConfigError";
|
|
37
|
+
Object.setPrototypeOf(this, _DatabaseConfigError.prototype);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var ConnectionError = class _ConnectionError extends DatabaseError {
|
|
41
|
+
constructor(message, provider, host, port) {
|
|
42
|
+
super(message, provider, ApiErrorCode.CONNECTION_ERROR);
|
|
43
|
+
this.host = host;
|
|
44
|
+
this.port = port;
|
|
45
|
+
this.name = "ConnectionError";
|
|
46
|
+
Object.setPrototypeOf(this, _ConnectionError.prototype);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var AuthenticationError = class _AuthenticationError extends DatabaseError {
|
|
50
|
+
constructor(message, provider) {
|
|
51
|
+
super(message, provider, ApiErrorCode.AUTH_ERROR);
|
|
52
|
+
this.name = "AuthenticationError";
|
|
53
|
+
Object.setPrototypeOf(this, _AuthenticationError.prototype);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
var PoolExhaustedError = class _PoolExhaustedError extends DatabaseError {
|
|
57
|
+
constructor(message, provider, poolSize) {
|
|
58
|
+
super(message, provider, ApiErrorCode.POOL_EXHAUSTED);
|
|
59
|
+
this.poolSize = poolSize;
|
|
60
|
+
this.name = "PoolExhaustedError";
|
|
61
|
+
Object.setPrototypeOf(this, _PoolExhaustedError.prototype);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
var QueryError = class _QueryError extends DatabaseError {
|
|
65
|
+
constructor(message, provider, query, position, detail) {
|
|
66
|
+
super(message, provider, ApiErrorCode.QUERY_ERROR, query);
|
|
67
|
+
this.position = position;
|
|
68
|
+
this.detail = detail;
|
|
69
|
+
this.name = "QueryError";
|
|
70
|
+
Object.setPrototypeOf(this, _QueryError.prototype);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var TimeoutError = class _TimeoutError extends DatabaseError {
|
|
74
|
+
constructor(message, provider, timeout, query) {
|
|
75
|
+
super(message, provider, ApiErrorCode.TIMEOUT_ERROR, query);
|
|
76
|
+
this.timeout = timeout;
|
|
77
|
+
this.name = "TimeoutError";
|
|
78
|
+
Object.setPrototypeOf(this, _TimeoutError.prototype);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
var QueryCancelledError = class _QueryCancelledError extends DatabaseError {
|
|
82
|
+
constructor(message, provider, query) {
|
|
83
|
+
super(message, provider, ApiErrorCode.QUERY_CANCELLED, query);
|
|
84
|
+
this.name = "QueryCancelledError";
|
|
85
|
+
Object.setPrototypeOf(this, _QueryCancelledError.prototype);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
function isDatabaseError(error) {
|
|
89
|
+
return error instanceof DatabaseError;
|
|
90
|
+
}
|
|
91
|
+
function mapDatabaseError(error, provider, query) {
|
|
92
|
+
if (isDatabaseError(error)) {
|
|
93
|
+
return error;
|
|
94
|
+
}
|
|
95
|
+
if (!(error instanceof Error)) {
|
|
96
|
+
return new DatabaseError(String(error), provider);
|
|
97
|
+
}
|
|
98
|
+
const message = error.message.toLowerCase();
|
|
99
|
+
if (message.includes("econnrefused") || message.includes("connection refused") || message.includes("connect etimedout") || message.includes("getaddrinfo")) {
|
|
100
|
+
return new ConnectionError(
|
|
101
|
+
`Failed to connect to ${provider} database: ${error.message}`,
|
|
102
|
+
provider
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
if (message.includes("password") || message.includes("authentication") || message.includes("access denied") || message.includes("permission denied")) {
|
|
106
|
+
return new AuthenticationError(
|
|
107
|
+
`Authentication failed: ${error.message}`,
|
|
108
|
+
provider
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
if (message.includes("canceling statement") || message.includes("query execution was interrupted") || message.includes("query was cancelled") || message.includes("kill query")) {
|
|
112
|
+
return new QueryCancelledError(
|
|
113
|
+
"Query was cancelled",
|
|
114
|
+
provider,
|
|
115
|
+
query
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
if (message.includes("timeout") || message.includes("timed out")) {
|
|
119
|
+
return new TimeoutError(
|
|
120
|
+
`Query timeout: ${error.message}`,
|
|
121
|
+
provider,
|
|
122
|
+
void 0,
|
|
123
|
+
query
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
if (message.includes("ora-01017") || message.includes("invalid username/password")) {
|
|
127
|
+
return new AuthenticationError(`Authentication failed: ${error.message}`, provider);
|
|
128
|
+
}
|
|
129
|
+
if (message.includes("ora-12541") || message.includes("ora-12154") || message.includes("tns:")) {
|
|
130
|
+
return new ConnectionError(`Failed to connect to Oracle: ${error.message}`, provider);
|
|
131
|
+
}
|
|
132
|
+
if (message.includes("ora-00942")) {
|
|
133
|
+
return new QueryError(`Table or view does not exist: ${error.message}`, provider, query);
|
|
134
|
+
}
|
|
135
|
+
if (message.includes("login failed")) {
|
|
136
|
+
return new AuthenticationError(`Authentication failed: ${error.message}`, provider);
|
|
137
|
+
}
|
|
138
|
+
if (message.includes("cannot open database")) {
|
|
139
|
+
return new ConnectionError(`Database not found: ${error.message}`, provider);
|
|
140
|
+
}
|
|
141
|
+
if (message.includes("syntax error") || message.includes("column") || message.includes("relation")) {
|
|
142
|
+
return new QueryError(
|
|
143
|
+
error.message,
|
|
144
|
+
provider,
|
|
145
|
+
query,
|
|
146
|
+
error.position
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
if (message.includes("pool") || message.includes("too many connections")) {
|
|
150
|
+
return new PoolExhaustedError(
|
|
151
|
+
`Connection pool error: ${error.message}`,
|
|
152
|
+
provider
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
return new DatabaseError(error.message, provider, void 0, query);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export { ConnectionError, DatabaseConfigError, QueryError, mapDatabaseError };
|
|
159
|
+
//# sourceMappingURL=chunk-CZVV3JJB.mjs.map
|
|
160
|
+
//# sourceMappingURL=chunk-CZVV3JJB.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/api/error-codes.ts","../src/lib/db/errors.ts"],"names":[],"mappings":"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","file":"chunk-CZVV3JJB.mjs","sourcesContent":["/**\n * API Error Codes\n * Single source of truth for all error codes used across server and client\n */\n\nexport const ApiErrorCode = {\n // Database errors\n QUERY_CANCELLED: 'QUERY_CANCELLED',\n QUERY_ERROR: 'QUERY_ERROR',\n CONFIG_ERROR: 'CONFIG_ERROR',\n AUTH_ERROR: 'AUTH_ERROR',\n TIMEOUT_ERROR: 'TIMEOUT_ERROR',\n CONNECTION_ERROR: 'CONNECTION_ERROR',\n POOL_EXHAUSTED: 'POOL_EXHAUSTED',\n DATABASE_ERROR: 'DATABASE_ERROR',\n\n // LLM errors\n LLM_SAFETY: 'LLM_SAFETY',\n LLM_AUTH: 'LLM_AUTH',\n LLM_RATE_LIMIT: 'LLM_RATE_LIMIT',\n LLM_CONFIG: 'LLM_CONFIG',\n LLM_STREAM: 'LLM_STREAM',\n LLM_ERROR: 'LLM_ERROR',\n\n // Generic\n INTERNAL_ERROR: 'INTERNAL_ERROR',\n NETWORK_ERROR: 'NETWORK_ERROR',\n} as const;\n\nexport type ApiErrorCode = (typeof ApiErrorCode)[keyof typeof ApiErrorCode];\n","/**\n * Database Error Classes\n * Custom error types for database operations\n */\n\nimport type { DatabaseType } from './types';\nimport { ApiErrorCode } from '@/lib/api/error-codes';\n\n// ============================================================================\n// Base Database Error\n// ============================================================================\n\n/**\n * Base error class for all database-related errors\n */\nexport class DatabaseError extends Error {\n constructor(\n message: string,\n public readonly provider?: DatabaseType,\n public readonly code?: ApiErrorCode,\n public readonly query?: string\n ) {\n super(message);\n this.name = 'DatabaseError';\n Object.setPrototypeOf(this, DatabaseError.prototype);\n }\n\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n provider: this.provider,\n code: this.code,\n // Don't expose full query in production for security\n query: this.query ? this.query.substring(0, 100) + '...' : undefined,\n };\n }\n}\n\n// ============================================================================\n// Configuration Errors\n// ============================================================================\n\n/**\n * Configuration error - missing or invalid configuration\n */\nexport class DatabaseConfigError extends DatabaseError {\n constructor(message: string, provider?: DatabaseType) {\n super(message, provider, ApiErrorCode.CONFIG_ERROR);\n this.name = 'DatabaseConfigError';\n Object.setPrototypeOf(this, DatabaseConfigError.prototype);\n }\n}\n\n// ============================================================================\n// Connection Errors\n// ============================================================================\n\n/**\n * Connection error - failed to connect to database\n */\nexport class ConnectionError extends DatabaseError {\n constructor(\n message: string,\n provider?: DatabaseType,\n public readonly host?: string,\n public readonly port?: number\n ) {\n super(message, provider, ApiErrorCode.CONNECTION_ERROR);\n this.name = 'ConnectionError';\n Object.setPrototypeOf(this, ConnectionError.prototype);\n }\n}\n\n/**\n * Authentication error - invalid credentials\n */\nexport class AuthenticationError extends DatabaseError {\n constructor(message: string, provider?: DatabaseType) {\n super(message, provider, ApiErrorCode.AUTH_ERROR);\n this.name = 'AuthenticationError';\n Object.setPrototypeOf(this, AuthenticationError.prototype);\n }\n}\n\n/**\n * Pool exhausted error - no available connections in pool\n */\nexport class PoolExhaustedError extends DatabaseError {\n constructor(\n message: string,\n provider?: DatabaseType,\n public readonly poolSize?: number\n ) {\n super(message, provider, ApiErrorCode.POOL_EXHAUSTED);\n this.name = 'PoolExhaustedError';\n Object.setPrototypeOf(this, PoolExhaustedError.prototype);\n }\n}\n\n// ============================================================================\n// Query Errors\n// ============================================================================\n\n/**\n * Query error - SQL syntax or execution error\n */\nexport class QueryError extends DatabaseError {\n constructor(\n message: string,\n provider?: DatabaseType,\n query?: string,\n public readonly position?: number,\n public readonly detail?: string\n ) {\n super(message, provider, ApiErrorCode.QUERY_ERROR, query);\n this.name = 'QueryError';\n Object.setPrototypeOf(this, QueryError.prototype);\n }\n}\n\n/**\n * Timeout error - query or connection timeout\n */\nexport class TimeoutError extends DatabaseError {\n constructor(\n message: string,\n provider?: DatabaseType,\n public readonly timeout?: number,\n query?: string\n ) {\n super(message, provider, ApiErrorCode.TIMEOUT_ERROR, query);\n this.name = 'TimeoutError';\n Object.setPrototypeOf(this, TimeoutError.prototype);\n }\n}\n\n/**\n * Query cancelled error - user-initiated cancellation\n */\nexport class QueryCancelledError extends DatabaseError {\n constructor(message: string, provider?: DatabaseType, query?: string) {\n super(message, provider, ApiErrorCode.QUERY_CANCELLED, query);\n this.name = 'QueryCancelledError';\n Object.setPrototypeOf(this, QueryCancelledError.prototype);\n }\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\nexport function isDatabaseError(error: unknown): error is DatabaseError {\n return error instanceof DatabaseError;\n}\n\nexport function isConnectionError(error: unknown): error is ConnectionError {\n return error instanceof ConnectionError;\n}\n\nexport function isQueryError(error: unknown): error is QueryError {\n return error instanceof QueryError;\n}\n\nexport function isTimeoutError(error: unknown): error is TimeoutError {\n return error instanceof TimeoutError;\n}\n\nexport function isAuthenticationError(error: unknown): error is AuthenticationError {\n return error instanceof AuthenticationError;\n}\n\nexport function isQueryCancelledError(error: unknown): error is QueryCancelledError {\n return error instanceof QueryCancelledError;\n}\n\n// ============================================================================\n// Error Mapping Utilities\n// ============================================================================\n\n/**\n * Check if an error is retryable\n */\nexport function isRetryableError(error: unknown): boolean {\n if (!isDatabaseError(error)) {\n // Network errors are typically retryable\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return true;\n }\n return false;\n }\n\n // Auth and config errors are not retryable\n if (error instanceof AuthenticationError || error instanceof DatabaseConfigError) {\n return false;\n }\n\n // Query syntax errors are not retryable\n if (error instanceof QueryError && error.position !== undefined) {\n return false;\n }\n\n // Connection and timeout errors may be retryable\n return true;\n}\n\n/**\n * Map native database errors to our error types\n */\nexport function mapDatabaseError(\n error: unknown,\n provider: DatabaseType,\n query?: string\n): DatabaseError {\n if (isDatabaseError(error)) {\n return error;\n }\n\n if (!(error instanceof Error)) {\n return new DatabaseError(String(error), provider);\n }\n\n const message = error.message.toLowerCase();\n\n // Connection errors\n if (\n message.includes('econnrefused') ||\n message.includes('connection refused') ||\n message.includes('connect etimedout') ||\n message.includes('getaddrinfo')\n ) {\n return new ConnectionError(\n `Failed to connect to ${provider} database: ${error.message}`,\n provider\n );\n }\n\n // Authentication errors\n if (\n message.includes('password') ||\n message.includes('authentication') ||\n message.includes('access denied') ||\n message.includes('permission denied')\n ) {\n return new AuthenticationError(\n `Authentication failed: ${error.message}`,\n provider\n );\n }\n\n // Query cancellation (must check before timeout — 'canceling statement' is cancellation, not timeout)\n if (\n message.includes('canceling statement') ||\n message.includes('query execution was interrupted') ||\n message.includes('query was cancelled') ||\n message.includes('kill query')\n ) {\n return new QueryCancelledError(\n 'Query was cancelled',\n provider,\n query\n );\n }\n\n // Timeout errors\n if (\n message.includes('timeout') ||\n message.includes('timed out')\n ) {\n return new TimeoutError(\n `Query timeout: ${error.message}`,\n provider,\n undefined,\n query\n );\n }\n\n // Oracle errors\n if (message.includes('ora-01017') || message.includes('invalid username/password')) {\n return new AuthenticationError(`Authentication failed: ${error.message}`, provider);\n }\n if (message.includes('ora-12541') || message.includes('ora-12154') || message.includes('tns:')) {\n return new ConnectionError(`Failed to connect to Oracle: ${error.message}`, provider);\n }\n if (message.includes('ora-00942')) {\n return new QueryError(`Table or view does not exist: ${error.message}`, provider, query);\n }\n\n // MSSQL errors\n if (message.includes('login failed')) {\n return new AuthenticationError(`Authentication failed: ${error.message}`, provider);\n }\n if (message.includes('cannot open database')) {\n return new ConnectionError(`Database not found: ${error.message}`, provider);\n }\n\n // Query errors (PostgreSQL specific)\n if (message.includes('syntax error') || message.includes('column') || message.includes('relation')) {\n return new QueryError(\n error.message,\n provider,\n query,\n (error as { position?: number }).position\n );\n }\n\n // Pool errors\n if (message.includes('pool') || message.includes('too many connections')) {\n return new PoolExhaustedError(\n `Connection pool error: ${error.message}`,\n provider\n );\n }\n\n // Generic database error\n return new DatabaseError(error.message, provider, undefined, query);\n}\n"]}
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkRCQB4FCE_js = require('./chunk-RCQB4FCE.js');
|
|
4
|
+
var chunkVLCRUZX7_js = require('./chunk-VLCRUZX7.js');
|
|
5
|
+
var chunkJZO5KRZN_js = require('./chunk-JZO5KRZN.js');
|
|
6
|
+
var chunkQ6LRDBK7_js = require('./chunk-Q6LRDBK7.js');
|
|
7
|
+
var ssh2 = require('ssh2');
|
|
8
|
+
var net = require('net');
|
|
9
|
+
|
|
10
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
|
|
12
|
+
var net__default = /*#__PURE__*/_interopDefault(net);
|
|
13
|
+
|
|
14
|
+
var activeTunnels = /* @__PURE__ */ new Map();
|
|
15
|
+
async function createSSHTunnel(connectionId, sshConfig, remoteHost, remotePort) {
|
|
16
|
+
const existing = activeTunnels.get(connectionId);
|
|
17
|
+
if (existing) {
|
|
18
|
+
return existing;
|
|
19
|
+
}
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
const sshClient = new ssh2.Client();
|
|
22
|
+
let localServer = null;
|
|
23
|
+
const cleanup = async () => {
|
|
24
|
+
activeTunnels.delete(connectionId);
|
|
25
|
+
if (localServer) {
|
|
26
|
+
localServer.close();
|
|
27
|
+
localServer = null;
|
|
28
|
+
}
|
|
29
|
+
sshClient.end();
|
|
30
|
+
};
|
|
31
|
+
sshClient.on("ready", () => {
|
|
32
|
+
localServer = net__default.default.createServer((socket) => {
|
|
33
|
+
sshClient.forwardOut(
|
|
34
|
+
"127.0.0.1",
|
|
35
|
+
0,
|
|
36
|
+
remoteHost,
|
|
37
|
+
remotePort,
|
|
38
|
+
(err, stream) => {
|
|
39
|
+
if (err) {
|
|
40
|
+
socket.end();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
stream.on("error", () => {
|
|
44
|
+
socket.destroy();
|
|
45
|
+
});
|
|
46
|
+
socket.on("error", () => {
|
|
47
|
+
stream.close();
|
|
48
|
+
});
|
|
49
|
+
socket.pipe(stream).pipe(socket);
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
localServer.on("error", (err) => {
|
|
54
|
+
cleanup();
|
|
55
|
+
reject(new Error(`SSH tunnel local server error: ${err.message}`));
|
|
56
|
+
});
|
|
57
|
+
localServer.listen(0, "127.0.0.1", () => {
|
|
58
|
+
const address = localServer.address();
|
|
59
|
+
const tunnelInfo = {
|
|
60
|
+
localHost: "127.0.0.1",
|
|
61
|
+
localPort: address.port,
|
|
62
|
+
close: cleanup
|
|
63
|
+
};
|
|
64
|
+
activeTunnels.set(connectionId, tunnelInfo);
|
|
65
|
+
chunkVLCRUZX7_js.logger.info(`Tunnel created for ${connectionId}: 127.0.0.1:${address.port} -> ${remoteHost}:${remotePort}`, { connectionId });
|
|
66
|
+
resolve(tunnelInfo);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
sshClient.on("error", (err) => {
|
|
70
|
+
sshClient.end();
|
|
71
|
+
cleanup();
|
|
72
|
+
reject(new Error(`SSH connection error: ${err.message}`));
|
|
73
|
+
});
|
|
74
|
+
const connectOptions = {
|
|
75
|
+
host: sshConfig.host,
|
|
76
|
+
port: sshConfig.port || 22,
|
|
77
|
+
username: sshConfig.username
|
|
78
|
+
};
|
|
79
|
+
if (sshConfig.authMethod === "password") {
|
|
80
|
+
connectOptions.password = sshConfig.password;
|
|
81
|
+
} else if (sshConfig.authMethod === "privateKey") {
|
|
82
|
+
connectOptions.privateKey = sshConfig.privateKey;
|
|
83
|
+
if (sshConfig.passphrase) {
|
|
84
|
+
connectOptions.passphrase = sshConfig.passphrase;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
sshClient.connect(connectOptions);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async function closeSSHTunnel(connectionId) {
|
|
91
|
+
const tunnel = activeTunnels.get(connectionId);
|
|
92
|
+
if (tunnel) {
|
|
93
|
+
await tunnel.close();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/lib/db/factory.ts
|
|
98
|
+
async function createDatabaseProvider(connection, options = {}) {
|
|
99
|
+
const sanitize = (v) => v.replace(/[\r\n]/g, " ").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g, "");
|
|
100
|
+
console.log(`[DB] Creating ${sanitize(connection.type)} provider for "${sanitize(connection.name || "")}"`);
|
|
101
|
+
switch (connection.type) {
|
|
102
|
+
// SQL Databases - dynamically imported to reduce memory
|
|
103
|
+
case "postgres": {
|
|
104
|
+
const { PostgresProvider } = await import('./postgres-RLCWNFFX.js');
|
|
105
|
+
return new PostgresProvider(connection, options);
|
|
106
|
+
}
|
|
107
|
+
case "mysql": {
|
|
108
|
+
const { MySQLProvider } = await import('./mysql-Y3MSA5QY.js');
|
|
109
|
+
return new MySQLProvider(connection, options);
|
|
110
|
+
}
|
|
111
|
+
case "sqlite": {
|
|
112
|
+
const { SQLiteProvider } = await import('./sqlite-4I2P2OGQ.js');
|
|
113
|
+
return new SQLiteProvider(connection, options);
|
|
114
|
+
}
|
|
115
|
+
case "oracle": {
|
|
116
|
+
const { OracleProvider } = await import('./oracle-L6VEAVXO.js');
|
|
117
|
+
return new OracleProvider(connection, options);
|
|
118
|
+
}
|
|
119
|
+
case "mssql": {
|
|
120
|
+
const { MSSQLProvider } = await import('./mssql-PMOU4D36.js');
|
|
121
|
+
return new MSSQLProvider(connection, options);
|
|
122
|
+
}
|
|
123
|
+
// Document Databases - dynamically imported
|
|
124
|
+
case "mongodb": {
|
|
125
|
+
const { MongoDBProvider } = await import('./mongodb-YQJJTLX3.js');
|
|
126
|
+
return new MongoDBProvider(connection, options);
|
|
127
|
+
}
|
|
128
|
+
// Key-Value Stores - dynamically imported
|
|
129
|
+
case "redis": {
|
|
130
|
+
const { RedisProvider } = await import('./redis-QVQ6YU62.js');
|
|
131
|
+
return new RedisProvider(connection, options);
|
|
132
|
+
}
|
|
133
|
+
default:
|
|
134
|
+
throw new chunkJZO5KRZN_js.DatabaseConfigError(
|
|
135
|
+
`Unknown database type: ${connection.type}. Supported types: postgres, mysql, sqlite, oracle, mssql, mongodb, redis`,
|
|
136
|
+
connection.type
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
var providerCache = /* @__PURE__ */ new Map();
|
|
141
|
+
var IDLE_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
142
|
+
var SWEEP_INTERVAL_MS = 5 * 60 * 1e3;
|
|
143
|
+
var sweepTimer = null;
|
|
144
|
+
async function evictIdleProviders(maxIdleMs = IDLE_TIMEOUT_MS) {
|
|
145
|
+
const now = Date.now();
|
|
146
|
+
let evicted = 0;
|
|
147
|
+
for (const [id, entry] of providerCache) {
|
|
148
|
+
if (now - entry.lastUsed >= maxIdleMs) {
|
|
149
|
+
chunkVLCRUZX7_js.logger.info(`[DB] Evicting idle provider: ${id} (idle ${Math.round((now - entry.lastUsed) / 6e4)}min)`);
|
|
150
|
+
try {
|
|
151
|
+
await entry.provider.disconnect();
|
|
152
|
+
} catch (error) {
|
|
153
|
+
chunkVLCRUZX7_js.logger.warn(`[DB] Error disconnecting idle provider ${id}`, { connectionId: id, error: String(error) });
|
|
154
|
+
}
|
|
155
|
+
providerCache.delete(id);
|
|
156
|
+
try {
|
|
157
|
+
await closeSSHTunnel(id);
|
|
158
|
+
} catch (e) {
|
|
159
|
+
}
|
|
160
|
+
evicted++;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (providerCache.size === 0 && sweepTimer) {
|
|
164
|
+
clearInterval(sweepTimer);
|
|
165
|
+
sweepTimer = null;
|
|
166
|
+
}
|
|
167
|
+
return evicted;
|
|
168
|
+
}
|
|
169
|
+
function startIdleSweep() {
|
|
170
|
+
if (sweepTimer) return;
|
|
171
|
+
sweepTimer = setInterval(() => {
|
|
172
|
+
evictIdleProviders();
|
|
173
|
+
}, SWEEP_INTERVAL_MS);
|
|
174
|
+
if (sweepTimer && typeof sweepTimer === "object" && "unref" in sweepTimer) {
|
|
175
|
+
sweepTimer.unref();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
async function getOrCreateProvider(connection, options = {}) {
|
|
179
|
+
var _a;
|
|
180
|
+
const cacheKey = connection.id;
|
|
181
|
+
const cached = providerCache.get(cacheKey);
|
|
182
|
+
if (cached == null ? void 0 : cached.provider.isConnected()) {
|
|
183
|
+
cached.lastUsed = Date.now();
|
|
184
|
+
return cached.provider;
|
|
185
|
+
}
|
|
186
|
+
let effectiveConnection = connection;
|
|
187
|
+
let tunnel = null;
|
|
188
|
+
if (((_a = connection.sshTunnel) == null ? void 0 : _a.enabled) && connection.host && connection.port) {
|
|
189
|
+
tunnel = await createSSHTunnel(
|
|
190
|
+
connection.id,
|
|
191
|
+
connection.sshTunnel,
|
|
192
|
+
connection.host,
|
|
193
|
+
connection.port
|
|
194
|
+
);
|
|
195
|
+
effectiveConnection = chunkQ6LRDBK7_js.__spreadProps(chunkQ6LRDBK7_js.__spreadValues({}, connection), {
|
|
196
|
+
host: tunnel.localHost,
|
|
197
|
+
port: tunnel.localPort
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
const provider = await createDatabaseProvider(effectiveConnection, options);
|
|
201
|
+
try {
|
|
202
|
+
await provider.connect();
|
|
203
|
+
} catch (error) {
|
|
204
|
+
if (tunnel) {
|
|
205
|
+
await tunnel.close().catch(() => {
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
providerCache.set(cacheKey, { provider, lastUsed: Date.now() });
|
|
211
|
+
startIdleSweep();
|
|
212
|
+
return provider;
|
|
213
|
+
}
|
|
214
|
+
async function removeProvider(connectionId) {
|
|
215
|
+
const cached = providerCache.get(connectionId);
|
|
216
|
+
if (cached) {
|
|
217
|
+
try {
|
|
218
|
+
await cached.provider.disconnect();
|
|
219
|
+
} catch (error) {
|
|
220
|
+
chunkVLCRUZX7_js.logger.warn(`Error disconnecting provider ${connectionId}`, { connectionId, error: String(error) });
|
|
221
|
+
}
|
|
222
|
+
providerCache.delete(connectionId);
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
await closeSSHTunnel(connectionId);
|
|
226
|
+
} catch (error) {
|
|
227
|
+
chunkVLCRUZX7_js.logger.warn(`Error closing SSH tunnel for ${connectionId}`, { connectionId, error: String(error) });
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
async function clearProviderCache() {
|
|
231
|
+
if (sweepTimer) {
|
|
232
|
+
clearInterval(sweepTimer);
|
|
233
|
+
sweepTimer = null;
|
|
234
|
+
}
|
|
235
|
+
const disconnectPromises = [];
|
|
236
|
+
for (const [id, entry] of providerCache) {
|
|
237
|
+
disconnectPromises.push(
|
|
238
|
+
entry.provider.disconnect().catch((error) => {
|
|
239
|
+
console.error(`[DB] Error disconnecting provider ${id}:`, error);
|
|
240
|
+
})
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
await Promise.all(disconnectPromises);
|
|
244
|
+
providerCache.clear();
|
|
245
|
+
}
|
|
246
|
+
function getProviderCacheStats() {
|
|
247
|
+
return {
|
|
248
|
+
size: providerCache.size,
|
|
249
|
+
connections: Array.from(providerCache.keys())
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
var shutdownRegistered = false;
|
|
253
|
+
function registerShutdownHandlers() {
|
|
254
|
+
if (shutdownRegistered) return;
|
|
255
|
+
shutdownRegistered = true;
|
|
256
|
+
const shutdown = async (signal) => {
|
|
257
|
+
chunkVLCRUZX7_js.logger.info(`[DB] Received ${signal}, closing all database connections...`);
|
|
258
|
+
try {
|
|
259
|
+
await clearProviderCache();
|
|
260
|
+
chunkVLCRUZX7_js.logger.info("[DB] All database connections closed gracefully");
|
|
261
|
+
} catch (error) {
|
|
262
|
+
chunkVLCRUZX7_js.logger.error("[DB] Error during graceful shutdown", { error: String(error) });
|
|
263
|
+
}
|
|
264
|
+
process.exit(0);
|
|
265
|
+
};
|
|
266
|
+
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
267
|
+
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
268
|
+
}
|
|
269
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV !== "test") {
|
|
270
|
+
registerShutdownHandlers();
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// src/lib/llm/factory.ts
|
|
274
|
+
async function createLLMProvider(config) {
|
|
275
|
+
const resolvedConfig = chunkRCQB4FCE_js.resolveConfig(config);
|
|
276
|
+
const safeConfig = chunkRCQB4FCE_js.getSafeConfigForLogging(resolvedConfig);
|
|
277
|
+
console.log(`[LLM] Creating provider:`, safeConfig);
|
|
278
|
+
try {
|
|
279
|
+
switch (resolvedConfig.provider) {
|
|
280
|
+
case "gemini": {
|
|
281
|
+
const { GeminiProvider } = await import('./gemini-4ASHNK4H.js');
|
|
282
|
+
return new GeminiProvider(resolvedConfig);
|
|
283
|
+
}
|
|
284
|
+
case "openai": {
|
|
285
|
+
const { OpenAIProvider } = await import('./openai-AK3R37BS.js');
|
|
286
|
+
return new OpenAIProvider(resolvedConfig);
|
|
287
|
+
}
|
|
288
|
+
case "ollama": {
|
|
289
|
+
const { OllamaProvider } = await import('./ollama-HVWAGKQC.js');
|
|
290
|
+
return new OllamaProvider(resolvedConfig);
|
|
291
|
+
}
|
|
292
|
+
case "custom": {
|
|
293
|
+
const { CustomProvider } = await import('./custom-BNDOYC5P.js');
|
|
294
|
+
return new CustomProvider(resolvedConfig);
|
|
295
|
+
}
|
|
296
|
+
default:
|
|
297
|
+
throw new chunkRCQB4FCE_js.LLMConfigError(
|
|
298
|
+
`Unknown provider: ${resolvedConfig.provider}. Valid options: gemini, openai, ollama, custom`,
|
|
299
|
+
resolvedConfig.provider
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
} catch (error) {
|
|
303
|
+
if (error instanceof chunkRCQB4FCE_js.LLMConfigError) {
|
|
304
|
+
throw error;
|
|
305
|
+
}
|
|
306
|
+
throw new chunkRCQB4FCE_js.LLMConfigError(
|
|
307
|
+
`Failed to load ${resolvedConfig.provider} provider: ${error instanceof Error ? error.message : String(error)}`,
|
|
308
|
+
resolvedConfig.provider
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
var defaultProvider = null;
|
|
313
|
+
async function getDefaultProvider() {
|
|
314
|
+
if (!defaultProvider) {
|
|
315
|
+
defaultProvider = await createLLMProvider();
|
|
316
|
+
}
|
|
317
|
+
return defaultProvider;
|
|
318
|
+
}
|
|
319
|
+
function resetDefaultProvider() {
|
|
320
|
+
defaultProvider = null;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
exports.clearProviderCache = clearProviderCache;
|
|
324
|
+
exports.createDatabaseProvider = createDatabaseProvider;
|
|
325
|
+
exports.createLLMProvider = createLLMProvider;
|
|
326
|
+
exports.getDefaultProvider = getDefaultProvider;
|
|
327
|
+
exports.getOrCreateProvider = getOrCreateProvider;
|
|
328
|
+
exports.getProviderCacheStats = getProviderCacheStats;
|
|
329
|
+
exports.removeProvider = removeProvider;
|
|
330
|
+
exports.resetDefaultProvider = resetDefaultProvider;
|
|
331
|
+
//# sourceMappingURL=chunk-D4WVWWWF.js.map
|
|
332
|
+
//# sourceMappingURL=chunk-D4WVWWWF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/ssh/tunnel.ts","../src/lib/db/factory.ts","../src/lib/llm/factory.ts"],"names":["Client","net","logger","DatabaseConfigError","__spreadProps","resolveConfig","getSafeConfigForLogging","LLMConfigError"],"mappings":"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","file":"chunk-D4WVWWWF.js","sourcesContent":["/**\n * SSH Tunnel Manager\n * Creates SSH tunnels for database connections behind firewalls/bastion hosts.\n * Uses ssh2 library for tunnel creation.\n */\n\nimport { Client } from 'ssh2';\nimport net from 'net';\nimport type { SSHTunnelConfig } from '@/lib/types';\nimport { logger } from '@/lib/logger';\n\nexport interface TunnelInfo {\n localHost: string;\n localPort: number;\n close: () => Promise<void>;\n}\n\n// Cache active tunnels by connection ID\nconst activeTunnels = new Map<string, TunnelInfo>();\n\n/**\n * Create an SSH tunnel for a database connection.\n * Returns the local host/port to connect the database client to.\n */\nexport async function createSSHTunnel(\n connectionId: string,\n sshConfig: SSHTunnelConfig,\n remoteHost: string,\n remotePort: number\n): Promise<TunnelInfo> {\n // Return existing tunnel if already active\n // Note: cached tunnel may be stale if the SSH connection dropped silently.\n // Callers should handle connection errors and call closeSSHTunnel() to evict stale entries.\n const existing = activeTunnels.get(connectionId);\n if (existing) {\n return existing;\n }\n\n return new Promise((resolve, reject) => {\n const sshClient = new Client();\n let localServer: net.Server | null = null;\n\n const cleanup = async () => {\n activeTunnels.delete(connectionId);\n if (localServer) {\n localServer.close();\n localServer = null;\n }\n sshClient.end();\n };\n\n sshClient.on('ready', () => {\n // Create a local TCP server that forwards to the remote host through SSH\n localServer = net.createServer((socket) => {\n sshClient.forwardOut(\n '127.0.0.1',\n 0,\n remoteHost,\n remotePort,\n (err, stream) => {\n if (err) {\n socket.end();\n return;\n }\n // Prevent unhandled stream errors from crashing the process\n stream.on('error', () => { socket.destroy(); });\n socket.on('error', () => { stream.close(); });\n socket.pipe(stream).pipe(socket);\n }\n );\n });\n\n // Attach error handler before listen to catch bind/listen errors\n localServer.on('error', (err) => {\n cleanup();\n reject(new Error(`SSH tunnel local server error: ${err.message}`));\n });\n\n // Listen on a random available port\n localServer.listen(0, '127.0.0.1', () => {\n const address = localServer!.address() as net.AddressInfo;\n const tunnelInfo: TunnelInfo = {\n localHost: '127.0.0.1',\n localPort: address.port,\n close: cleanup,\n };\n activeTunnels.set(connectionId, tunnelInfo);\n logger.info(`Tunnel created for ${connectionId}: 127.0.0.1:${address.port} -> ${remoteHost}:${remotePort}`, { connectionId });\n resolve(tunnelInfo);\n });\n });\n\n sshClient.on('error', (err) => {\n // Ensure SSH file descriptors are released before rejecting\n sshClient.end();\n cleanup();\n reject(new Error(`SSH connection error: ${err.message}`));\n });\n\n // Build SSH connection options\n const connectOptions: Parameters<Client['connect']>[0] = {\n host: sshConfig.host,\n port: sshConfig.port || 22,\n username: sshConfig.username,\n };\n\n if (sshConfig.authMethod === 'password') {\n connectOptions.password = sshConfig.password;\n } else if (sshConfig.authMethod === 'privateKey') {\n connectOptions.privateKey = sshConfig.privateKey;\n if (sshConfig.passphrase) {\n connectOptions.passphrase = sshConfig.passphrase;\n }\n }\n\n sshClient.connect(connectOptions);\n });\n}\n\n/**\n * Close an SSH tunnel by connection ID\n */\nexport async function closeSSHTunnel(connectionId: string): Promise<void> {\n const tunnel = activeTunnels.get(connectionId);\n if (tunnel) {\n await tunnel.close();\n }\n}\n\n/**\n * Check if a tunnel exists for a connection\n */\nexport function hasTunnel(connectionId: string): boolean {\n return activeTunnels.has(connectionId);\n}\n\n/**\n * Get tunnel info for a connection\n */\nexport function getTunnelInfo(connectionId: string): TunnelInfo | undefined {\n return activeTunnels.get(connectionId);\n}\n","/**\n * Database Provider Factory\n * Creates appropriate provider instance based on connection type\n * Uses dynamic imports to reduce memory footprint - providers are loaded on demand\n */\n\nimport {\n type DatabaseProvider,\n type DatabaseConnection,\n type ProviderOptions,\n} from './types';\nimport { DatabaseConfigError } from './errors';\nimport { createSSHTunnel, closeSSHTunnel } from '@/lib/ssh/tunnel';\nimport { logger } from '@/lib/logger';\n\n// ============================================================================\n// Provider Factory\n// ============================================================================\n\n/**\n * Create a database provider based on connection configuration\n * Uses dynamic imports to load providers on-demand, reducing initial memory usage\n *\n * @param connection - Database connection configuration\n * @param options - Optional provider options (pooling, timeout, etc.)\n * @returns Promise<DatabaseProvider> instance\n * @throws DatabaseConfigError if connection type is not supported\n *\n * @example\n * // SQL Database\n * const provider = await createDatabaseProvider({\n * id: '1',\n * name: 'My PostgreSQL',\n * type: 'postgres',\n * host: 'localhost',\n * port: 5432,\n * database: 'mydb',\n * user: 'admin',\n * password: 'secret',\n * createdAt: new Date(),\n * });\n *\n * // MongoDB\n * const mongoProvider = await createDatabaseProvider({\n * id: '2',\n * name: 'My MongoDB',\n * type: 'mongodb',\n * connectionString: 'mongodb://localhost:27017/mydb',\n * createdAt: new Date(),\n * });\n *\n * await provider.connect();\n * const result = await provider.query('SELECT * FROM users');\n * await provider.disconnect();\n */\nexport async function createDatabaseProvider(\n connection: DatabaseConnection,\n options: ProviderOptions = {}\n): Promise<DatabaseProvider> {\n // Sanitize user-controlled values to prevent log injection\n const sanitize = (v: string) => v.replace(/[\\r\\n]/g, ' ').replace(/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/g, '');\n console.log(`[DB] Creating ${sanitize(connection.type)} provider for \"${sanitize(connection.name || '')}\"`);\n\n switch (connection.type) {\n // SQL Databases - dynamically imported to reduce memory\n case 'postgres': {\n const { PostgresProvider } = await import('./providers/sql/postgres');\n return new PostgresProvider(connection, options);\n }\n\n case 'mysql': {\n const { MySQLProvider } = await import('./providers/sql/mysql');\n return new MySQLProvider(connection, options);\n }\n\n case 'sqlite': {\n const { SQLiteProvider } = await import('./providers/sql/sqlite');\n return new SQLiteProvider(connection, options);\n }\n\n case 'oracle': {\n const { OracleProvider } = await import('./providers/sql/oracle');\n return new OracleProvider(connection, options);\n }\n\n case 'mssql': {\n const { MSSQLProvider } = await import('./providers/sql/mssql');\n return new MSSQLProvider(connection, options);\n }\n\n // Document Databases - dynamically imported\n case 'mongodb': {\n const { MongoDBProvider } = await import('./providers/document/mongodb');\n return new MongoDBProvider(connection, options);\n }\n\n // Key-Value Stores - dynamically imported\n case 'redis': {\n const { RedisProvider } = await import('./providers/keyvalue/redis');\n return new RedisProvider(connection, options);\n }\n\n default:\n throw new DatabaseConfigError(\n `Unknown database type: ${connection.type}. Supported types: postgres, mysql, sqlite, oracle, mssql, mongodb, redis`,\n connection.type\n );\n }\n}\n\n// ============================================================================\n// Provider Cache (for connection reuse)\n// ============================================================================\n\ninterface CachedProvider {\n provider: DatabaseProvider;\n lastUsed: number;\n}\n\nconst providerCache = new Map<string, CachedProvider>();\n\n/** Idle timeout: evict providers unused for 30 minutes */\nconst IDLE_TIMEOUT_MS = 30 * 60 * 1000;\n/** Sweep interval: check for idle providers every 5 minutes */\nconst SWEEP_INTERVAL_MS = 5 * 60 * 1000;\n\nlet sweepTimer: ReturnType<typeof setInterval> | null = null;\n\n/**\n * Evict providers that have been idle longer than maxIdleMs.\n * Called by the periodic sweep timer, but also exported for direct testing.\n *\n * @returns number of evicted providers\n */\nexport async function evictIdleProviders(maxIdleMs: number = IDLE_TIMEOUT_MS): Promise<number> {\n const now = Date.now();\n let evicted = 0;\n\n for (const [id, entry] of providerCache) {\n if (now - entry.lastUsed >= maxIdleMs) {\n logger.info(`[DB] Evicting idle provider: ${id} (idle ${Math.round((now - entry.lastUsed) / 60000)}min)`);\n try {\n await entry.provider.disconnect();\n } catch (error) {\n logger.warn(`[DB] Error disconnecting idle provider ${id}`, { connectionId: id, error: String(error) });\n }\n providerCache.delete(id);\n // Also close SSH tunnel\n try {\n await closeSSHTunnel(id);\n } catch { /* ignore */ }\n evicted++;\n }\n }\n\n // Stop sweeping if cache is empty\n if (providerCache.size === 0 && sweepTimer) {\n clearInterval(sweepTimer);\n sweepTimer = null;\n }\n\n return evicted;\n}\n\nfunction startIdleSweep(): void {\n if (sweepTimer) return;\n sweepTimer = setInterval(() => { evictIdleProviders(); }, SWEEP_INTERVAL_MS);\n // Allow process to exit even if timer is running\n if (sweepTimer && typeof sweepTimer === 'object' && 'unref' in sweepTimer) {\n sweepTimer.unref();\n }\n}\n\n/**\n * Get or create a database provider with caching\n * Useful for API routes to reuse connections\n *\n * @param connection - Database connection configuration\n * @param options - Optional provider options\n * @returns Cached or new DatabaseProvider instance\n */\nexport async function getOrCreateProvider(\n connection: DatabaseConnection,\n options: ProviderOptions = {}\n): Promise<DatabaseProvider> {\n const cacheKey = connection.id;\n\n // Check cache\n const cached = providerCache.get(cacheKey);\n\n if (cached?.provider.isConnected()) {\n cached.lastUsed = Date.now();\n return cached.provider;\n }\n\n // If SSH tunnel is configured, create tunnel first and rewrite connection\n let effectiveConnection = connection;\n let tunnel: Awaited<ReturnType<typeof createSSHTunnel>> | null = null;\n if (connection.sshTunnel?.enabled && connection.host && connection.port) {\n tunnel = await createSSHTunnel(\n connection.id,\n connection.sshTunnel,\n connection.host,\n connection.port\n );\n // Rewrite connection to point to local tunnel endpoint\n effectiveConnection = {\n ...connection,\n host: tunnel.localHost,\n port: tunnel.localPort,\n };\n }\n\n // Create new provider (async - dynamically loads the provider module)\n const provider = await createDatabaseProvider(effectiveConnection, options);\n try {\n await provider.connect();\n } catch (error) {\n // Clean up SSH tunnel if provider connect fails to prevent FD leak\n if (tunnel) {\n await tunnel.close().catch(() => {});\n }\n throw error;\n }\n\n // Cache it\n providerCache.set(cacheKey, { provider, lastUsed: Date.now() });\n\n // Start idle sweep if not already running\n startIdleSweep();\n\n return provider;\n}\n\n/**\n * Remove a provider from cache and disconnect\n */\nexport async function removeProvider(connectionId: string): Promise<void> {\n const cached = providerCache.get(connectionId);\n\n if (cached) {\n try {\n await cached.provider.disconnect();\n } catch (error) {\n logger.warn(`Error disconnecting provider ${connectionId}`, { connectionId, error: String(error) });\n }\n providerCache.delete(connectionId);\n }\n\n // Close SSH tunnel if exists\n try {\n await closeSSHTunnel(connectionId);\n } catch (error) {\n logger.warn(`Error closing SSH tunnel for ${connectionId}`, { connectionId, error: String(error) });\n }\n}\n\n/**\n * Clear all cached providers\n */\nexport async function clearProviderCache(): Promise<void> {\n // Stop idle sweep\n if (sweepTimer) {\n clearInterval(sweepTimer);\n sweepTimer = null;\n }\n\n const disconnectPromises: Promise<void>[] = [];\n\n for (const [id, entry] of providerCache) {\n disconnectPromises.push(\n entry.provider.disconnect().catch((error) => {\n console.error(`[DB] Error disconnecting provider ${id}:`, error);\n })\n );\n }\n\n await Promise.all(disconnectPromises);\n providerCache.clear();\n}\n\n/**\n * Get cache statistics\n */\nexport function getProviderCacheStats(): { size: number; connections: string[] } {\n return {\n size: providerCache.size,\n connections: Array.from(providerCache.keys()),\n };\n}\n\n// ============================================================================\n// Graceful Shutdown\n// ============================================================================\n\nlet shutdownRegistered = false;\n\n/**\n * Register process signal handlers for graceful shutdown.\n * Safe to call multiple times — handlers are only registered once.\n */\nexport function registerShutdownHandlers(): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n\n const shutdown = async (signal: string) => {\n logger.info(`[DB] Received ${signal}, closing all database connections...`);\n try {\n await clearProviderCache();\n logger.info('[DB] All database connections closed gracefully');\n } catch (error) {\n logger.error('[DB] Error during graceful shutdown', { error: String(error) });\n }\n process.exit(0);\n };\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n}\n\n// Auto-register on server-side (not during tests)\nif (typeof process !== 'undefined' && process.env.NODE_ENV !== 'test') {\n registerShutdownHandlers();\n}\n","/**\n * LLM Provider Factory\n * Creates appropriate provider instance based on configuration\n * Uses dynamic imports to reduce memory footprint - providers are loaded on demand\n */\n\nimport { type LLMConfig, type LLMProvider, LLMConfigError } from './types';\nimport { resolveConfig, getSafeConfigForLogging } from './utils/config';\n\n// ============================================================================\n// Provider Factory\n// ============================================================================\n\n/**\n * Create an LLM provider based on configuration\n * Uses dynamic imports to load providers on-demand, reducing initial memory usage\n *\n * @param config - Optional configuration overrides. If not provided,\n * configuration is resolved from environment variables.\n * @returns Promise<LLMProvider> instance\n * @throws LLMConfigError if configuration is invalid\n *\n * @example\n * // Use environment configuration\n * const provider = await createLLMProvider();\n *\n * @example\n * // Override specific settings\n * const provider = await createLLMProvider({\n * provider: 'openai',\n * model: 'gpt-4-turbo',\n * });\n */\nexport async function createLLMProvider(config?: Partial<LLMConfig>): Promise<LLMProvider> {\n const resolvedConfig = resolveConfig(config);\n\n // Log configuration (safely)\n const safeConfig = getSafeConfigForLogging(resolvedConfig);\n console.log(`[LLM] Creating provider:`, safeConfig);\n\n try {\n switch (resolvedConfig.provider) {\n case 'gemini': {\n const { GeminiProvider } = await import('./providers/gemini');\n return new GeminiProvider(resolvedConfig);\n }\n\n case 'openai': {\n const { OpenAIProvider } = await import('./providers/openai');\n return new OpenAIProvider(resolvedConfig);\n }\n\n case 'ollama': {\n const { OllamaProvider } = await import('./providers/ollama');\n return new OllamaProvider(resolvedConfig);\n }\n\n case 'custom': {\n const { CustomProvider } = await import('./providers/custom');\n return new CustomProvider(resolvedConfig);\n }\n\n default:\n throw new LLMConfigError(\n `Unknown provider: ${resolvedConfig.provider}. Valid options: gemini, openai, ollama, custom`,\n resolvedConfig.provider\n );\n }\n } catch (error) {\n if (error instanceof LLMConfigError) {\n throw error;\n }\n throw new LLMConfigError(\n `Failed to load ${resolvedConfig.provider} provider: ${error instanceof Error ? error.message : String(error)}`,\n resolvedConfig.provider\n );\n }\n}\n\n// ============================================================================\n// Singleton Instance (Optional)\n// ============================================================================\n\nlet defaultProvider: LLMProvider | null = null;\n\n/**\n * Get the default LLM provider instance (singleton)\n * Creates a new instance if one doesn't exist\n */\nexport async function getDefaultProvider(): Promise<LLMProvider> {\n if (!defaultProvider) {\n defaultProvider = await createLLMProvider();\n }\n return defaultProvider;\n}\n\n/**\n * Reset the default provider (useful for testing or config changes)\n */\nexport function resetDefaultProvider(): void {\n defaultProvider = null;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-DY3KXE44.mjs"}
|