fdb2 1.0.37 → 1.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +41 -0
  2. package/dist/public/explorer.css +517 -478
  3. package/dist/public/explorer.js +1114 -872
  4. package/dist/public/index.css +87 -27
  5. package/dist/public/index.js +97 -49
  6. package/dist/public/layout.js +2 -2
  7. package/dist/public/vue.js +1 -1
  8. package/dist/server/core/schema/__tests__/canonical.test.ts +195 -0
  9. package/dist/server/core/schema/__tests__/ddl-emitter.test.ts +456 -0
  10. package/dist/server/core/schema/__tests__/diff.test.ts +242 -0
  11. package/dist/server/core/schema/__tests__/roundtrip.property.test.ts +403 -0
  12. package/dist/server/core/schema/canonical.d.ts +50 -0
  13. package/dist/server/core/schema/canonical.d.ts.map +1 -0
  14. package/dist/server/core/schema/canonical.js +212 -0
  15. package/dist/server/core/schema/canonical.js.map +1 -0
  16. package/dist/server/core/schema/canonical.ts +223 -0
  17. package/dist/server/core/schema/ddl-emitter.d.ts +68 -0
  18. package/dist/server/core/schema/ddl-emitter.d.ts.map +1 -0
  19. package/dist/server/core/schema/ddl-emitter.js +813 -0
  20. package/dist/server/core/schema/ddl-emitter.js.map +1 -0
  21. package/dist/server/core/schema/ddl-emitter.ts +925 -0
  22. package/dist/server/core/schema/diff.d.ts +16 -0
  23. package/dist/server/core/schema/diff.d.ts.map +1 -0
  24. package/dist/server/core/schema/diff.js +115 -0
  25. package/dist/server/core/schema/diff.js.map +1 -0
  26. package/dist/server/core/schema/diff.ts +134 -0
  27. package/dist/server/core/schema/type-defaults.d.ts +27 -0
  28. package/dist/server/core/schema/type-defaults.d.ts.map +1 -0
  29. package/dist/server/core/schema/type-defaults.js +61 -0
  30. package/dist/server/core/schema/type-defaults.js.map +1 -0
  31. package/dist/server/core/schema/type-defaults.ts +79 -0
  32. package/dist/server/index.d.ts +1 -1
  33. package/dist/server/index.d.ts.map +1 -1
  34. package/dist/server/index.js +347 -124
  35. package/dist/server/index.js.map +1 -1
  36. package/dist/server/index.ts +336 -161
  37. package/dist/server/model/ddl-spec.d.ts +163 -0
  38. package/dist/server/model/ddl-spec.d.ts.map +1 -0
  39. package/dist/server/model/ddl-spec.js +32 -0
  40. package/dist/server/model/ddl-spec.js.map +1 -0
  41. package/dist/server/model/ddl-spec.ts +175 -0
  42. package/dist/server/service/connection.service.d.ts +20 -0
  43. package/dist/server/service/connection.service.d.ts.map +1 -1
  44. package/dist/server/service/connection.service.js +99 -25
  45. package/dist/server/service/connection.service.js.map +1 -1
  46. package/dist/server/service/connection.service.ts +104 -25
  47. package/dist/server/service/database/base.service.d.ts +0 -4
  48. package/dist/server/service/database/base.service.d.ts.map +1 -1
  49. package/dist/server/service/database/base.service.js.map +1 -1
  50. package/dist/server/service/database/base.service.ts +0 -5
  51. package/dist/server/service/database/clickhouse.service.d.ts +0 -5
  52. package/dist/server/service/database/clickhouse.service.d.ts.map +1 -1
  53. package/dist/server/service/database/clickhouse.service.js +0 -49
  54. package/dist/server/service/database/clickhouse.service.js.map +1 -1
  55. package/dist/server/service/database/clickhouse.service.ts +0 -52
  56. package/dist/server/service/database/cockroachdb.service.d.ts +0 -5
  57. package/dist/server/service/database/cockroachdb.service.d.ts.map +1 -1
  58. package/dist/server/service/database/cockroachdb.service.js +11 -142
  59. package/dist/server/service/database/cockroachdb.service.js.map +1 -1
  60. package/dist/server/service/database/cockroachdb.service.ts +11 -161
  61. package/dist/server/service/database/database.service.d.ts +55 -2
  62. package/dist/server/service/database/database.service.d.ts.map +1 -1
  63. package/dist/server/service/database/database.service.js +246 -4
  64. package/dist/server/service/database/database.service.js.map +1 -1
  65. package/dist/server/service/database/database.service.ts +295 -7
  66. package/dist/server/service/database/mongodb.service.d.ts +0 -6
  67. package/dist/server/service/database/mongodb.service.d.ts.map +1 -1
  68. package/dist/server/service/database/mongodb.service.js +0 -8
  69. package/dist/server/service/database/mongodb.service.js.map +1 -1
  70. package/dist/server/service/database/mongodb.service.ts +0 -8
  71. package/dist/server/service/database/mssql.service.d.ts +8 -4
  72. package/dist/server/service/database/mssql.service.d.ts.map +1 -1
  73. package/dist/server/service/database/mssql.service.js +27 -101
  74. package/dist/server/service/database/mssql.service.js.map +1 -1
  75. package/dist/server/service/database/mssql.service.ts +28 -122
  76. package/dist/server/service/database/mysql.service.d.ts +0 -4
  77. package/dist/server/service/database/mysql.service.d.ts.map +1 -1
  78. package/dist/server/service/database/mysql.service.js +11 -137
  79. package/dist/server/service/database/mysql.service.js.map +1 -1
  80. package/dist/server/service/database/mysql.service.ts +11 -173
  81. package/dist/server/service/database/oracle.service.d.ts +0 -4
  82. package/dist/server/service/database/oracle.service.d.ts.map +1 -1
  83. package/dist/server/service/database/oracle.service.js +11 -104
  84. package/dist/server/service/database/oracle.service.js.map +1 -1
  85. package/dist/server/service/database/oracle.service.ts +11 -127
  86. package/dist/server/service/database/postgres.service.d.ts +0 -4
  87. package/dist/server/service/database/postgres.service.d.ts.map +1 -1
  88. package/dist/server/service/database/postgres.service.js +11 -112
  89. package/dist/server/service/database/postgres.service.js.map +1 -1
  90. package/dist/server/service/database/postgres.service.ts +11 -133
  91. package/dist/server/service/database/sap.service.d.ts +0 -4
  92. package/dist/server/service/database/sap.service.d.ts.map +1 -1
  93. package/dist/server/service/database/sap.service.js +11 -137
  94. package/dist/server/service/database/sap.service.js.map +1 -1
  95. package/dist/server/service/database/sap.service.ts +11 -158
  96. package/dist/server/service/database/sql-type.helper.d.ts.map +1 -1
  97. package/dist/server/service/database/sql-type.helper.js +9 -47
  98. package/dist/server/service/database/sql-type.helper.js.map +1 -1
  99. package/dist/server/service/database/sql-type.helper.ts +11 -53
  100. package/dist/server/service/database/sqlite.service.d.ts +0 -5
  101. package/dist/server/service/database/sqlite.service.d.ts.map +1 -1
  102. package/dist/server/service/database/sqlite.service.js +11 -147
  103. package/dist/server/service/database/sqlite.service.js.map +1 -1
  104. package/dist/server/service/database/sqlite.service.ts +11 -177
  105. package/package.json +1 -1
  106. package/server.js +1 -1
