@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 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/db/types.ts","../src/lib/db/utils/pool-manager.ts","../src/lib/db/base-provider.ts"],"names":["performance"],"mappings":";;;;AAsCO,IAAM,mBAAA,GAAkC;AAAA,EAC7C,GAAA,EAAK,CAAA;AAAA,EACL,GAAA,EAAK,EAAA;AAAA,EACL,WAAA,EAAa,GAAA;AAAA,EACb,cAAA,EAAgB;AAClB,CAAA;AAGO,IAAM,qBAAA,GAAwB,GAAA;;;ACC9B,SAAS,gBAAgB,MAAA,EAA0C;AACxE,EAAA,OAAO,kCACF,mBAAA,CAAA,EACA,MAAA,CAAA;AAEP;AAwNO,SAAS,YAAY,KAAA,EAAuB;AACjD,EAAA,IAAI,KAAA,KAAU,GAAG,OAAO,KAAA;AAExB,EAAA,MAAM,CAAA,GAAI,IAAA;AACV,EAAA,MAAM,QAAQ,CAAC,GAAA,EAAK,IAAA,EAAM,IAAA,EAAM,MAAM,IAAI,CAAA;AAC1C,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAC,CAAA;AAElD,EAAA,OAAO,CAAA,EAAG,UAAA,CAAA,CAAY,KAAA,GAAQ,IAAA,CAAK,IAAI,CAAA,EAAG,CAAC,CAAA,EAAG,OAAA,CAAQ,CAAC,CAAC,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AACvE;AAKO,SAAS,eAAe,EAAA,EAAoB;AACjD,EAAA,IAAI,EAAA,GAAK,GAAA,EAAM,OAAO,CAAA,EAAG,EAAE,CAAA,EAAA,CAAA;AAC3B,EAAA,IAAI,EAAA,GAAK,KAAO,OAAO,CAAA,EAAA,CAAI,KAAK,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA;AAChD,EAAA,IAAI,EAAA,GAAK,MAAS,OAAO,CAAA,EAAA,CAAI,KAAK,GAAA,EAAO,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA;AACnD,EAAA,OAAO,CAAA,EAAA,CAAI,EAAA,GAAK,IAAA,EAAS,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA;AACrC;;;ACvPO,IAAe,uBAAf,MAAgE;AAAA,EAS3D,WAAA,CACR,MAAA,EACA,OAAA,GAA2B,EAAC,EAC5B;AAnDJ,IAAA,IAAA,EAAA;AAoDI,IAAA,IAAA,CAAK,OAAO,MAAA,CAAO,IAAA;AACnB,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,IAAA,CAAK,UAAA,GAAa,eAAA,CAAgB,OAAA,CAAQ,IAAI,CAAA;AAC9C,IAAA,IAAA,CAAK,YAAA,GAAA,CAAe,EAAA,GAAA,OAAA,CAAQ,YAAA,KAAR,IAAA,GAAA,EAAA,GAAwB,qBAAA;AAC5C,IAAA,IAAA,CAAK,KAAA,GAAQ;AAAA,MACX,SAAA,EAAW,KAAA;AAAA,MACX,aAAA,EAAe;AAAA,KACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EA0BO,WAAA,GAAuB;AAC5B,IAAA,OAAO,KAAK,KAAA,CAAM,SAAA;AAAA,EACpB;AAAA,EAEA,MAAa,SAAA,GAA+B;AAC1C,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,SAAA,EAAU;AACpC,IAAA,OAAO,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU,MAAM,IAAI,CAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,iBAAA,CAAkB,OAAA,GAA6B,EAAC,EAA4B;AACvF,IAAA,MAAM;AAAA,MACJ,aAAA,GAAgB,IAAA;AAAA,MAChB,cAAA,GAAiB,IAAA;AAAA,MACjB,cAAA,GAAiB,IAAA;AAAA,MACjB,cAAA,GAAiB,EAAA;AAAA,MACjB,YAAA,GAAe,EAAA;AAAA,MACf;AAAA;AAAA,KACF,GAAI,OAAA;AAGJ,IAAA,MAAM,CAAC,UAAUA,YAAAA,EAAa,WAAA,EAAa,cAAc,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,MAC7E,KAAK,WAAA,EAAY;AAAA,MACjB,KAAK,qBAAA,EAAsB;AAAA,MAC3B,IAAA,CAAK,cAAA,CAAe,EAAE,KAAA,EAAO,gBAAgB,CAAA;AAAA,MAC7C,IAAA,CAAK,iBAAA,CAAkB,EAAE,KAAA,EAAO,cAAc;AAAA,KAC/C,CAAA;AAED,IAAA,MAAM,MAAA,GAAyB;AAAA,MAC7B,SAAA,sBAAe,IAAA,EAAK;AAAA,MACpB,QAAA;AAAA,MACA,WAAA,EAAAA,YAAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA,KACF;AAGA,IAAA,MAAM,mBAAoC,EAAC;AAE3C,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,gBAAA,CAAiB,IAAA;AAAA,QACf,IAAA,CAAK,cAAc,EAAE,MAAA,EAAQ,cAAc,CAAA,CAAE,IAAA,CAAK,CAAC,MAAA,KAAW;AAC5D,UAAA,MAAA,CAAO,MAAA,GAAS,MAAA;AAAA,QAClB,CAAC;AAAA,OACH;AAAA,IACF;AAEA,IAAA,IAAI,cAAA,EAAgB;AAClB,MAAA,gBAAA,CAAiB,IAAA;AAAA,QACf,IAAA,CAAK,cAAc,EAAE,MAAA,EAAQ,cAAc,CAAA,CAAE,IAAA,CAAK,CAAC,OAAA,KAAY;AAC7D,UAAA,MAAA,CAAO,OAAA,GAAU,OAAA;AAAA,QACnB,CAAC;AAAA,OACH;AAAA,IACF;AAEA,IAAA,IAAI,cAAA,EAAgB;AAClB,MAAA,gBAAA,CAAiB,IAAA;AAAA,QACf,IAAA,CAAK,eAAA,EAAgB,CAAE,IAAA,CAAK,CAAC,OAAA,KAAY;AACvC,UAAA,MAAA,CAAO,OAAA,GAAU,OAAA;AAAA,QACnB,CAAC;AAAA,OACH;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,CAAQ,IAAI,gBAAgB,CAAA;AAElC,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEO,QAAA,GAAiB;AACtB,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,EAAA,EAAI;AACnB,MAAA,MAAM,IAAI,mBAAA,CAAoB,2BAAA,EAA6B,IAAA,CAAK,IAAI,CAAA;AAAA,IACtE;AAEA,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM;AACrB,MAAA,MAAM,IAAI,mBAAA,CAAoB,2BAAA,EAA6B,IAAA,CAAK,IAAI,CAAA;AAAA,IACtE;AAAA,EAGF;AAAA;AAAA;AAAA;AAAA,EAMO,eAAA,GAAwC;AAC7C,IAAA,OAAO;AAAA,MACL,aAAA,EAAe,KAAA;AAAA,MACf,eAAA,EAAiB,IAAA;AAAA,MACjB,6BAAA,EAA+B,IAAA;AAAA,MAC/B,mBAAA,EAAqB,IAAA;AAAA,MACrB,mBAAA,EAAqB,IAAA;AAAA,MACrB,uBAAuB,CAAC,QAAA,EAAU,WAAW,SAAA,EAAW,MAAA,EAAQ,YAAY,OAAO,CAAA;AAAA,MACnF,wBAAA,EAA0B,KAAA;AAAA,MAC1B,WAAA,EAAa,IAAA;AAAA,MACb,oBAAA,EAAsB;AAAA,KACxB;AAAA,EACF;AAAA,EAEO,SAAA,GAA4B;AACjC,IAAA,OAAO;AAAA,MACL,UAAA,EAAY,OAAA;AAAA,MACZ,gBAAA,EAAkB,QAAA;AAAA,MAClB,OAAA,EAAS,KAAA;AAAA,MACT,aAAA,EAAe,MAAA;AAAA,MACf,YAAA,EAAc,gBAAA;AAAA,MACd,cAAA,EAAgB,gBAAA;AAAA,MAChB,aAAA,EAAe,eAAA;AAAA,MACf,YAAA,EAAc,cAAA;AAAA,MACd,iBAAA,EAAmB,6BAAA;AAAA,MACnB,kBAAA,EAAoB,aAAA;AAAA,MACpB,kBAAA,EAAoB,mBAAA;AAAA,MACpB,iBAAA,EAAmB,gGAAA;AAAA,MACnB,iBAAA,EAAmB,YAAA;AAAA,MACnB,iBAAA,EAAmB,eAAA;AAAA,MACnB,gBAAA,EAAkB;AAAA,KACpB;AAAA,EACF;AAAA,EAEO,YAAA,CAAa,KAAA,EAAe,OAAA,GAA+B,EAAC,EAAkB;AACnF,IAAA,OAAO,EAAE,KAAA,EAAO,UAAA,EAAY,KAAA,EAAO,KAAA,EAAO,OAAA,CAAQ,KAAA,IAAS,GAAA,EAAK,MAAA,EAAQ,OAAA,CAAQ,MAAA,IAAU,CAAA,EAAE;AAAA,EAC9F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASU,eAAA,GAAwB;AAChC,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,CAAM,SAAA,EAAW;AACzB,MAAA,MAAM,IAAI,mBAAA;AAAA,QACR,kDAAA;AAAA,QACA,IAAA,CAAK;AAAA,OACP;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,WAAc,EAAA,EAAkC;AAC9D,IAAA,IAAA,CAAK,KAAA,CAAM,aAAA,EAAA;AACX,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,EAAA,EAAG;AAAA,IAClB,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,KAAA,CAAM,aAAA,EAAA;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,iBACd,EAAA,EAC+C;AAC/C,IAAA,MAAM,SAAA,GAAY,YAAY,GAAA,EAAI;AAClC,IAAA,MAAM,MAAA,GAAS,MAAM,EAAA,EAAG;AACxB,IAAA,MAAM,gBAAgB,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,GAAA,KAAQ,SAAS,CAAA;AAC9D,IAAA,OAAO,EAAE,QAAQ,aAAA,EAAc;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKU,QAAA,CAAS,OAAgB,KAAA,EAAuB;AACxD,IAAA,OAAO,gBAAA,CAAiB,KAAA,EAAO,IAAA,CAAK,IAAA,EAAM,KAAK,CAAA;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKU,QAAA,CAAS,WAAmB,KAAA,EAAsB;AAC1D,IAAA,MAAM,eAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAE1E,IAAA,MAAM,QAAA,GAAW,CAAC,CAAA,KAAc,CAAA,CAAE,OAAA,CAAQ,WAAW,GAAG,CAAA,CAAE,OAAA,CAAQ,+BAAA,EAAiC,EAAE,CAAA;AACrG,IAAA,OAAA,CAAQ,KAAA;AAAA,MACN,CAAA,IAAA,EAAO,QAAA,CAAS,IAAA,CAAK,IAAI,CAAC,CAAA,EAAA,EAAK,QAAA,CAAS,SAAS,CAAC,CAAA,SAAA,EAAY,QAAA,CAAS,YAAY,CAAC,CAAA;AAAA,KACtF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKU,aAAA,GAAyC;AACjD,IAAA,OAAO;AAAA,MACL,EAAA,EAAI,KAAK,MAAA,CAAO,EAAA;AAAA,MAChB,IAAA,EAAM,KAAK,MAAA,CAAO,IAAA;AAAA,MAClB,IAAA,EAAM,KAAK,MAAA,CAAO,IAAA;AAAA,MAClB,IAAA,EAAM,KAAK,MAAA,CAAO,IAAA;AAAA,MAClB,IAAA,EAAM,KAAK,MAAA,CAAO,IAAA;AAAA,MAClB,QAAA,EAAU,KAAK,MAAA,CAAO,QAAA;AAAA,MACtB,IAAA,EAAM,KAAK,MAAA,CAAO;AAAA;AAAA,KAEpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKU,iBAAA,GAA4B;AACpC,IAAA,IAAI,IAAA,CAAK,OAAO,gBAAA,EAAkB;AAEhC,MAAA,OAAO,IAAA,CAAK,MAAA,CAAO,gBAAA,CAAiB,OAAA,CAAQ,cAAc,OAAO,CAAA;AAAA,IACnE;AACA,IAAA,OAAO,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA,CAAA;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA,EAKU,eAAe,EAAA,EAAoB;AAC3C,IAAA,OAAO,eAAe,EAAE,CAAA;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKU,aAAa,SAAA,EAA0B;AAC/C,IAAA,IAAA,CAAK,MAAM,SAAA,GAAY,SAAA;AACvB,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,IAAA,CAAK,KAAA,CAAM,aAAA,mBAAgB,IAAI,IAAA,EAAK;AACpC,MAAA,IAAA,CAAK,MAAM,SAAA,GAAY,MAAA;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKU,SAAS,KAAA,EAAoB;AACrC,IAAA,IAAA,CAAK,MAAM,SAAA,GAAY,KAAA;AACvB,IAAA,IAAA,CAAK,MAAM,SAAA,GAAY,KAAA;AAAA,EACzB;AACF","file":"chunk-QJP5FZRY.mjs","sourcesContent":["/**\n * Database Provider Types & Interfaces\n * Strategy Pattern implementation for multi-database support\n */\n\n// Re-export common types from main types file\nexport type {\n DatabaseType,\n DatabaseConnection,\n TableSchema,\n ColumnSchema,\n IndexSchema,\n ForeignKeySchema,\n QueryResult,\n} from '../types';\n\nimport type {\n DatabaseType,\n DatabaseConnection,\n TableSchema,\n QueryResult,\n} from '../types';\n\n// ============================================================================\n// Pool Configuration\n// ============================================================================\n\nexport interface PoolConfig {\n /** Minimum number of connections in pool (default: 2) */\n min: number;\n /** Maximum number of connections in pool (default: 10) */\n max: number;\n /** Close idle connections after this time in ms (default: 30000) */\n idleTimeout: number;\n /** Wait for connection timeout in ms (default: 60000) */\n acquireTimeout: number;\n}\n\nexport const DEFAULT_POOL_CONFIG: PoolConfig = {\n min: 2,\n max: 10,\n idleTimeout: 30000,\n acquireTimeout: 60000,\n};\n\n/** Query timeout in milliseconds (default: 60 seconds) */\nexport const DEFAULT_QUERY_TIMEOUT = 60000;\n\n// ============================================================================\n// Health Information\n// ============================================================================\n\nexport interface SlowQuery {\n query: string;\n calls: number;\n avgTime: string;\n}\n\nexport interface ActiveSession {\n pid: number | string;\n user: string;\n database: string;\n state: string;\n query: string;\n duration: string;\n}\n\nexport interface HealthInfo {\n activeConnections: number;\n databaseSize: string;\n cacheHitRatio: string;\n slowQueries: SlowQuery[];\n activeSessions: ActiveSession[];\n}\n\n// ============================================================================\n// Maintenance Operations\n// ============================================================================\n\nexport type MaintenanceType = 'vacuum' | 'analyze' | 'reindex' | 'kill' | 'optimize' | 'check';\n\nexport interface MaintenanceResult {\n success: boolean;\n executionTime: number;\n message: string;\n}\n\n// ============================================================================\n// Provider Capabilities & Labels\n// ============================================================================\n\nexport interface ProviderCapabilities {\n queryLanguage: 'sql' | 'json';\n supportsExplain: boolean;\n supportsExternalQueryLimiting: boolean;\n supportsCreateTable: boolean;\n supportsMaintenance: boolean;\n maintenanceOperations: MaintenanceType[];\n supportsConnectionString: boolean;\n defaultPort: number | null;\n schemaRefreshPattern: string;\n}\n\nexport interface ProviderLabels {\n entityName: string;\n entityNamePlural: string;\n rowName: string;\n rowNamePlural: string;\n selectAction: string;\n generateAction: string;\n analyzeAction: string;\n vacuumAction: string;\n searchPlaceholder: string;\n analyzeGlobalLabel: string;\n analyzeGlobalTitle: string;\n analyzeGlobalDesc: string;\n vacuumGlobalLabel: string;\n vacuumGlobalTitle: string;\n vacuumGlobalDesc: string;\n}\n\nexport interface PreparedQuery {\n query: string;\n wasLimited: boolean;\n limit: number;\n offset: number;\n}\n\nexport interface QueryPrepareOptions {\n limit?: number;\n offset?: number;\n unlimited?: boolean;\n}\n\n// ============================================================================\n// Provider Interface (Strategy Pattern)\n// ============================================================================\n\nexport interface DatabaseProvider {\n /** Database type identifier */\n readonly type: DatabaseType;\n\n /** Connection configuration */\n readonly config: DatabaseConnection;\n\n /**\n * Initialize connection pool or single connection\n */\n connect(): Promise<void>;\n\n /**\n * Close all connections and cleanup resources\n */\n disconnect(): Promise<void>;\n\n /**\n * Check if provider is currently connected\n */\n isConnected(): boolean;\n\n /**\n * Execute a SQL query\n * @param sql - SQL query string\n * @param params - Optional query parameters for prepared statements\n * @returns Query result with rows, fields, and execution time\n */\n query(sql: string, params?: unknown[]): Promise<QueryResult>;\n\n /**\n * Get full database schema\n * @returns Array of table schemas with columns, indexes, and foreign keys\n */\n getSchema(): Promise<TableSchema[]>;\n\n /**\n * Get list of table names\n */\n getTables(): Promise<string[]>;\n\n /**\n * Get health and performance metrics\n */\n getHealth(): Promise<HealthInfo>;\n\n /**\n * Get comprehensive monitoring data\n * @param options - What to include in the monitoring data\n */\n getMonitoringData(options?: MonitoringOptions): Promise<MonitoringData>;\n\n /**\n * Get database overview metrics\n */\n getOverview(): Promise<DatabaseOverview>;\n\n /**\n * Get performance metrics\n */\n getPerformanceMetrics(): Promise<PerformanceMetrics>;\n\n /**\n * Get slow query statistics\n * @param options - Query options (limit)\n */\n getSlowQueries(options?: { limit?: number }): Promise<SlowQueryStats[]>;\n\n /**\n * Get active sessions with details\n * @param options - Query options (limit)\n */\n getActiveSessions(options?: { limit?: number }): Promise<ActiveSessionDetails[]>;\n\n /**\n * Get table statistics\n * @param options - Query options (schema filter)\n */\n getTableStats(options?: { schema?: string }): Promise<TableStats[]>;\n\n /**\n * Get index statistics\n * @param options - Query options (schema filter)\n */\n getIndexStats(options?: { schema?: string }): Promise<IndexStats[]>;\n\n /**\n * Get storage/tablespace statistics\n */\n getStorageStats(): Promise<StorageStats[]>;\n\n /**\n * Run maintenance operations\n * @param type - Type of maintenance operation\n * @param target - Optional target (table name or process ID)\n */\n runMaintenance(type: MaintenanceType, target?: string): Promise<MaintenanceResult>;\n\n /**\n * Validate provider configuration\n * @throws DatabaseConfigError if configuration is invalid\n */\n validate(): void;\n\n /**\n * Get provider capabilities (query language, supported features, etc.)\n */\n getCapabilities(): ProviderCapabilities;\n\n /**\n * Get UI labels for this provider (entity names, action labels, etc.)\n */\n getLabels(): ProviderLabels;\n\n /**\n * Prepare a query for execution (apply limits, analyze query type, etc.)\n */\n prepareQuery(query: string, options?: QueryPrepareOptions): PreparedQuery;\n}\n\n// ============================================================================\n// Provider Configuration Options\n// ============================================================================\n\nexport interface ProviderOptions {\n /** Connection pool configuration */\n pool?: Partial<PoolConfig>;\n /** Query timeout in milliseconds */\n queryTimeout?: number;\n /** Enable SSL/TLS connection */\n ssl?: boolean | { rejectUnauthorized: boolean };\n /** Connection timezone */\n timezone?: string;\n}\n\n// ============================================================================\n// Internal Types\n// ============================================================================\n\nexport interface ConnectionState {\n connected: boolean;\n lastConnected?: Date;\n lastError?: Error;\n activeQueries: number;\n}\n\n// ============================================================================\n// Monitoring Types (Extended)\n// ============================================================================\n\n/**\n * Database overview metrics\n */\nexport interface DatabaseOverview {\n version: string;\n uptime: string;\n startTime?: Date;\n activeConnections: number;\n maxConnections: number;\n databaseSize: string;\n databaseSizeBytes: number;\n tableCount: number;\n indexCount: number;\n}\n\n/**\n * Performance metrics for the database\n */\nexport interface PerformanceMetrics {\n /** Cache hit ratio as percentage (0-100) */\n cacheHitRatio: number;\n /** Transactions per second */\n transactionsPerSecond?: number;\n /** Queries per second */\n queriesPerSecond?: number;\n /** Buffer pool usage as percentage (0-100) */\n bufferPoolUsage?: number;\n /** Number of deadlocks */\n deadlocks?: number;\n /** Checkpoint write time */\n checkpointWriteTime?: string;\n}\n\n/**\n * Slow query with detailed statistics\n */\nexport interface SlowQueryStats {\n queryId?: string;\n query: string;\n calls: number;\n totalTime: number;\n avgTime: number;\n minTime?: number;\n maxTime?: number;\n rows: number;\n sharedBlksHit?: number;\n sharedBlksRead?: number;\n}\n\n/**\n * Active session with detailed information\n */\nexport interface ActiveSessionDetails {\n pid: number | string;\n user: string;\n database: string;\n applicationName?: string;\n clientAddr?: string;\n state: string;\n query: string;\n queryStart?: Date;\n duration: string;\n durationMs: number;\n waitEventType?: string;\n waitEvent?: string;\n blocked?: boolean;\n}\n\n/**\n * Table statistics\n */\nexport interface TableStats {\n schemaName: string;\n tableName: string;\n rowCount: number;\n liveRowCount?: number;\n deadRowCount?: number;\n tableSize: string;\n tableSizeBytes: number;\n indexSize?: string;\n indexSizeBytes?: number;\n totalSize: string;\n totalSizeBytes: number;\n lastVacuum?: Date;\n lastAnalyze?: Date;\n bloatRatio?: number;\n}\n\n/**\n * Index statistics\n */\nexport interface IndexStats {\n schemaName: string;\n tableName: string;\n indexName: string;\n indexType?: string;\n columns: string[];\n isUnique: boolean;\n isPrimary: boolean;\n indexSize: string;\n indexSizeBytes: number;\n scans: number;\n usageRatio?: number;\n}\n\n/**\n * Storage statistics\n */\nexport interface StorageStats {\n name: string;\n location?: string;\n size: string;\n sizeBytes: number;\n usagePercent?: number;\n walSize?: string;\n walSizeBytes?: number;\n}\n\n/**\n * Comprehensive monitoring data combining all metrics\n */\nexport interface MonitoringData {\n timestamp: Date;\n overview: DatabaseOverview;\n performance: PerformanceMetrics;\n slowQueries: SlowQueryStats[];\n activeSessions: ActiveSessionDetails[];\n tables?: TableStats[];\n indexes?: IndexStats[];\n storage?: StorageStats[];\n}\n\n/**\n * Options for monitoring queries\n */\nexport interface MonitoringOptions {\n /** Include table statistics */\n includeTables?: boolean;\n /** Include index statistics */\n includeIndexes?: boolean;\n /** Include storage/tablespace info */\n includeStorage?: boolean;\n /** Limit for slow queries (default: 10) */\n slowQueryLimit?: number;\n /** Limit for active sessions (default: 50) */\n sessionLimit?: number;\n /** Schema filter (default: 'public' for PostgreSQL) */\n schemaFilter?: string;\n}\n","/**\n * Connection Pool Manager\n * Abstract pool management utilities for database providers\n */\n\nimport { type PoolConfig, DEFAULT_POOL_CONFIG, type DatabaseType } from '../types';\nimport { TimeoutError } from '../errors';\n\n// ============================================================================\n// Pool Statistics\n// ============================================================================\n\nexport interface PoolStats {\n /** Total connections in pool */\n total: number;\n /** Currently idle connections */\n idle: number;\n /** Currently active/busy connections */\n active: number;\n /** Connections waiting in queue */\n waiting: number;\n}\n\n// ============================================================================\n// Pool Manager Interface\n// ============================================================================\n\nexport interface PoolManager<T> {\n /** Acquire a connection from the pool */\n acquire(): Promise<T>;\n /** Release a connection back to the pool */\n release(connection: T): void;\n /** Get pool statistics */\n getStats(): PoolStats;\n /** Drain all connections and close pool */\n drain(): Promise<void>;\n /** Check if pool is healthy */\n isHealthy(): boolean;\n}\n\n// ============================================================================\n// Pool Configuration Utilities\n// ============================================================================\n\n/**\n * Merge user config with defaults\n */\nexport function mergePoolConfig(config?: Partial<PoolConfig>): PoolConfig {\n return {\n ...DEFAULT_POOL_CONFIG,\n ...config,\n };\n}\n\n/**\n * Validate pool configuration\n */\nexport function validatePoolConfig(config: PoolConfig): void {\n if (config.min < 0) {\n throw new Error('Pool min must be non-negative');\n }\n if (config.max < 1) {\n throw new Error('Pool max must be at least 1');\n }\n if (config.min > config.max) {\n throw new Error('Pool min cannot be greater than max');\n }\n if (config.idleTimeout < 0) {\n throw new Error('Pool idleTimeout must be non-negative');\n }\n if (config.acquireTimeout < 0) {\n throw new Error('Pool acquireTimeout must be non-negative');\n }\n}\n\n// ============================================================================\n// Timeout Utilities\n// ============================================================================\n\n/**\n * Execute a promise with timeout\n */\nexport async function withTimeout<T>(\n promise: Promise<T>,\n timeout: number,\n provider: DatabaseType,\n operation: string\n): Promise<T> {\n let timeoutId: NodeJS.Timeout;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new TimeoutError(\n `${operation} timed out after ${timeout}ms`,\n provider,\n timeout\n ));\n }, timeout);\n });\n\n try {\n const result = await Promise.race([promise, timeoutPromise]);\n clearTimeout(timeoutId!);\n return result;\n } catch (error) {\n clearTimeout(timeoutId!);\n throw error;\n }\n}\n\n/**\n * Create a cancellable query wrapper\n */\nexport function createCancellableQuery<T>(\n queryFn: (signal?: AbortSignal) => Promise<T>,\n timeout: number,\n provider: DatabaseType\n): { promise: Promise<T>; cancel: () => void } {\n const controller = new AbortController();\n let timeoutId: NodeJS.Timeout;\n\n const promise = new Promise<T>((resolve, reject) => {\n timeoutId = setTimeout(() => {\n controller.abort();\n reject(new TimeoutError(\n `Query timed out after ${timeout}ms`,\n provider,\n timeout\n ));\n }, timeout);\n\n queryFn(controller.signal)\n .then(resolve)\n .catch(reject)\n .finally(() => clearTimeout(timeoutId));\n });\n\n return {\n promise,\n cancel: () => {\n clearTimeout(timeoutId);\n controller.abort();\n },\n };\n}\n\n// ============================================================================\n// Connection Health Check\n// ============================================================================\n\n/**\n * Simple ping-like health check\n */\nexport async function checkConnectionHealth<T>(\n acquireFn: () => Promise<T>,\n releaseFn: (conn: T) => void,\n pingFn: (conn: T) => Promise<void>,\n timeout: number,\n provider: DatabaseType\n): Promise<boolean> {\n try {\n const conn = await withTimeout(\n acquireFn(),\n timeout,\n provider,\n 'Connection acquire'\n );\n\n try {\n await withTimeout(\n pingFn(conn),\n timeout,\n provider,\n 'Connection ping'\n );\n return true;\n } finally {\n releaseFn(conn);\n }\n } catch {\n return false;\n }\n}\n\n// ============================================================================\n// Retry Logic\n// ============================================================================\n\nexport interface RetryOptions {\n maxAttempts?: number;\n initialDelay?: number;\n maxDelay?: number;\n backoffMultiplier?: number;\n}\n\nconst DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {\n maxAttempts: 3,\n initialDelay: 1000,\n maxDelay: 10000,\n backoffMultiplier: 2,\n};\n\n/**\n * Execute with retry logic and exponential backoff\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {},\n isRetryable: (error: unknown) => boolean = () => true,\n provider?: DatabaseType\n): Promise<T> {\n const opts = { ...DEFAULT_RETRY_OPTIONS, ...options };\n let lastError: Error | undefined;\n let delay = opts.initialDelay;\n\n for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n if (!isRetryable(error) || attempt === opts.maxAttempts) {\n throw error;\n }\n\n console.error(\n `[DB${provider ? `:${provider}` : ''}] Operation failed (attempt ${attempt}/${opts.maxAttempts}): ${lastError.message}. Retrying in ${delay}ms...`\n );\n\n await sleep(delay);\n delay = Math.min(delay * opts.backoffMultiplier, opts.maxDelay);\n }\n }\n\n throw lastError;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// ============================================================================\n// SQL Utilities\n// ============================================================================\n\n/**\n * Escape SQL identifier (table name, column name)\n * Prevents SQL injection in dynamic queries\n */\nexport function escapeIdentifier(identifier: string, provider: DatabaseType): string {\n // Remove any existing quotes and escape internal quotes\n const cleaned = identifier.replace(/[\"'`]/g, '');\n\n switch (provider) {\n case 'postgres':\n return `\"${cleaned}\"`;\n case 'mysql':\n return `\\`${cleaned}\\``;\n case 'sqlite':\n return `\"${cleaned}\"`;\n default:\n return `\"${cleaned}\"`;\n }\n}\n\n/**\n * Format bytes to human readable size\n */\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;\n}\n\n/**\n * Format duration in milliseconds to human readable\n */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`;\n if (ms < 3600000) return `${(ms / 60000).toFixed(2)}m`;\n return `${(ms / 3600000).toFixed(2)}h`;\n}\n","/**\n * Base Database Provider\n * Abstract class implementing common provider functionality\n */\n\nimport {\n type DatabaseProvider,\n type DatabaseType,\n type DatabaseConnection,\n type TableSchema,\n type QueryResult,\n type HealthInfo,\n type MaintenanceType,\n type MaintenanceResult,\n type ProviderOptions,\n type PoolConfig,\n type ConnectionState,\n type MonitoringData,\n type MonitoringOptions,\n type DatabaseOverview,\n type PerformanceMetrics,\n type SlowQueryStats,\n type ActiveSessionDetails,\n type TableStats,\n type IndexStats,\n type StorageStats,\n type ProviderCapabilities,\n type ProviderLabels,\n type PreparedQuery,\n type QueryPrepareOptions,\n DEFAULT_QUERY_TIMEOUT,\n} from './types';\nimport { DatabaseConfigError, mapDatabaseError } from './errors';\nimport { mergePoolConfig, formatDuration } from './utils/pool-manager';\n\n// ============================================================================\n// Base Provider Class\n// ============================================================================\n\nexport abstract class BaseDatabaseProvider implements DatabaseProvider {\n public readonly type: DatabaseType;\n public readonly config: DatabaseConnection;\n\n protected readonly poolConfig: PoolConfig;\n protected readonly queryTimeout: number;\n protected readonly options: ProviderOptions;\n protected state: ConnectionState;\n\n protected constructor(\n config: DatabaseConnection,\n options: ProviderOptions = {}\n ) {\n this.type = config.type;\n this.config = config;\n this.options = options;\n this.poolConfig = mergePoolConfig(options.pool);\n this.queryTimeout = options.queryTimeout ?? DEFAULT_QUERY_TIMEOUT;\n this.state = {\n connected: false,\n activeQueries: 0,\n };\n }\n\n // ============================================================================\n // Abstract Methods (must be implemented by subclasses)\n // ============================================================================\n\n public abstract connect(): Promise<void>;\n public abstract disconnect(): Promise<void>;\n public abstract query(sql: string, params?: unknown[]): Promise<QueryResult>;\n public abstract getSchema(): Promise<TableSchema[]>;\n public abstract getHealth(): Promise<HealthInfo>;\n public abstract runMaintenance(type: MaintenanceType, target?: string): Promise<MaintenanceResult>;\n\n // Monitoring methods (must be implemented by subclasses)\n public abstract getOverview(): Promise<DatabaseOverview>;\n public abstract getPerformanceMetrics(): Promise<PerformanceMetrics>;\n public abstract getSlowQueries(options?: { limit?: number }): Promise<SlowQueryStats[]>;\n public abstract getActiveSessions(options?: { limit?: number }): Promise<ActiveSessionDetails[]>;\n public abstract getTableStats(options?: { schema?: string }): Promise<TableStats[]>;\n public abstract getIndexStats(options?: { schema?: string }): Promise<IndexStats[]>;\n public abstract getStorageStats(): Promise<StorageStats[]>;\n\n // ============================================================================\n // Common Implementations\n // ============================================================================\n\n public isConnected(): boolean {\n return this.state.connected;\n }\n\n public async getTables(): Promise<string[]> {\n const schema = await this.getSchema();\n return schema.map((table) => table.name);\n }\n\n /**\n * Get comprehensive monitoring data\n * This default implementation calls all monitoring methods in parallel\n * Subclasses can override for optimized implementations\n */\n public async getMonitoringData(options: MonitoringOptions = {}): Promise<MonitoringData> {\n const {\n includeTables = true,\n includeIndexes = true,\n includeStorage = true,\n slowQueryLimit = 10,\n sessionLimit = 50,\n schemaFilter, // undefined = all user schemas\n } = options;\n\n // Fetch core data in parallel\n const [overview, performance, slowQueries, activeSessions] = await Promise.all([\n this.getOverview(),\n this.getPerformanceMetrics(),\n this.getSlowQueries({ limit: slowQueryLimit }),\n this.getActiveSessions({ limit: sessionLimit }),\n ]);\n\n const result: MonitoringData = {\n timestamp: new Date(),\n overview,\n performance,\n slowQueries,\n activeSessions,\n };\n\n // Fetch optional data in parallel\n const optionalPromises: Promise<void>[] = [];\n\n if (includeTables) {\n optionalPromises.push(\n this.getTableStats({ schema: schemaFilter }).then((tables) => {\n result.tables = tables;\n })\n );\n }\n\n if (includeIndexes) {\n optionalPromises.push(\n this.getIndexStats({ schema: schemaFilter }).then((indexes) => {\n result.indexes = indexes;\n })\n );\n }\n\n if (includeStorage) {\n optionalPromises.push(\n this.getStorageStats().then((storage) => {\n result.storage = storage;\n })\n );\n }\n\n await Promise.all(optionalPromises);\n\n return result;\n }\n\n public validate(): void {\n if (!this.config.id) {\n throw new DatabaseConfigError('Connection ID is required', this.type);\n }\n\n if (!this.config.type) {\n throw new DatabaseConfigError('Database type is required', this.type);\n }\n\n // Subclasses should override for provider-specific validation\n }\n\n // ============================================================================\n // Provider Metadata (defaults — subclasses override)\n // ============================================================================\n\n public getCapabilities(): ProviderCapabilities {\n return {\n queryLanguage: 'sql',\n supportsExplain: true,\n supportsExternalQueryLimiting: true,\n supportsCreateTable: true,\n supportsMaintenance: true,\n maintenanceOperations: ['vacuum', 'analyze', 'reindex', 'kill', 'optimize', 'check'],\n supportsConnectionString: false,\n defaultPort: null,\n schemaRefreshPattern: '(CREATE|DROP|ALTER|TRUNCATE)\\\\b',\n };\n }\n\n public getLabels(): ProviderLabels {\n return {\n entityName: 'Table',\n entityNamePlural: 'Tables',\n rowName: 'row',\n rowNamePlural: 'rows',\n selectAction: 'Select Top 100',\n generateAction: 'Generate Query',\n analyzeAction: 'Analyze Table',\n vacuumAction: 'Vacuum Table',\n searchPlaceholder: 'Search tables or columns...',\n analyzeGlobalLabel: 'Run Analyze',\n analyzeGlobalTitle: 'Update Statistics',\n analyzeGlobalDesc: \"Updates the planner's statistics for all tables in the database to improve query optimization.\",\n vacuumGlobalLabel: 'Run Vacuum',\n vacuumGlobalTitle: 'Reclaim Space',\n vacuumGlobalDesc: 'Removes dead rows from tables and returns space to the operating system.',\n };\n }\n\n public prepareQuery(query: string, options: QueryPrepareOptions = {}): PreparedQuery {\n return { query, wasLimited: false, limit: options.limit || 500, offset: options.offset || 0 };\n }\n\n // ============================================================================\n // Protected Helpers\n // ============================================================================\n\n /**\n * Ensure provider is connected before operation\n */\n protected ensureConnected(): void {\n if (!this.state.connected) {\n throw new DatabaseConfigError(\n 'Provider is not connected. Call connect() first.',\n this.type\n );\n }\n }\n\n /**\n * Track active query count\n */\n protected async trackQuery<T>(fn: () => Promise<T>): Promise<T> {\n this.state.activeQueries++;\n try {\n return await fn();\n } finally {\n this.state.activeQueries--;\n }\n }\n\n /**\n * Measure query execution time\n */\n protected async measureExecution<T>(\n fn: () => Promise<T>\n ): Promise<{ result: T; executionTime: number }> {\n const startTime = performance.now();\n const result = await fn();\n const executionTime = Math.round(performance.now() - startTime);\n return { result, executionTime };\n }\n\n /**\n * Map native errors to DatabaseError\n */\n protected mapError(error: unknown, query?: string): Error {\n return mapDatabaseError(error, this.type, query);\n }\n\n /**\n * Log error with safe config\n */\n protected logError(operation: string, error: unknown): void {\n const errorMessage = error instanceof Error ? error.message : String(error);\n // Sanitize to prevent log injection via newlines/control chars\n const sanitize = (v: string) => v.replace(/[\\r\\n]/g, ' ').replace(/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/g, '');\n console.error(\n `[DB:${sanitize(this.type)}] ${sanitize(operation)} failed: ${sanitize(errorMessage)}`\n );\n }\n\n /**\n * Get config without sensitive data for logging\n */\n protected getSafeConfig(): Record<string, unknown> {\n return {\n id: this.config.id,\n name: this.config.name,\n type: this.config.type,\n host: this.config.host,\n port: this.config.port,\n database: this.config.database,\n user: this.config.user,\n // Never log password or connection string\n };\n }\n\n /**\n * Build connection info for health check\n */\n protected getConnectionInfo(): string {\n if (this.config.connectionString) {\n // Mask password in connection string\n return this.config.connectionString.replace(/:([^:@]+)@/, ':***@');\n }\n return `${this.config.host}:${this.config.port}/${this.config.database}`;\n }\n\n /**\n * Format duration for display\n */\n protected formatDuration(ms: number): string {\n return formatDuration(ms);\n }\n\n /**\n * Update connection state\n */\n protected setConnected(connected: boolean): void {\n this.state.connected = connected;\n if (connected) {\n this.state.lastConnected = new Date();\n this.state.lastError = undefined;\n }\n }\n\n /**\n * Record connection error\n */\n protected setError(error: Error): void {\n this.state.lastError = error;\n this.state.connected = false;\n }\n}\n"]}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { BaseDatabaseProvider } from './chunk-QJP5FZRY.mjs';
|
|
2
|
+
|
|
3
|
+
// src/lib/db/utils/query-limiter.ts
|
|
4
|
+
var DEFAULT_QUERY_LIMIT = 500;
|
|
5
|
+
var MAX_UNLIMITED_ROWS = 1e5;
|
|
6
|
+
function stripTrailingSemicolon(s) {
|
|
7
|
+
let end = s.length;
|
|
8
|
+
while (end > 0 && (s[end - 1] === " " || s[end - 1] === " " || s[end - 1] === "\n" || s[end - 1] === "\r")) end--;
|
|
9
|
+
while (end > 0 && s[end - 1] === ";") end--;
|
|
10
|
+
while (end > 0 && (s[end - 1] === " " || s[end - 1] === " " || s[end - 1] === "\n" || s[end - 1] === "\r")) end--;
|
|
11
|
+
return s.slice(0, end);
|
|
12
|
+
}
|
|
13
|
+
function analyzeQuery(sql) {
|
|
14
|
+
const trimmed = stripTrailingSemicolon(sql.trim());
|
|
15
|
+
const normalized = trimmed.replace(/\s+/g, " ").toUpperCase();
|
|
16
|
+
let type = "OTHER";
|
|
17
|
+
if (/^\s*SELECT\b/i.test(trimmed)) type = "SELECT";
|
|
18
|
+
else if (/^\s*INSERT\b/i.test(trimmed)) type = "INSERT";
|
|
19
|
+
else if (/^\s*UPDATE\b/i.test(trimmed)) type = "UPDATE";
|
|
20
|
+
else if (/^\s*DELETE\b/i.test(trimmed)) type = "DELETE";
|
|
21
|
+
else if (/^\s*(CREATE|ALTER|DROP|TRUNCATE)\b/i.test(trimmed)) type = "DDL";
|
|
22
|
+
else if (/^\s*WITH\b/i.test(trimmed) && /\bSELECT\b/i.test(trimmed)) {
|
|
23
|
+
type = "SELECT";
|
|
24
|
+
}
|
|
25
|
+
const limitMatch = trimmed.match(
|
|
26
|
+
/\bLIMIT\s+(\d+)(?:\s*,\s*(\d+)|\s+OFFSET\s+(\d+))?\s*$/i
|
|
27
|
+
);
|
|
28
|
+
let hasLimit = false;
|
|
29
|
+
let existingLimit;
|
|
30
|
+
let existingOffset;
|
|
31
|
+
if (limitMatch) {
|
|
32
|
+
hasLimit = true;
|
|
33
|
+
if (limitMatch[2] !== void 0) {
|
|
34
|
+
existingOffset = parseInt(limitMatch[1]);
|
|
35
|
+
existingLimit = parseInt(limitMatch[2]);
|
|
36
|
+
} else {
|
|
37
|
+
existingLimit = parseInt(limitMatch[1]);
|
|
38
|
+
existingOffset = limitMatch[3] ? parseInt(limitMatch[3]) : void 0;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!hasLimit) {
|
|
42
|
+
const fetchMatch = trimmed.match(/\bFETCH\s+(?:FIRST|NEXT)\s+(\d+)\s+ROWS?\s+ONLY\s*$/i);
|
|
43
|
+
if (fetchMatch) {
|
|
44
|
+
hasLimit = true;
|
|
45
|
+
existingLimit = parseInt(fetchMatch[1]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (!hasLimit) {
|
|
49
|
+
const topMatch = trimmed.match(/^\s*SELECT\s+TOP\s+(\d+)\b/i);
|
|
50
|
+
if (topMatch) {
|
|
51
|
+
hasLimit = true;
|
|
52
|
+
existingLimit = parseInt(topMatch[1]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!hasLimit && /\bROWNUM\s*<=?\s*\d+/i.test(normalized)) {
|
|
56
|
+
hasLimit = true;
|
|
57
|
+
}
|
|
58
|
+
const offsetOnlyMatch = !hasLimit && trimmed.match(/\bOFFSET\s+(\d+)\s*$/i);
|
|
59
|
+
const hasOffset = hasLimit ? existingOffset !== void 0 : !!offsetOnlyMatch;
|
|
60
|
+
if (offsetOnlyMatch && !hasLimit) {
|
|
61
|
+
existingOffset = parseInt(offsetOnlyMatch[1]);
|
|
62
|
+
}
|
|
63
|
+
const isUnion = /\bUNION\b/i.test(normalized);
|
|
64
|
+
const hasCTE = /^\s*WITH\b/i.test(trimmed);
|
|
65
|
+
const selectCount = (normalized.match(/\bSELECT\b/g) || []).length;
|
|
66
|
+
const hasSubquery = selectCount > 1;
|
|
67
|
+
return {
|
|
68
|
+
type,
|
|
69
|
+
hasLimit,
|
|
70
|
+
existingLimit,
|
|
71
|
+
hasOffset,
|
|
72
|
+
existingOffset,
|
|
73
|
+
isUnion,
|
|
74
|
+
hasCTE,
|
|
75
|
+
hasSubquery
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function applyQueryLimit(sql, limit, offset = 0, options = {}) {
|
|
79
|
+
const { forceLimit = false } = options;
|
|
80
|
+
const info = analyzeQuery(sql);
|
|
81
|
+
if (info.type !== "SELECT") {
|
|
82
|
+
return {
|
|
83
|
+
sql,
|
|
84
|
+
wasLimited: false,
|
|
85
|
+
appliedLimit: 0,
|
|
86
|
+
appliedOffset: 0
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (info.hasLimit && !forceLimit) {
|
|
90
|
+
return {
|
|
91
|
+
sql,
|
|
92
|
+
wasLimited: false,
|
|
93
|
+
originalLimit: info.existingLimit,
|
|
94
|
+
appliedLimit: info.existingLimit || 0,
|
|
95
|
+
appliedOffset: info.existingOffset || 0
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const trimmedInput = sql.trim();
|
|
99
|
+
let modifiedSql = stripTrailingSemicolon(trimmedInput);
|
|
100
|
+
const hasSemicolon = modifiedSql.length < trimmedInput.length && trimmedInput.includes(";");
|
|
101
|
+
if (info.hasLimit && forceLimit) {
|
|
102
|
+
modifiedSql = modifiedSql.replace(/\bLIMIT\s+\d+\s*,\s*\d+\s*$/i, "").trim();
|
|
103
|
+
modifiedSql = modifiedSql.replace(/\bLIMIT\s+\d+(?:\s+OFFSET\s+\d+)?\s*$/i, "").trim();
|
|
104
|
+
}
|
|
105
|
+
const limitClause = offset > 0 ? `LIMIT ${limit} OFFSET ${offset}` : `LIMIT ${limit}`;
|
|
106
|
+
modifiedSql = `${modifiedSql} ${limitClause}`;
|
|
107
|
+
if (hasSemicolon) {
|
|
108
|
+
modifiedSql += ";";
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
sql: modifiedSql,
|
|
112
|
+
wasLimited: true,
|
|
113
|
+
originalLimit: info.existingLimit,
|
|
114
|
+
appliedLimit: limit,
|
|
115
|
+
appliedOffset: offset
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/lib/db/providers/sql/sql-base.ts
|
|
120
|
+
var SQLBaseProvider = class extends BaseDatabaseProvider {
|
|
121
|
+
constructor(config, options = {}) {
|
|
122
|
+
super(config, options);
|
|
123
|
+
}
|
|
124
|
+
// ============================================================================
|
|
125
|
+
// SQL-Specific Utilities
|
|
126
|
+
// ============================================================================
|
|
127
|
+
/**
|
|
128
|
+
* Escape identifier based on SQL dialect
|
|
129
|
+
* PostgreSQL/SQLite: "identifier"
|
|
130
|
+
* MySQL: `identifier`
|
|
131
|
+
*/
|
|
132
|
+
escapeIdentifier(identifier) {
|
|
133
|
+
if (this.type === "mssql") {
|
|
134
|
+
const escaped2 = identifier.replace(/\]/g, "]]");
|
|
135
|
+
return `[${escaped2}]`;
|
|
136
|
+
}
|
|
137
|
+
const quoteChar = this.type === "mysql" ? "`" : '"';
|
|
138
|
+
const escaped = identifier.replace(
|
|
139
|
+
new RegExp(quoteChar, "g"),
|
|
140
|
+
quoteChar + quoteChar
|
|
141
|
+
);
|
|
142
|
+
return `${quoteChar}${escaped}${quoteChar}`;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Escape string value for SQL
|
|
146
|
+
*/
|
|
147
|
+
escapeString(value) {
|
|
148
|
+
return value.replace(/'/g, "''");
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Build LIMIT clause based on dialect
|
|
152
|
+
*/
|
|
153
|
+
buildLimitClause(limit, offset) {
|
|
154
|
+
if (offset !== void 0 && offset > 0) {
|
|
155
|
+
return `LIMIT ${limit} OFFSET ${offset}`;
|
|
156
|
+
}
|
|
157
|
+
return `LIMIT ${limit}`;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get placeholder style for parameterized queries
|
|
161
|
+
* PostgreSQL: $1, $2, $3
|
|
162
|
+
* MySQL/SQLite: ?, ?, ?
|
|
163
|
+
*/
|
|
164
|
+
getPlaceholder(index) {
|
|
165
|
+
if (this.type === "postgres") return `$${index}`;
|
|
166
|
+
if (this.type === "oracle") return `:${index}`;
|
|
167
|
+
if (this.type === "mssql") return `@p${index}`;
|
|
168
|
+
return "?";
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Determine if SSL should be enabled based on host
|
|
172
|
+
*/
|
|
173
|
+
shouldEnableSSL() {
|
|
174
|
+
var _a;
|
|
175
|
+
const host = ((_a = this.config.host) == null ? void 0 : _a.toLowerCase()) || "";
|
|
176
|
+
const cloudProviders = [
|
|
177
|
+
"supabase",
|
|
178
|
+
"render",
|
|
179
|
+
"neon",
|
|
180
|
+
"planetscale",
|
|
181
|
+
"aws",
|
|
182
|
+
"azure",
|
|
183
|
+
"gcp",
|
|
184
|
+
"cloud"
|
|
185
|
+
];
|
|
186
|
+
return this.options.ssl === true || cloudProviders.some((provider) => host.includes(provider));
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Get information schema name based on dialect
|
|
190
|
+
*/
|
|
191
|
+
getInformationSchemaName() {
|
|
192
|
+
return "information_schema";
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get default schema/database name for queries
|
|
196
|
+
*/
|
|
197
|
+
getDefaultSchema() {
|
|
198
|
+
var _a;
|
|
199
|
+
switch (this.type) {
|
|
200
|
+
case "postgres":
|
|
201
|
+
return "public";
|
|
202
|
+
case "mysql":
|
|
203
|
+
return this.config.database || "";
|
|
204
|
+
case "oracle":
|
|
205
|
+
return ((_a = this.config.user) == null ? void 0 : _a.toUpperCase()) || "";
|
|
206
|
+
case "mssql":
|
|
207
|
+
return "dbo";
|
|
208
|
+
default:
|
|
209
|
+
return "";
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Check if query is read-only (SELECT, SHOW, DESCRIBE, EXPLAIN)
|
|
214
|
+
*/
|
|
215
|
+
isReadOnlyQuery(sql) {
|
|
216
|
+
const trimmed = sql.trim().toLowerCase();
|
|
217
|
+
return trimmed.startsWith("select") || trimmed.startsWith("show") || trimmed.startsWith("describe") || trimmed.startsWith("explain") || trimmed.startsWith("pragma");
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Check if query modifies schema (CREATE, DROP, ALTER, TRUNCATE)
|
|
221
|
+
*/
|
|
222
|
+
isSchemaModifyingQuery(sql) {
|
|
223
|
+
const trimmed = sql.trim().toLowerCase();
|
|
224
|
+
return trimmed.startsWith("create") || trimmed.startsWith("drop") || trimmed.startsWith("alter") || trimmed.startsWith("truncate");
|
|
225
|
+
}
|
|
226
|
+
// ============================================================================
|
|
227
|
+
// Query Preparation (applies LIMIT for SELECT queries)
|
|
228
|
+
// ============================================================================
|
|
229
|
+
prepareQuery(query, options = {}) {
|
|
230
|
+
const { limit = DEFAULT_QUERY_LIMIT, offset = 0, unlimited = false } = options;
|
|
231
|
+
const effectiveLimit = unlimited ? MAX_UNLIMITED_ROWS : limit;
|
|
232
|
+
const queryInfo = analyzeQuery(query);
|
|
233
|
+
if (queryInfo.type === "SELECT") {
|
|
234
|
+
const limitResult = applyQueryLimit(query, effectiveLimit, offset);
|
|
235
|
+
return {
|
|
236
|
+
query: limitResult.sql,
|
|
237
|
+
wasLimited: limitResult.wasLimited,
|
|
238
|
+
limit: effectiveLimit,
|
|
239
|
+
offset
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
return { query, wasLimited: false, limit: effectiveLimit, offset };
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
export { DEFAULT_QUERY_LIMIT, MAX_UNLIMITED_ROWS, SQLBaseProvider, analyzeQuery };
|
|
247
|
+
//# sourceMappingURL=chunk-R3POCJK6.mjs.map
|
|
248
|
+
//# sourceMappingURL=chunk-R3POCJK6.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/db/utils/query-limiter.ts","../src/lib/db/providers/sql/sql-base.ts"],"names":["escaped"],"mappings":"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","file":"chunk-R3POCJK6.mjs","sourcesContent":["/**\n * Query Limiter Utility\n * SELECT sorgularına otomatik LIMIT ekleyerek büyük result set'lerin\n * sistemi kilitlemesini önler.\n */\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nexport const DEFAULT_QUERY_LIMIT = 500;\nexport const MAX_UNLIMITED_ROWS = 100000;\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface QueryLimitOptions {\n defaultLimit: number;\n maxUnlimited: number;\n forceLimit: boolean;\n}\n\nexport interface ParsedQueryInfo {\n type: 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE' | 'DDL' | 'OTHER';\n hasLimit: boolean;\n existingLimit?: number;\n hasOffset: boolean;\n existingOffset?: number;\n isUnion: boolean;\n hasCTE: boolean;\n hasSubquery: boolean;\n}\n\nexport interface LimitedQueryResult {\n sql: string;\n wasLimited: boolean;\n originalLimit?: number;\n appliedLimit: number;\n appliedOffset: number;\n}\n\n// ============================================================================\n// Query Analysis\n// ============================================================================\n\n/**\n * SQL sorgusunu analiz eder ve türünü, LIMIT/OFFSET durumunu belirler.\n */\n/** Strip trailing semicolons and whitespace without regex to avoid ReDoS */\nfunction stripTrailingSemicolon(s: string): string {\n let end = s.length;\n while (end > 0 && (s[end - 1] === ' ' || s[end - 1] === '\\t' || s[end - 1] === '\\n' || s[end - 1] === '\\r')) end--;\n while (end > 0 && s[end - 1] === ';') end--;\n while (end > 0 && (s[end - 1] === ' ' || s[end - 1] === '\\t' || s[end - 1] === '\\n' || s[end - 1] === '\\r')) end--;\n return s.slice(0, end);\n}\n\nexport function analyzeQuery(sql: string): ParsedQueryInfo {\n // Strip trailing whitespace and semicolons upfront to avoid ReDoS-prone patterns\n const trimmed = stripTrailingSemicolon(sql.trim());\n const normalized = trimmed.replace(/\\s+/g, ' ').toUpperCase();\n\n // Query type detection\n let type: ParsedQueryInfo['type'] = 'OTHER';\n if (/^\\s*SELECT\\b/i.test(trimmed)) type = 'SELECT';\n else if (/^\\s*INSERT\\b/i.test(trimmed)) type = 'INSERT';\n else if (/^\\s*UPDATE\\b/i.test(trimmed)) type = 'UPDATE';\n else if (/^\\s*DELETE\\b/i.test(trimmed)) type = 'DELETE';\n else if (/^\\s*(CREATE|ALTER|DROP|TRUNCATE)\\b/i.test(trimmed)) type = 'DDL';\n // CTE (WITH clause) that leads to SELECT\n else if (/^\\s*WITH\\b/i.test(trimmed) && /\\bSELECT\\b/i.test(trimmed)) {\n type = 'SELECT';\n }\n\n // LIMIT/OFFSET detection - en dıştaki sorgunun LIMIT'ini bul\n // Regex: Sorgunun sonundaki LIMIT [sayı] [OFFSET sayı] pattern'i\n const limitMatch = trimmed.match(\n /\\bLIMIT\\s+(\\d+)(?:\\s*,\\s*(\\d+)|\\s+OFFSET\\s+(\\d+))?\\s*$/i\n );\n\n let hasLimit = false;\n let existingLimit: number | undefined;\n let existingOffset: number | undefined;\n\n if (limitMatch) {\n hasLimit = true;\n // LIMIT x, y format (MySQL style) veya LIMIT x OFFSET y\n if (limitMatch[2] !== undefined) {\n // LIMIT offset, count (MySQL style)\n existingOffset = parseInt(limitMatch[1]);\n existingLimit = parseInt(limitMatch[2]);\n } else {\n existingLimit = parseInt(limitMatch[1]);\n existingOffset = limitMatch[3] ? parseInt(limitMatch[3]) : undefined;\n }\n }\n\n // Oracle/MSSQL: FETCH FIRST N ROWS ONLY / FETCH NEXT N ROWS ONLY\n if (!hasLimit) {\n const fetchMatch = trimmed.match(/\\bFETCH\\s+(?:FIRST|NEXT)\\s+(\\d+)\\s+ROWS?\\s+ONLY\\s*$/i);\n if (fetchMatch) {\n hasLimit = true;\n existingLimit = parseInt(fetchMatch[1]);\n }\n }\n\n // MSSQL: SELECT TOP N\n if (!hasLimit) {\n const topMatch = trimmed.match(/^\\s*SELECT\\s+TOP\\s+(\\d+)\\b/i);\n if (topMatch) {\n hasLimit = true;\n existingLimit = parseInt(topMatch[1]);\n }\n }\n\n // Oracle legacy: ROWNUM in WHERE clause\n if (!hasLimit && /\\bROWNUM\\s*<=?\\s*\\d+/i.test(normalized)) {\n hasLimit = true;\n }\n\n // OFFSET without LIMIT (rare but possible in PostgreSQL)\n const offsetOnlyMatch = !hasLimit && trimmed.match(/\\bOFFSET\\s+(\\d+)\\s*$/i);\n const hasOffset = hasLimit ? existingOffset !== undefined : !!offsetOnlyMatch;\n\n if (offsetOnlyMatch && !hasLimit) {\n existingOffset = parseInt(offsetOnlyMatch[1]);\n }\n\n // UNION detection\n const isUnion = /\\bUNION\\b/i.test(normalized);\n\n // CTE detection (WITH clause)\n const hasCTE = /^\\s*WITH\\b/i.test(trimmed);\n\n // Subquery detection (nested SELECT - birden fazla SELECT var mı)\n const selectCount = (normalized.match(/\\bSELECT\\b/g) || []).length;\n const hasSubquery = selectCount > 1;\n\n return {\n type,\n hasLimit,\n existingLimit,\n hasOffset,\n existingOffset,\n isUnion,\n hasCTE,\n hasSubquery,\n };\n}\n\n// ============================================================================\n// Query Limiting\n// ============================================================================\n\n/**\n * SELECT sorgusuna LIMIT ekler veya mevcut LIMIT'i günceller.\n */\nexport function applyQueryLimit(\n sql: string,\n limit: number,\n offset: number = 0,\n options: Partial<QueryLimitOptions> = {}\n): LimitedQueryResult {\n const { forceLimit = false } = options;\n const info = analyzeQuery(sql);\n\n // SELECT değilse, limit ekleme\n if (info.type !== 'SELECT') {\n return {\n sql,\n wasLimited: false,\n appliedLimit: 0,\n appliedOffset: 0,\n };\n }\n\n // Mevcut LIMIT varsa ve forceLimit false ise, mevcut limiti koru\n if (info.hasLimit && !forceLimit) {\n return {\n sql,\n wasLimited: false,\n originalLimit: info.existingLimit,\n appliedLimit: info.existingLimit || 0,\n appliedOffset: info.existingOffset || 0,\n };\n }\n\n // Check for trailing semicolon before stripping (string-based to avoid ReDoS)\n const trimmedInput = sql.trim();\n let modifiedSql = stripTrailingSemicolon(trimmedInput);\n const hasSemicolon = modifiedSql.length < trimmedInput.length && trimmedInput.includes(';');\n\n // Mevcut LIMIT/OFFSET'i kaldır (eğer forceLimit true ise)\n if (info.hasLimit && forceLimit) {\n // MySQL style: LIMIT offset, count\n modifiedSql = modifiedSql\n .replace(/\\bLIMIT\\s+\\d+\\s*,\\s*\\d+\\s*$/i, '')\n .trim();\n // Standard style: LIMIT count OFFSET offset\n modifiedSql = modifiedSql\n .replace(/\\bLIMIT\\s+\\d+(?:\\s+OFFSET\\s+\\d+)?\\s*$/i, '')\n .trim();\n }\n\n // LIMIT OFFSET clause'u ekle\n const limitClause =\n offset > 0 ? `LIMIT ${limit} OFFSET ${offset}` : `LIMIT ${limit}`;\n\n modifiedSql = `${modifiedSql} ${limitClause}`;\n\n if (hasSemicolon) {\n modifiedSql += ';';\n }\n\n return {\n sql: modifiedSql,\n wasLimited: true,\n originalLimit: info.existingLimit,\n appliedLimit: limit,\n appliedOffset: offset,\n };\n}\n\n/**\n * Sorgunun LIMIT'li olup olmadığını hızlıca kontrol eder.\n */\nexport function hasQueryLimit(sql: string): boolean {\n const info = analyzeQuery(sql);\n return info.hasLimit;\n}\n\n/**\n * Sorgunun SELECT türünde olup olmadığını kontrol eder.\n */\nexport function isSelectQuery(sql: string): boolean {\n const info = analyzeQuery(sql);\n return info.type === 'SELECT';\n}\n","/**\n * SQL Base Provider\n * Abstract class with shared logic for all SQL-based databases\n */\n\nimport { BaseDatabaseProvider } from '../../base-provider';\nimport {\n type DatabaseConnection,\n type ProviderOptions,\n type PreparedQuery,\n type QueryPrepareOptions,\n} from '../../types';\nimport {\n analyzeQuery,\n applyQueryLimit,\n DEFAULT_QUERY_LIMIT,\n MAX_UNLIMITED_ROWS,\n} from '../../utils/query-limiter';\n\n// ============================================================================\n// SQL Base Provider\n// ============================================================================\n\nexport abstract class SQLBaseProvider extends BaseDatabaseProvider {\n constructor(config: DatabaseConnection, options: ProviderOptions = {}) {\n super(config, options);\n }\n\n // ============================================================================\n // SQL-Specific Utilities\n // ============================================================================\n\n /**\n * Escape identifier based on SQL dialect\n * PostgreSQL/SQLite: \"identifier\"\n * MySQL: `identifier`\n */\n protected escapeIdentifier(identifier: string): string {\n if (this.type === 'mssql') {\n const escaped = identifier.replace(/\\]/g, ']]');\n return `[${escaped}]`;\n }\n const quoteChar = this.type === 'mysql' ? '`' : '\"';\n const escaped = identifier.replace(\n new RegExp(quoteChar, 'g'),\n quoteChar + quoteChar\n );\n return `${quoteChar}${escaped}${quoteChar}`;\n }\n\n /**\n * Escape string value for SQL\n */\n protected escapeString(value: string): string {\n return value.replace(/'/g, \"''\");\n }\n\n /**\n * Build LIMIT clause based on dialect\n */\n protected buildLimitClause(limit: number, offset?: number): string {\n if (offset !== undefined && offset > 0) {\n return `LIMIT ${limit} OFFSET ${offset}`;\n }\n return `LIMIT ${limit}`;\n }\n\n /**\n * Get placeholder style for parameterized queries\n * PostgreSQL: $1, $2, $3\n * MySQL/SQLite: ?, ?, ?\n */\n protected getPlaceholder(index: number): string {\n if (this.type === 'postgres') return `$${index}`;\n if (this.type === 'oracle') return `:${index}`;\n if (this.type === 'mssql') return `@p${index}`;\n return '?';\n }\n\n /**\n * Determine if SSL should be enabled based on host\n */\n protected shouldEnableSSL(): boolean {\n const host = this.config.host?.toLowerCase() || '';\n const cloudProviders = [\n 'supabase',\n 'render',\n 'neon',\n 'planetscale',\n 'aws',\n 'azure',\n 'gcp',\n 'cloud',\n ];\n return (\n this.options.ssl === true ||\n cloudProviders.some((provider) => host.includes(provider))\n );\n }\n\n /**\n * Get information schema name based on dialect\n */\n protected getInformationSchemaName(): string {\n return 'information_schema';\n }\n\n /**\n * Get default schema/database name for queries\n */\n protected getDefaultSchema(): string {\n switch (this.type) {\n case 'postgres':\n return 'public';\n case 'mysql':\n return this.config.database || '';\n case 'oracle':\n return this.config.user?.toUpperCase() || '';\n case 'mssql':\n return 'dbo';\n default:\n return '';\n }\n }\n\n /**\n * Check if query is read-only (SELECT, SHOW, DESCRIBE, EXPLAIN)\n */\n protected isReadOnlyQuery(sql: string): boolean {\n const trimmed = sql.trim().toLowerCase();\n return (\n trimmed.startsWith('select') ||\n trimmed.startsWith('show') ||\n trimmed.startsWith('describe') ||\n trimmed.startsWith('explain') ||\n trimmed.startsWith('pragma')\n );\n }\n\n /**\n * Check if query modifies schema (CREATE, DROP, ALTER, TRUNCATE)\n */\n protected isSchemaModifyingQuery(sql: string): boolean {\n const trimmed = sql.trim().toLowerCase();\n return (\n trimmed.startsWith('create') ||\n trimmed.startsWith('drop') ||\n trimmed.startsWith('alter') ||\n trimmed.startsWith('truncate')\n );\n }\n\n // ============================================================================\n // Query Preparation (applies LIMIT for SELECT queries)\n // ============================================================================\n\n public override prepareQuery(query: string, options: QueryPrepareOptions = {}): PreparedQuery {\n const { limit = DEFAULT_QUERY_LIMIT, offset = 0, unlimited = false } = options;\n const effectiveLimit = unlimited ? MAX_UNLIMITED_ROWS : limit;\n const queryInfo = analyzeQuery(query);\n\n if (queryInfo.type === 'SELECT') {\n const limitResult = applyQueryLimit(query, effectiveLimit, offset);\n return {\n query: limitResult.sql,\n wasLimited: limitResult.wasLimited,\n limit: effectiveLimit,\n offset,\n };\n }\n\n return { query, wasLimited: false, limit: effectiveLimit, offset };\n }\n}\n"]}
|