@@ -1684,13 +1684,13 @@ body.platform-desktop .text-primary.spinner-border {
1684
1684
  }
1685
1685
 
1686
1686
  /* 覆盖Bootstrap默认样式 */
1687
- .toast-container[data-v-7d639c44] {
1687
+ .toast-container[data-v-daf8ceb9] {
1688
1688
  z-index: 1100;
1689
1689
  }
1690
- .fade-out[data-v-7d639c44] {
1691
- animation: fadeOut-7d639c44 1s forwards;
1690
+ .fade-out[data-v-daf8ceb9] {
1691
+ animation: fadeOut-daf8ceb9 1s forwards;
1692
1692
  }
1693
- @keyframes fadeOut-7d639c44 {
1693
+ @keyframes fadeOut-daf8ceb9 {
1694
1694
  0% { opacity: 1; transform: translateY(0);
1695
1695
  }
1696
1696
  100% { opacity: 0; transform: translateY(-120%);}
@@ -1712,37 +1712,95 @@ body.platform-desktop .text-primary.spinner-border {
1712
1712
  text-align: center;
1713
1713
  }
1714
1714
 
1715
- .modal-dialog[data-v-aa6b0e1f] {
1715
+ .modal-dialog[data-v-8c11135e] {
1716
1716
  z-index: var(--bs-modal-zindex);
1717
- max-width:none !important;
1717
+ max-width: none;
1718
1718
  }
1719
- .modal-success .modal-header[data-v-aa6b0e1f] {
1719
+
1720
+ /* 纯文案提示弹窗:宽高跟随内容,短消息不再撑成大弹窗 */
1721
+ .modal-dialog.modal-dialog-auto[data-v-8c11135e] {
1722
+ width: fit-content;
1723
+ min-width: min(280px, 92vw);
1724
+ max-width: min(80vw, 420px);
1725
+ margin: auto;
1726
+ }
1727
+
1728
+ /* ---------------- 弹窗自身的紧凑密度 ----------------
1729
+ * database.css 的 .modal-header/.modal-body/.modal-footer 面向「网页大屏」,
1730
+ * 而桌面端靠 body.platform-desktop 覆盖成紧凑值,webview(VSCode)没有该类,
1731
+ * 于是同一套弹窗在 webview 里标题 24px、内边距 32px,显得又空又大。
1732
+ * 这里把密度收进组件自身(与 platform-desktop 的取值一致),
1733
+ * 两个宿主下观感统一,不再依赖全局样式差异。
1734
+ */
1735
+ .modal-header[data-v-8c11135e] {
1736
+ padding: 0.625rem 0.875rem;
1737
+ }
1738
+ .modal-header[data-v-8c11135e]::before {
1739
+ display: none; /* 去掉标题栏顶部 4px 品牌色条 */
1740
+ }
1741
+ .modal-title[data-v-8c11135e] {
1742
+ font-size: 0.875rem;
1743
+ font-weight: 600;
1744
+ }
1745
+ .modal-body[data-v-8c11135e] {
1746
+ padding: 0.875rem;
1747
+ display: flex;
1748
+ flex-direction: column;
1749
+ align-items: stretch;
1750
+ }
1751
+ .modal-footer[data-v-8c11135e] {
1752
+ padding: 0.5rem 0.875rem;
1753
+ gap: 0.5rem;
1754
+ }
1755
+ .modal-footer .btn[data-v-8c11135e] {
1756
+ padding: 0.25rem 0.75rem;
1757
+ font-size: 0.8125rem;
1758
+ }
1759
+
1760
+ /* 关闭按钮:不用 .btn-close 的 svg data-uri 背景(webview CSP 下不渲染,
1761
+ * 会退化成一个无图标的灰色方块),改用 bootstrap-icons 字形画叉 */
1762
+ .btn-close[data-v-8c11135e] {
1763
+ display: inline-flex;
1764
+ align-items: center;
1765
+ justify-content: center;
1766
+ width: 24px;
1767
+ height: 24px;
1768
+ padding: 0;
1769
+ border: none;
1770
+ border-radius: 6px;
1771
+ background-color: transparent;
1772
+ background-image: none;
1773
+ box-shadow: none;
1774
+ opacity: 0.85;
1775
+ font-size: 13px;
1776
+ color: inherit;
1777
+ }
1778
+ .btn-close[data-v-8c11135e]:hover,
1779
+ .btn-close[data-v-8c11135e]:focus {
1780
+ background-color: rgba(128, 128, 128, 0.28);
1781
+ opacity: 1;
1782
+ }
1783
+ .modal-success .modal-header[data-v-8c11135e] {
1720
1784
  background-color: var(--bs-success);
1721
1785
  color: white;
1722
1786
  }
1723
- .modal-error .modal-header[data-v-aa6b0e1f] {
1787
+ .modal-error .modal-header[data-v-8c11135e] {
1724
1788
  background-color: var(--bs-danger);
1725
1789
  color: white;
1726
1790
  }
1727
- .modal-warning .modal-header[data-v-aa6b0e1f] {
1791
+ .modal-warning .modal-header[data-v-8c11135e] {
1728
1792
  background-color: var(--bs-warning);
1729
1793
  color: var(--bs-dark);
1730
1794
  }
1731
- .modal-info .modal-header[data-v-aa6b0e1f] {
1795
+ .modal-info .modal-header[data-v-8c11135e] {
1732
1796
  background-color: var(--bs-info);
1733
1797
  color: white;
1734
1798
  }
1735
- .modal-body[data-v-aa6b0e1f] {
1736
- min-height: 80px;
1737
- display: flex;
1738
- flex-direction: column;
1739
- align-items: stretch;
1740
- }
1741
- .error-details[data-v-aa6b0e1f] {
1799
+ .error-details[data-v-8c11135e] {
1742
1800
  width: 100%;
1743
1801
  margin-top: 1rem;
1744
1802
  }
1745
- .error-content[data-v-aa6b0e1f] {
1803
+ .error-content[data-v-8c11135e] {
1746
1804
  background-color: var(--db-bg-soft2);
1747
1805
  border: 1px solid var(--db-gray-medium);
1748
1806
  border-radius: 0.375rem;
@@ -1756,17 +1814,17 @@ body.platform-desktop .text-primary.spinner-border {
1756
1814
  font-size: 0.875rem;
1757
1815
  line-height: 1.5;
1758
1816
  }
1759
- .error-details-toggle[data-v-aa6b0e1f] {
1817
+ .error-details-toggle[data-v-8c11135e] {
1760
1818
  width: 100%;
1761
1819
  }
1762
- .error-details-content[data-v-aa6b0e1f] {
1820
+ .error-details-content[data-v-8c11135e] {
1763
1821
  background-color: var(--db-bg-soft2);
1764
1822
  border: 1px solid var(--db-gray-medium);
1765
1823
  border-radius: 0.375rem;
1766
1824
  padding: 1rem;
1767
1825
  margin-top: 0.5rem;
1768
1826
  }
1769
- .error-json[data-v-aa6b0e1f] {
1827
+ .error-json[data-v-8c11135e] {
1770
1828
  background-color: var(--db-text-body);
1771
1829
  color: var(--db-bg-soft2);
1772
1830
  border-radius: 0.25rem;
@@ -1778,20 +1836,22 @@ body.platform-desktop .text-primary.spinner-border {
1778
1836
  white-space: pre-wrap;
1779
1837
  word-break: break-word;
1780
1838
  }
1781
- .error-meta[data-v-aa6b0e1f] {
1839
+ .error-meta[data-v-8c11135e] {
1782
1840
  border-bottom: 1px solid var(--db-gray-medium);
1783
1841
  padding-bottom: 0.5rem;
1784
1842
  margin-bottom: 0.5rem;
1785
1843
  }
1786
- .modal-body .fs-1[data-v-aa6b0e1f] {
1787
- font-size: 2.5rem;
1788
- margin-bottom: 1rem;
1844
+
1845
+ /* 提示类型图标:随内容紧凑展示(不用 Bootstrap 的 fs-1,避免 2.5rem 撑高弹窗) */
1846
+ .modal-type-icon[data-v-8c11135e] {
1847
+ font-size: 1.25rem;
1848
+ line-height: 1;
1789
1849
  }
1790
1850
 
1791
1851
  /* 响应式调整 */
1792
1852
  @media (max-width: 576px) {
1793
- .error-content[data-v-aa6b0e1f],
1794
- .error-json[data-v-aa6b0e1f] {
1853
+ .error-content[data-v-8c11135e],
1854
+ .error-json[data-v-8c11135e] {
1795
1855
  font-size: 0.75rem;
1796
1856
  max-height: 150px;
1797
1857
  }
@@ -1,6 +1,6 @@
1
1
  const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./layout.js","./rolldown-runtime.js","./vue.js","./layout.css","./explorer.js","./explorer.css","./vconsole.min.js"])))=>i.map(i=>d[i]);
2
2
  import { a as __toESM, n as __esmMin, r as __exportAll, t as __commonJSMin } from "./rolldown-runtime.js";
3
- import { $ as onScopeDispose, A as defineComponent, B as renderList, C as createBlock, F as nextTick, H as resolveComponent, I as onBeforeUnmount, J as getCurrentScope, L as onMounted, M as hasInjectionContext, O as createTextVNode, P as inject, Q as markRaw, R as onUnmounted, S as createBaseVNode, T as createElementBlock, U as resolveDynamicComponent, V as renderSlot, W as watch, X as isReactive, Z as isRef, a as init_vue_router, b as Fragment, c as createI18n, ct as toDisplayString, d as init_vue_runtime_esm_bundler, et as reactive, i as createWebHistory, it as unref, j as getCurrentInstance, k as createVNode, l as init_vue_i18n, n as useTitle, nt as toRaw, ot as normalizeClass, p as createApp, q as effectScope, r as createRouter, rt as toRefs, st as normalizeStyle, t as init_core, tt as ref, u as useI18n, w as createCommentVNode, x as computed, y as withModifiers, z as openBlock } from "./vue.js";
3
+ import { $ as markRaw, A as defineComponent, B as renderList, C as createBlock, F as nextTick, G as watch, H as resolveComponent, I as onBeforeUnmount, J as effectScope, L as onMounted, M as hasInjectionContext, O as createTextVNode, P as inject, Q as isRef, R as onUnmounted, S as createBaseVNode, T as createElementBlock, U as resolveDynamicComponent, V as renderSlot, W as useSlots, Y as getCurrentScope, Z as isReactive, a as init_vue_router, at as unref, b as Fragment, c as createI18n, ct as normalizeStyle, d as init_vue_runtime_esm_bundler, et as onScopeDispose, i as createWebHistory, it as toRefs, j as getCurrentInstance, k as createVNode, l as init_vue_i18n, lt as toDisplayString, n as useTitle, nt as ref, p as createApp, r as createRouter, rt as toRaw, st as normalizeClass, t as init_core, tt as reactive, u as useI18n, w as createCommentVNode, x as computed, y as withModifiers, z as openBlock } from "./vue.js";
4
4
  import { i as init_bootstrap, n as init_bootstrap_esm, r as init_bootstrap_icons, t as Modal } from "./bootstrap.js";
5
5
  //#region \0vite/modulepreload-polyfill.js
6
6
  (function polyfill() {
@@ -4510,6 +4510,13 @@ function getVSCodeBridge() {
4510
4510
  if (!bridgeInstance) bridgeInstance = new VSCodeBridge();
4511
4511
  return bridgeInstance;
4512
4512
  }
4513
+ /**
4514
+ * 判断是否在 VSCode 环境中
4515
+ */
4516
+ function isVSCodeEnvironment() {
4517
+ if (!bridgeInstance) bridgeInstance = new VSCodeBridge();
4518
+ return bridgeInstance.isVSCodeEnvironment();
4519
+ }
4513
4520
  var VSCodeBridge, bridgeInstance;
4514
4521
  var init_bridge = __esmMin((() => {
4515
4522
  VSCodeBridge = class {
@@ -4535,10 +4542,15 @@ var init_bridge = __esmMin((() => {
4535
4542
  }
4536
4543
  /**
4537
4544
  * 监听来自 VSCode 扩展的消息
4545
+ *
4546
+ * 这里刻意不按 event.origin 过滤:VSCode 各版本经 webview.postMessage 下发时
4547
+ * 携带的 origin 并不稳定(部分版本为非空值),一旦过滤就会把宿主消息整批丢掉,
4548
+ * 表现为「连接下拉为空 / 数据库列表不展示」这类面板级静默失效。
4549
+ * rpc.ts 与 entry/explorer.ts 的监听同样不过滤,这里与之保持一致。
4550
+ * webview 内 CSP 已限定脚本来源、宿主是唯一消息来源,该过滤没有实际收益。
4538
4551
  */
4539
4552
  onMessage(callback) {
4540
4553
  window.addEventListener("message", (event) => {
4541
- if (event.origin) return;
4542
4554
  callback(event.data);
4543
4555
  });
4544
4556
  }
@@ -5079,6 +5091,12 @@ var init_zh_CN = __esmMin((() => {
5079
5091
  quickActions: "快速操作",
5080
5092
  exportSchema: "导出架构",
5081
5093
  viewLogs: "查看日志",
5094
+ schemaExported: "架构已导出({count} 个数据库){path}",
5095
+ schemaExportNoDatabase: "当前连接下没有可导出的数据库",
5096
+ schemaExportFailed: "架构导出失败",
5097
+ logsTitle: "数据库日志",
5098
+ logsEmpty: "没有可展示的日志记录",
5099
+ logsLoadFailed: "日志读取失败",
5082
5100
  searchDatabase: "搜索数据库...",
5083
5101
  loadingDatabases: "加载数据库列表...",
5084
5102
  noDatabase: "暂无数据库",
@@ -5110,6 +5128,13 @@ var init_zh_CN = __esmMin((() => {
5110
5128
  basicInfo: "基本信息",
5111
5129
  connectionConfig: "连接配置",
5112
5130
  sqliteConfig: "SQLite配置",
5131
+ remoteConfig: "远程代理服务",
5132
+ remoteUrl: "服务地址",
5133
+ remoteUrlPlaceholder: "http://192.168.1.10:9800",
5134
+ remoteToken: "访问令牌(可选)",
5135
+ remoteTokenPlaceholder: "与服务端 DB_TOOL_REMOTE_TOKEN 一致",
5136
+ remoteConfigHint: "保存后,该远程服务上的所有数据库连接会自动出现在连接列表中,可像本地数据库一样直接访问。",
5137
+ remoteUrlRequired: "请填写远程服务地址",
5113
5138
  authInfo: "认证信息",
5114
5139
  otherOptions: "其他选项",
5115
5140
  host: "主机地址",
@@ -5163,7 +5188,6 @@ var init_zh_CN = __esmMin((() => {
5163
5188
  refreshDatabase: "刷新数据库",
5164
5189
  deleteDatabase: "删除数据库",
5165
5190
  refreshTable: "刷新表",
5166
- viewStructure: "查看结构",
5167
5191
  defaultTitle: "数据库浏览器",
5168
5192
  defaultDesc: "请从左侧选择一个连接、数据库或表来查看详细信息",
5169
5193
  rowsSuffix: "行"
@@ -5275,7 +5299,6 @@ var init_zh_CN = __esmMin((() => {
5275
5299
  operationFailed: "操作失败",
5276
5300
  structureModifySuccess: "表结构修改成功",
5277
5301
  structureModifyFailed: "表结构修改失败",
5278
- confirmDeleteColumn: "确定要删除列 {name} 吗?",
5279
5302
  confirmDeleteIndex: "确定要删除索引 {name} 吗?",
5280
5303
  confirmDeleteFK: "确定要删除外键 {name} 吗?",
5281
5304
  noInsertField: "没有可插入的字段",
@@ -5602,7 +5625,8 @@ var init_zh_CN = __esmMin((() => {
5602
5625
  syncSuccess: "数据同步成功,{success}/{total} 个表同步完成,共同步 {rows} 行数据",
5603
5626
  syncSuccessToast: "数据同步成功,{success}/{total} 个表同步完成",
5604
5627
  loadTablesFailed: "加载表列表失败",
5605
- sqlSent: "已发送 SQL 查询",
5628
+ execFailed: "执行失败",
5629
+ selectConnectionFirst: "请先选择数据库连接",
5606
5630
  featureInDev: "{feature}功能开发中...",
5607
5631
  healthNormal: "正常",
5608
5632
  healthCheckConnection: "连接状态",
@@ -5835,6 +5859,12 @@ var init_en_US = __esmMin((() => {
5835
5859
  quickActions: "Quick Actions",
5836
5860
  exportSchema: "Export Schema",
5837
5861
  viewLogs: "View Logs",
5862
+ schemaExported: "Schema exported ({count} database(s)){path}",
5863
+ schemaExportNoDatabase: "No database available to export for this connection",
5864
+ schemaExportFailed: "Failed to export schema",
5865
+ logsTitle: "Database Logs",
5866
+ logsEmpty: "No log records to display",
5867
+ logsLoadFailed: "Failed to load logs",
5838
5868
  searchDatabase: "Search databases...",
5839
5869
  loadingDatabases: "Loading databases...",
5840
5870
  noDatabase: "No databases yet",
@@ -5866,6 +5896,13 @@ var init_en_US = __esmMin((() => {
5866
5896
  basicInfo: "Basic Information",
5867
5897
  connectionConfig: "Connection Configuration",
5868
5898
  sqliteConfig: "SQLite Configuration",
5899
+ remoteConfig: "Remote Proxy Service",
5900
+ remoteUrl: "Service URL",
5901
+ remoteUrlPlaceholder: "http://192.168.1.10:9800",
5902
+ remoteToken: "Access Token (optional)",
5903
+ remoteTokenPlaceholder: "Same as the server DB_TOOL_REMOTE_TOKEN",
5904
+ remoteConfigHint: "After saving, all database connections on that remote service appear in the connection list and can be accessed like local databases.",
5905
+ remoteUrlRequired: "Remote service URL is required",
5869
5906
  authInfo: "Authentication",
5870
5907
  otherOptions: "Other Options",
5871
5908
  host: "Host",
@@ -5919,7 +5956,6 @@ var init_en_US = __esmMin((() => {
5919
5956
  refreshDatabase: "Refresh Database",
5920
5957
  deleteDatabase: "Delete Database",
5921
5958
  refreshTable: "Refresh Table",
5922
- viewStructure: "View Structure",
5923
5959
  defaultTitle: "Database Explorer",
5924
5960
  defaultDesc: "Select a connection, database, or table from the left panel to view details",
5925
5961
  rowsSuffix: "rows"
@@ -6028,7 +6064,6 @@ var init_en_US = __esmMin((() => {
6028
6064
  operationFailed: "Operation failed",
6029
6065
  structureModifySuccess: "Table structure modified successfully",
6030
6066
  structureModifyFailed: "Failed to modify table structure",
6031
- confirmDeleteColumn: "Are you sure you want to delete column {name}?",
6032
6067
  confirmDeleteIndex: "Are you sure you want to delete index {name}?",
6033
6068
  confirmDeleteFK: "Are you sure you want to delete foreign key {name}?",
6034
6069
  noInsertField: "No insertable fields",
@@ -6355,7 +6390,8 @@ var init_en_US = __esmMin((() => {
6355
6390
  syncSuccess: "Data sync successful, {success}/{total} tables synced, {rows} rows total",
6356
6391
  syncSuccessToast: "Data sync successful, {success}/{total} tables synced",
6357
6392
  loadTablesFailed: "Failed to load table list",
6358
- sqlSent: "SQL query sent",
6393
+ execFailed: "Execution failed",
6394
+ selectConnectionFirst: "Please select a database connection first",
6359
6395
  featureInDev: "{feature} feature is under development...",
6360
6396
  healthNormal: "Normal",
6361
6397
  healthCheckConnection: "Connection Status",
@@ -6797,7 +6833,7 @@ var init_toast_vue_vue_type_script_setup_true_lang = __esmMin((() => {
6797
6833
  }, [toast.title ? (openBlock(), createElementBlock("div", _hoisted_2$4, [createBaseVNode("strong", _hoisted_3$3, toDisplayString(toast.title), 1), createBaseVNode("button", {
6798
6834
  type: "button",
6799
6835
  class: "btn-close",
6800
- onClick: ($event) => removeToast(index)
6836
+ onClick: ($event) => removeToast(toast)
6801
6837
  }, null, 8, _hoisted_4$2)])) : createCommentVNode("", true), createBaseVNode("div", _hoisted_5$2, toDisplayString(toast.message), 1)], 2);
6802
6838
  }), 128))]);
6803
6839
  };
@@ -6805,8 +6841,8 @@ var init_toast_vue_vue_type_script_setup_true_lang = __esmMin((() => {
6805
6841
  });
6806
6842
  }));
6807
6843
  //#endregion
6808
- //#region src/components/toast/toast.vue?vue&type=style&index=0&scoped=7d639c44&lang.css
6809
- var init_toast_vue_vue_type_style_index_0_scoped_7d639c44_lang = __esmMin((() => {}));
6844
+ //#region src/components/toast/toast.vue?vue&type=style&index=0&scoped=daf8ceb9&lang.css
6845
+ var init_toast_vue_vue_type_style_index_0_scoped_daf8ceb9_lang = __esmMin((() => {}));
6810
6846
  //#endregion
6811
6847
  //#region \0plugin-vue:export-helper
6812
6848
  var _plugin_vue_export_helper_default;
@@ -6823,9 +6859,9 @@ var toast_default$1;
6823
6859
  var init_toast$2 = __esmMin((() => {
6824
6860
  init_toast_vue_vue_type_script_setup_true_lang();
6825
6861
  init_toast_vue_vue_type_script_setup_true_lang();
6826
- init_toast_vue_vue_type_style_index_0_scoped_7d639c44_lang();
6862
+ init_toast_vue_vue_type_style_index_0_scoped_daf8ceb9_lang();
6827
6863
  init__plugin_vue_export_helper();
6828
- toast_default$1 = /*#__PURE__*/ _plugin_vue_export_helper_default(toast_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-7d639c44"]]);
6864
+ toast_default$1 = /*#__PURE__*/ _plugin_vue_export_helper_default(toast_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-daf8ceb9"]]);
6829
6865
  }));
6830
6866
  //#endregion
6831
6867
  //#region src/utils/toast.ts
@@ -6952,7 +6988,7 @@ var init_loading = __esmMin((() => {
6952
6988
  }));
6953
6989
  //#endregion
6954
6990
  //#region src/components/modal/index.vue?vue&type=script&setup=true&lang.ts
6955
- var _hoisted_1$2, _hoisted_2$2, _hoisted_3$2, _hoisted_4$1, _hoisted_5$1, _hoisted_6$1, _hoisted_7$1, _hoisted_8$1, _hoisted_9$1, index_vue_vue_type_script_setup_true_lang_default$1;
6991
+ var _hoisted_1$2, _hoisted_2$2, _hoisted_3$2, _hoisted_4$1, _hoisted_5$1, _hoisted_6$1, _hoisted_7$1, _hoisted_8$1, index_vue_vue_type_script_setup_true_lang_default$1;
6956
6992
  var init_index_vue_vue_type_script_setup_true_lang$1 = __esmMin((() => {
6957
6993
  init_vue_runtime_esm_bundler();
6958
6994
  init_vue_i18n();
@@ -6967,18 +7003,17 @@ var init_index_vue_vue_type_script_setup_true_lang$1 = __esmMin((() => {
6967
7003
  class: "modal-body text-wrap"
6968
7004
  };
6969
7005
  _hoisted_3$2 = { key: 1 };
6970
- _hoisted_4$1 = { class: "d-flex align-items-center mb-3" };
6971
- _hoisted_5$1 = { class: "flex-grow-1 text-wrap" };
6972
- _hoisted_6$1 = {
7006
+ _hoisted_4$1 = { class: "flex-grow-1 text-wrap" };
7007
+ _hoisted_5$1 = {
6973
7008
  key: 0,
6974
7009
  class: "error-details-toggle mt-2"
6975
7010
  };
6976
- _hoisted_7$1 = {
7011
+ _hoisted_6$1 = {
6977
7012
  key: 0,
6978
7013
  class: "error-details-content mt-2"
6979
7014
  };
6980
- _hoisted_8$1 = { class: "error-json" };
6981
- _hoisted_9$1 = { class: "modal-footer" };
7015
+ _hoisted_7$1 = { class: "error-json" };
7016
+ _hoisted_8$1 = { class: "modal-footer" };
6982
7017
  index_vue_vue_type_script_setup_true_lang_default$1 = /*@__PURE__*/ defineComponent({
6983
7018
  __name: "index",
6984
7019
  props: {
@@ -7044,23 +7079,17 @@ var init_index_vue_vue_type_script_setup_true_lang$1 = __esmMin((() => {
7044
7079
  const dynamicShowCancel = ref(false);
7045
7080
  const detailsExpanded = ref(false);
7046
7081
  const dynamicErrorDetails = ref(null);
7047
- const isMobile = ref(false);
7048
- const checkScreenSize = () => {
7049
- isMobile.value = window.innerWidth < 768;
7050
- };
7051
- checkScreenSize();
7052
- window.addEventListener("resize", checkScreenSize);
7053
- onUnmounted(() => {
7054
- window.removeEventListener("resize", checkScreenSize);
7055
- });
7082
+ const slots = useSlots();
7083
+ const isAutoSize = computed(() => !slots.default && !props.isFullScreen);
7056
7084
  const dynamicStyle = computed(() => {
7057
7085
  return {
7058
- maxWidth: isMobile.value ? "100vw" : "80vw!important",
7059
- width: "auto",
7060
- minWidth: "300px",
7086
+ ...isAutoSize.value ? {} : {
7087
+ width: "auto",
7088
+ minWidth: "300px"
7089
+ },
7061
7090
  wordWrap: "break-word",
7062
7091
  overflowWrap: "break-word",
7063
- zIndex: 1060,
7092
+ zIndex: "1060",
7064
7093
  ...Object.keys(props.style).length ? props.style : {},
7065
7094
  ...dynamicOptions.value?.style || {}
7066
7095
  };
@@ -7198,6 +7227,22 @@ var init_index_vue_vue_type_script_setup_true_lang$1 = __esmMin((() => {
7198
7227
  }
7199
7228
  return Promise.resolve();
7200
7229
  }
7230
+ /**
7231
+ * 强制收起弹窗(兜底)。
7232
+ * Bootstrap 的 hide() 依赖自身 _isShown / 过渡回调,在个别宿主环境(VSCode webview)
7233
+ * 里可能出现「点了关闭但状态没翻转」的情况,此时直接摘掉 show 类并移除遮罩,
7234
+ * 保证关闭按钮一定生效。
7235
+ */
7236
+ function forceHide() {
7237
+ const el = modalContainer.value;
7238
+ if (!el) return false;
7239
+ if (!(el.classList.contains("show") || getComputedStyle(el).display !== "none")) return false;
7240
+ el.classList.remove("show", "fade");
7241
+ el.style.display = "none";
7242
+ document.querySelectorAll(".modal-backdrop").forEach((b) => b.remove());
7243
+ ModalHide();
7244
+ return true;
7245
+ }
7201
7246
  function hide() {
7202
7247
  if (isHiding.value) {
7203
7248
  console.log("Modal already hiding, skipping");
@@ -7215,6 +7260,9 @@ var init_index_vue_vue_type_script_setup_true_lang$1 = __esmMin((() => {
7215
7260
  };
7216
7261
  modalInstance.hide();
7217
7262
  setTimeout(checkHidden, 100);
7263
+ setTimeout(() => {
7264
+ if (forceHide()) resolve();
7265
+ }, 800);
7218
7266
  });
7219
7267
  }
7220
7268
  return Promise.resolve();
@@ -7276,16 +7324,16 @@ var init_index_vue_vue_type_script_setup_true_lang$1 = __esmMin((() => {
7276
7324
  tabindex: "-1",
7277
7325
  "aria-labelledby": "modalLabel"
7278
7326
  }, [createBaseVNode("div", {
7279
- class: normalizeClass(["modal-dialog modal-dialog-centered", { "modal-fullscreen": __props.isFullScreen }]),
7327
+ class: normalizeClass(["modal-dialog modal-dialog-centered", {
7328
+ "modal-fullscreen": __props.isFullScreen,
7329
+ "modal-dialog-auto": isAutoSize.value
7330
+ }]),
7280
7331
  style: normalizeStyle(dynamicStyle.value)
7281
7332
  }, [createBaseVNode("div", {
7282
7333
  class: normalizeClass(["modal-content", contentClass.value]),
7283
7334
  style: { "margin": "auto" }
7284
7335
  }, [
7285
- createBaseVNode("div", {
7286
- class: normalizeClass(["modal-header", headerClass.value]),
7287
- style: { "padding": "1rem 1.5rem" }
7288
- }, [createBaseVNode("h5", _hoisted_1$2, [typeIcon.value ? (openBlock(), createElementBlock("i", {
7336
+ createBaseVNode("div", { class: normalizeClass(["modal-header", headerClass.value]) }, [createBaseVNode("h5", _hoisted_1$2, [typeIcon.value ? (openBlock(), createElementBlock("i", {
7289
7337
  key: 0,
7290
7338
  class: normalizeClass([typeIcon.value, "me-2"])
7291
7339
  }, null, 2)) : createCommentVNode("", true), createTextVNode(" " + toDisplayString(dynamicTitle.value || props.title), 1)]), createBaseVNode("button", {
@@ -7293,15 +7341,15 @@ var init_index_vue_vue_type_script_setup_true_lang$1 = __esmMin((() => {
7293
7341
  class: "btn-close",
7294
7342
  "aria-label": "Close",
7295
7343
  onClick: cancel
7296
- })], 2),
7297
- modalShow.value ? (openBlock(), createElementBlock("div", _hoisted_2$2, [_ctx.$slots.default ? renderSlot(_ctx.$slots, "default", { key: 0 }, void 0, true) : (openBlock(), createElementBlock("div", _hoisted_3$2, [createBaseVNode("div", _hoisted_4$1, [typeIcon.value ? (openBlock(), createElementBlock("i", {
7344
+ }, [..._cache[0] || (_cache[0] = [createBaseVNode("i", { class: "bi bi-x-lg" }, null, -1)])])], 2),
7345
+ modalShow.value ? (openBlock(), createElementBlock("div", _hoisted_2$2, [_ctx.$slots.default ? renderSlot(_ctx.$slots, "default", { key: 0 }, void 0, true) : (openBlock(), createElementBlock("div", _hoisted_3$2, [createBaseVNode("div", { class: normalizeClass(["d-flex align-items-center", shouldShowDetails() ? "mb-2" : "mb-0"]) }, [typeIcon.value ? (openBlock(), createElementBlock("i", {
7298
7346
  key: 0,
7299
- class: normalizeClass([typeIcon.value, "me-3 fs-1"])
7300
- }, null, 2)) : createCommentVNode("", true), createBaseVNode("div", _hoisted_5$1, toDisplayString(dynamicContent.value), 1)]), shouldShowDetails() ? (openBlock(), createElementBlock("div", _hoisted_6$1, [createBaseVNode("button", {
7347
+ class: normalizeClass([typeIcon.value, "me-3 modal-type-icon"])
7348
+ }, null, 2)) : createCommentVNode("", true), createBaseVNode("div", _hoisted_4$1, toDisplayString(dynamicContent.value), 1)], 2), shouldShowDetails() ? (openBlock(), createElementBlock("div", _hoisted_5$1, [createBaseVNode("button", {
7301
7349
  class: "btn btn-sm btn-outline-secondary",
7302
7350
  onClick: toggleDetails
7303
- }, [createTextVNode(toDisplayString(detailsExpanded.value ? _ctx.$t("common.hide") : _ctx.$t("common.details")) + " ", 1), _cache[0] || (_cache[0] = createBaseVNode("i", { class: "bi bi-chevron-{{detailsExpanded ? 'up' : 'down'}} ms-1" }, null, -1))]), detailsExpanded.value ? (openBlock(), createElementBlock("div", _hoisted_7$1, [createBaseVNode("pre", _hoisted_8$1, toDisplayString(formatErrorDetails()), 1)])) : createCommentVNode("", true)])) : createCommentVNode("", true)]))])) : createCommentVNode("", true),
7304
- createBaseVNode("div", _hoisted_9$1, [_ctx.$slots.footer ? renderSlot(_ctx.$slots, "footer", { key: 0 }, void 0, true) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [dynamicShowCancel.value || props.closeButton.show ? (openBlock(), createElementBlock("button", {
7351
+ }, [createTextVNode(toDisplayString(detailsExpanded.value ? _ctx.$t("common.hide") : _ctx.$t("common.details")) + " ", 1), _cache[1] || (_cache[1] = createBaseVNode("i", { class: "bi bi-chevron-{{detailsExpanded ? 'up' : 'down'}} ms-1" }, null, -1))]), detailsExpanded.value ? (openBlock(), createElementBlock("div", _hoisted_6$1, [createBaseVNode("pre", _hoisted_7$1, toDisplayString(formatErrorDetails()), 1)])) : createCommentVNode("", true)])) : createCommentVNode("", true)]))])) : createCommentVNode("", true),
7352
+ createBaseVNode("div", _hoisted_8$1, [_ctx.$slots.footer ? renderSlot(_ctx.$slots, "footer", { key: 0 }, void 0, true) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [dynamicShowCancel.value || props.closeButton.show ? (openBlock(), createElementBlock("button", {
7305
7353
  key: 0,
7306
7354
  type: "button",
7307
7355
  class: "btn btn-secondary",
@@ -7322,17 +7370,17 @@ var init_index_vue_vue_type_script_setup_true_lang$1 = __esmMin((() => {
7322
7370
  });
7323
7371
  }));
7324
7372
  //#endregion
7325
- //#region src/components/modal/index.vue?vue&type=style&index=0&scoped=aa6b0e1f&lang.css
7326
- var init_index_vue_vue_type_style_index_0_scoped_aa6b0e1f_lang = __esmMin((() => {}));
7373
+ //#region src/components/modal/index.vue?vue&type=style&index=0&scoped=8c11135e&lang.css
7374
+ var init_index_vue_vue_type_style_index_0_scoped_8c11135e_lang = __esmMin((() => {}));
7327
7375
  //#endregion
7328
7376
  //#region src/components/modal/index.vue
7329
7377
  var modal_default$1;
7330
7378
  var init_modal$1 = __esmMin((() => {
7331
7379
  init_index_vue_vue_type_script_setup_true_lang$1();
7332
7380
  init_index_vue_vue_type_script_setup_true_lang$1();
7333
- init_index_vue_vue_type_style_index_0_scoped_aa6b0e1f_lang();
7381
+ init_index_vue_vue_type_style_index_0_scoped_8c11135e_lang();
7334
7382
  init__plugin_vue_export_helper();
7335
- modal_default$1 = /*#__PURE__*/ _plugin_vue_export_helper_default(index_vue_vue_type_script_setup_true_lang_default$1, [["__scopeId", "data-v-aa6b0e1f"]]);
7383
+ modal_default$1 = /*#__PURE__*/ _plugin_vue_export_helper_default(index_vue_vue_type_script_setup_true_lang_default$1, [["__scopeId", "data-v-8c11135e"]]);
7336
7384
  }));
7337
7385
  //#endregion
7338
7386
  //#region src/components/dataGrid/pagination.vue?vue&type=script&setup=true&lang.ts
@@ -7776,4 +7824,4 @@ var init_modal = __esmMin((() => {
7776
7824
  app.mount("#app");
7777
7825
  })))();
7778
7826
  //#endregion
7779
- export { defineStore as A, init_rpc as C, vscodeSaveFile as D, vscodePickSaveFolder as E, init_detect as O, blobToBase64 as S, vscodeNotifyExported as T, init__plugin_vue_export_helper as _, dataGrid_default as a, init_base as b, pagination_default as c, init_loading as d, init_toast$1 as f, _plugin_vue_export_helper_default as g, toast_default$1 as h, showConfirm as i, init_pinia as j, isVSCode as k, init_modal$1 as l, init_toast$2 as m, init_modal as n, init_dataGrid as o, toast as p, showAlert as r, init_pagination as s, getModalInstance as t, modal_default$1 as u, getT as v, isVscodeWebview as w, request as x, init_i18n as y };
7827
+ export { isVSCodeEnvironment as A, init_rpc as C, vscodeSaveFile as D, vscodePickSaveFolder as E, isVSCode as M, defineStore as N, getVSCodeBridge as O, init_pinia as P, blobToBase64 as S, vscodeNotifyExported as T, init__plugin_vue_export_helper as _, dataGrid_default as a, init_base as b, pagination_default as c, init_loading as d, init_toast$1 as f, _plugin_vue_export_helper_default as g, toast_default$1 as h, showConfirm as i, init_detect as j, init_bridge as k, init_modal$1 as l, init_toast$2 as m, init_modal as n, init_dataGrid as o, toast as p, showAlert as r, init_pagination as s, getModalInstance as t, modal_default$1 as u, getT as v, isVscodeWebview as w, request as x, init_i18n as y };
@@ -1,6 +1,6 @@
1
1
  import { n as __esmMin } from "./rolldown-runtime.js";
2
- import { A as defineComponent, B as renderList, G as withCtx, H as resolveComponent, O as createTextVNode, S as createBaseVNode, T as createElementBlock, W as watch, b as Fragment, ct as toDisplayString, d as init_vue_runtime_esm_bundler, f as Transition, it as unref, k as createVNode, l as init_vue_i18n, u as useI18n, w as createCommentVNode, y as withModifiers, z as openBlock } from "./vue.js";
3
- import { A as defineStore, _ as init__plugin_vue_export_helper, g as _plugin_vue_export_helper_default, j as init_pinia } from "./index.js";
2
+ import { A as defineComponent, B as renderList, G as watch, H as resolveComponent, K as withCtx, O as createTextVNode, S as createBaseVNode, T as createElementBlock, at as unref, b as Fragment, d as init_vue_runtime_esm_bundler, f as Transition, k as createVNode, l as init_vue_i18n, lt as toDisplayString, u as useI18n, w as createCommentVNode, y as withModifiers, z as openBlock } from "./vue.js";
3
+ import { N as defineStore, P as init_pinia, _ as init__plugin_vue_export_helper, g as _plugin_vue_export_helper_default } from "./index.js";
4
4
  //#region src/stores/locale.ts
5
5
  var LOCALE_KEY, useLocaleStore;
6
6
  var init_locale = __esmMin((() => {
@@ -12963,4 +12963,4 @@ var init_core = __esmMin((() => {
12963
12963
  Number.POSITIVE_INFINITY;
12964
12964
  }));
12965
12965
  //#endregion
12966
- export { onScopeDispose as $, defineComponent as A, renderList as B, createBlock as C, createStaticVNode as D, createSlots as E, nextTick as F, withCtx as G, resolveComponent as H, onBeforeUnmount as I, getCurrentScope as J, withDirectives as K, onMounted as L, hasInjectionContext as M, init_runtime_core_esm_bundler as N, createTextVNode as O, inject as P, markRaw as Q, onUnmounted as R, createBaseVNode as S, createElementBlock as T, resolveDynamicComponent as U, renderSlot as V, watch as W, isReactive as X, init_reactivity_esm_bundler as Y, isRef as Z, vModelText as _, init_vue_router as a, init_shared_esm_bundler as at, Fragment as b, createI18n as c, toDisplayString$1 as ct, init_vue_runtime_esm_bundler as d, reactive as et, Transition as f, vModelSelect as g, vModelCheckbox as h, createWebHistory as i, unref as it, getCurrentInstance$1 as j, createVNode as k, init_vue_i18n as l, init_runtime_dom_esm_bundler as m, useTitle as n, toRaw as nt, useRoute as o, normalizeClass as ot, createApp as p, effectScope as q, createRouter as r, toRefs as rt, useRouter as s, normalizeStyle as st, init_core as t, ref as tt, useI18n as u, vShow as v, createCommentVNode as w, computed as x, withModifiers as y, openBlock as z };
12966
+ export { markRaw as $, defineComponent as A, renderList as B, createBlock as C, createStaticVNode as D, createSlots as E, nextTick as F, watch as G, resolveComponent as H, onBeforeUnmount as I, effectScope as J, withCtx as K, onMounted as L, hasInjectionContext as M, init_runtime_core_esm_bundler as N, createTextVNode as O, inject as P, isRef as Q, onUnmounted as R, createBaseVNode as S, createElementBlock as T, resolveDynamicComponent as U, renderSlot as V, useSlots as W, init_reactivity_esm_bundler as X, getCurrentScope as Y, isReactive as Z, vModelText as _, init_vue_router as a, unref as at, Fragment as b, createI18n as c, normalizeStyle as ct, init_vue_runtime_esm_bundler as d, onScopeDispose as et, Transition as f, vModelSelect as g, vModelCheckbox as h, createWebHistory as i, toRefs as it, getCurrentInstance$1 as j, createVNode as k, init_vue_i18n as l, toDisplayString$1 as lt, init_runtime_dom_esm_bundler as m, useTitle as n, ref as nt, useRoute as o, init_shared_esm_bundler as ot, createApp as p, withDirectives as q, createRouter as r, toRaw as rt, useRouter as s, normalizeClass as st, init_core as t, reactive as tt, useI18n as u, vShow as v, createCommentVNode as w, computed as x, withModifiers as y, openBlock as z };