@zz1996/dbhub-dameng 0.1.7 → 1.2.5-dameng.621

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 (32) hide show
  1. package/README.md +126 -137
  2. package/dbhub.dameng.toml.example +4 -11
  3. package/dist/{chunk-SQA2ISDE.js → chunk-2JL4KCP5.js} +21 -119
  4. package/dist/chunk-3RJRH3CN.js +121 -0
  5. package/dist/chunk-4276LPPU.js +179 -0
  6. package/dist/chunk-FU2ZJE4E.js +16 -0
  7. package/dist/chunk-HDPZAIDL.js +155 -0
  8. package/dist/{chunk-2A2QF3CS.js → chunk-HGU7ILEZ.js} +215 -68
  9. package/dist/{chunk-IPK7BYBL.js → chunk-JFWX35TB.js} +0 -1
  10. package/dist/chunk-O3PEWKBB.js +302 -0
  11. package/dist/dameng-NKF7NZKE.js +250 -0
  12. package/dist/index.js +461 -251
  13. package/dist/{mariadb-7F72IRB4.js → mariadb-MMC6WMEG.js} +86 -53
  14. package/dist/{mysql-A43SL7UM.js → mysql-TESH7KKV.js} +126 -50
  15. package/dist/{postgres-VFNLBWMF.js → postgres-C24SBQ4I.js} +154 -36
  16. package/dist/public/assets/index-BJ-1UrcV.css +1 -0
  17. package/dist/public/assets/index-BdBaFSHd.js +148 -0
  18. package/dist/public/assets/postgres-BpcazhJg.svg +22 -0
  19. package/dist/public/assets/sqlserver-ByfFYYpV.svg +11 -0
  20. package/dist/public/favicon.svg +57 -0
  21. package/dist/public/index.html +14 -0
  22. package/dist/public/logo-full-light.svg +58 -0
  23. package/dist/{registry-XSX2VZTD.js → registry-WVSFVS35.js} +3 -2
  24. package/dist/{sqlite-IOUAYHGE.js → sqlite-7BNGDMBZ.js} +57 -42
  25. package/dist/sqlserver-KZPPK67Q.js +1042 -0
  26. package/package.json +22 -65
  27. package/dist/chunk-RTB262PR.js +0 -60
  28. package/dist/chunk-ZNQTMARG.js +0 -127
  29. package/dist/dameng-5KYI5JBK.js +0 -898
  30. package/dist/sqlserver-OE4SFH4B.js +0 -587
  31. package/docs/README.md +0 -14
  32. package/docs/dameng-connector-plan.md +0 -143
package/README.md CHANGED
@@ -1,183 +1,172 @@
1
- > [!NOTE]
2
- > Brought to you by [Bytebase](https://www.bytebase.com/), open-source database DevSecOps platform.
3
-
4
- > [!NOTE]
5
- > This package is a local Dameng/DM8 connector fork of Bytebase DBHub. Use
6
- > `npx -y @zz1996/dbhub-dameng --transport stdio --config ./dbhub.dameng.toml`
7
- > for Dameng MCP usage.
8
- >
9
- > Dameng DSN format: `dameng://user:password@host:5236/schema`. Prefer a
10
- > least-privilege read-only Dameng account for production or shared databases,
11
- > even when the `execute_sql` tool is configured with `readonly = true`.
12
-
13
- <p align="center">
14
- <a href="https://dbhub.ai/" target="_blank">
15
- <picture>
16
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/bytebase/dbhub/main/docs/images/logo/full-dark.svg" width="75%">
17
- <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/bytebase/dbhub/main/docs/images/logo/full-light.svg" width="75%">
18
- <img src="https://raw.githubusercontent.com/bytebase/dbhub/main/docs/images/logo/full-light.svg" width="75%" alt="DBHub Logo">
19
- </picture>
20
- </a>
21
- </p>
22
-
23
- ```bash
24
- +------------------+ +--------------+ +------------------+
25
- | | | | | |
26
- | | | | | |
27
- | Claude Desktop +--->+ +--->+ PostgreSQL |
28
- | | | | | |
29
- | Claude Code +--->+ +--->+ SQL Server |
30
- | | | | | |
31
- | Cursor +--->+ DBHub +--->+ SQLite |
32
- | | | | | |
33
- | VS Code +--->+ +--->+ MySQL |
34
- | | | | | |
35
- | Copilot CLI +--->+ +--->+ MariaDB |
36
- | | | | | |
37
- | +--->+ +--->+ Dameng / DM8 |
38
- | | | | | |
39
- +------------------+ +--------------+ +------------------+
40
- MCP Clients MCP Server Databases
1
+ # DBHub Dameng
2
+
3
+ 让 AI 直接连接达梦 DM8,查询数据、查看表结构和字段说明。
4
+ 基于 [Bytebase DBHub](https://github.com/bytebase/dbhub),增加最小达梦适配。
5
+ 使用已发布的 npm 包即可,无需克隆仓库或编译源码。
6
+
7
+ 默认只有两个 MCP 工具:
8
+
9
+ | 工具 | 用途 |
10
+ | --- | --- |
11
+ | `search_objects` | 查找 schema、表、视图、字段、索引和存储过程 |
12
+ | `execute_sql` | 执行 SQL;按下方配置只允许读取,最多返回 100 行 |
13
+
14
+ ## 最简单:把这份 README 和连接串交给 AI
15
+
16
+ 在能够读写本机项目文件的 AI 编程客户端中,发送下面这段话。
17
+ 将最后一行替换为自己的连接串;也可以提供已有本地连接配置文件的路径。
18
+
19
+ ```text
20
+ 请根据以下 README,直接帮我在当前项目配置 DBHub 达梦 MCP,并验证连接:
21
+ https://github.com/zuozh11/dbhub-dameng/blob/main/README.md
22
+
23
+ 要求:
24
+ 1. 检查 Node.js >= 22.5,以及 npm/npx 是否可用。
25
+ 2. 使用 @zz1996/dbhub-dameng@latest,以 stdio 启动。
26
+ 3. 创建本机专用的 .agents/dbhub.dameng.toml,开启 readonly = true、max_rows = 100,
27
+ 只启用 execute_sql 和 search_objects。不要执行初始化脚本。
28
+ 4. 将含真实连接串的文件排除出 Git;如果同名文件已被跟踪,改用仓库外的本地文件。
29
+ 不要把密码写进 README、提交记录或最终回复。
30
+ 5. 检查当前客户端已有的 MCP 配置,只新增或更新 DBHub 条目,保留其他配置。
31
+ --config 使用配置文件的绝对路径。能识别客户端就直接配置,无法识别时再问我。
32
+ 6. 重连 MCP,确认两个工具可用,执行 SELECT 1 AS OK FROM DUAL,
33
+ 再用 search_objects 查询当前 schema 下的一个表名;不要读取业务数据或执行写操作。
34
+ 如果无法控制客户端重连,请明确告诉我需要在哪一步重连,不要把文件写好当成连接成功。
35
+ 7. 完成后说明配置文件位置、验证结果,以及是否还需要我重启客户端。
36
+
37
+ 我的数据库连接串:dameng://user:password@host:5236/APP
41
38
  ```
42
39
 
43
- DBHub is a zero-dependency, token efficient MCP server implementing the Model Context Protocol (MCP) server interface. This lightweight gateway allows MCP-compatible clients to connect to and explore different databases:
40
+ 如果只使用普通聊天网页,AI 可以生成配置,但需要你自己保存到本机并在 MCP 客户端中启用。
41
+ 真实连接信息仅提供给你信任的客户端;共享或生产库请使用最小权限只读账号。
44
42
 
45
- - **Local Development First**: Zero dependency, token efficient with just two MCP tools to maximize context window
46
- - **Multi-Database**: PostgreSQL, MySQL, MariaDB, SQL Server, SQLite, and Dameng/DM8 through a single interface
47
- - **Multi-Connection**: Connect to multiple databases simultaneously with TOML configuration
48
- - **Guardrails**: Read-only mode, row limiting, and query timeout to prevent runaway operations
49
- - **Secure Access**: SSH tunneling and SSL/TLS encryption
43
+ ## 连接串怎么写
50
44
 
51
- ## Supported Databases
52
-
53
- PostgreSQL, MySQL, SQL Server, MariaDB, SQLite, and Dameng/DM8.
54
-
55
- ## MCP Tools
56
-
57
- DBHub implements MCP tools for database operations:
58
-
59
- - **[execute_sql](https://dbhub.ai/tools/execute-sql)**: Execute SQL queries with transaction support and safety controls
60
- - **[search_objects](https://dbhub.ai/tools/search-objects)**: Search and explore database schemas, tables, columns, indexes, and procedures with progressive disclosure
61
- - **[Custom Tools](https://dbhub.ai/tools/custom-tools)**: Define reusable, parameterized SQL operations in your `dbhub.toml` configuration file
62
-
63
- ## Workbench
64
-
65
- DBHub includes a [built-in web interface](https://dbhub.ai/workbench/overview) for interacting with your database tools. It provides a visual way to execute queries, run custom tools, and view request traces without requiring an MCP client.
66
-
67
- ![workbench](https://raw.githubusercontent.com/bytebase/dbhub/main/docs/images/workbench/workbench.webp)
45
+ ```text
46
+ dameng://用户名:密码@主机:5236/Schema名称
47
+ ```
68
48
 
69
- ## Installation
49
+ 例如下面是虚构的配置:
70
50
 
71
- See the full [Installation Guide](https://dbhub.ai/installation) for detailed instructions.
51
+ ```text
52
+ dameng://reader:example_password@127.0.0.1:5236/APP
53
+ ```
72
54
 
73
- ### Quick Start
55
+ - 默认端口为 `5236`。
56
+ - 路径中的 `APP` 是 schema,不是数据库实例名;按数据库中的实际大小写填写。
57
+ - 用户名、密码中的特殊字符要进行 URL 编码,例如 `@` → `%40`、`#` → `%23`、`/` → `%2F`。
58
+ 已编码的连接串不要重复编码。
59
+ - 启动 MCP 的电脑必须能够访问该地址;内网数据库可能需要先连接 VPN。
74
60
 
75
- **Docker:**
61
+ ## 手动配置
76
62
 
77
- ```bash
78
- docker run --rm --init \
79
- --name dbhub \
80
- --publish 8080:8080 \
81
- bytebase/dbhub \
82
- --transport http \
83
- --port 8080 \
84
- --dsn "postgres://user:password@localhost:5432/dbname?sslmode=disable"
85
- ```
63
+ ### 1. 准备 Node.js
86
64
 
87
- **NPM:** (requires Node.js >= 22.5.0)
65
+ 需要 Node.js **>= 22.5**,并能访问 npm registry:
88
66
 
89
- ```bash
90
- npx @bytebase/dbhub@latest --transport http --port 8080 --dsn "postgres://user:password@localhost:5432/dbname?sslmode=disable"
67
+ ```sh
68
+ node --version
69
+ npm --version
70
+ npx --version
91
71
  ```
92
72
 
93
- **Dameng / DM8 fork:**
94
-
95
- ```bash
96
- npx -y @zz1996/dbhub-dameng --transport stdio --config ./dbhub.dameng.toml
97
- ```
73
+ ### 2. 创建本机数据库配置
98
74
 
99
- Minimal Dameng TOML configuration:
75
+ 创建 `.agents/dbhub.dameng.toml`,替换下面的示例连接串:
100
76
 
101
77
  ```toml
102
78
  [[sources]]
103
- id = "dm8_readonly"
104
- description = "Dameng DM8 database for schema discovery and read-only SQL queries"
105
- dsn = "dameng://${DM8_USER}:${DM8_PASSWORD}@${DM8_HOST}:5236/${DM8_SCHEMA}"
106
- query_timeout = 30
107
- lazy = true
108
-
109
- [[tools]]
110
- name = "search_objects"
111
- source = "dm8_readonly"
79
+ id = "default"
80
+ dsn = "dameng://reader:example_password@127.0.0.1:5236/APP"
112
81
 
113
82
  [[tools]]
114
83
  name = "execute_sql"
115
- source = "dm8_readonly"
84
+ source = "default"
116
85
  readonly = true
117
86
  max_rows = 100
87
+
88
+ [[tools]]
89
+ name = "search_objects"
90
+ source = "default"
118
91
  ```
119
92
 
120
- To verify the local Dameng connector against a real DM8 instance without
121
- committing credentials, set `DAMENG_DSN` or point to a local TOML file:
93
+ 将 `/.agents/dbhub.dameng.toml` 加入项目的 `.gitignore`,确保该文件未被 Git 跟踪。
94
+ 已被跟踪的文件不会因加入 `.gitignore` 自动停止跟踪,此时请改用仓库外的本地配置文件。
122
95
 
123
- ```bash
124
- DAMENG_DSN="dameng://user:password@host:5236/schema" pnpm verify:dameng
125
- pnpm verify:dameng -- --config ./dbhub.dameng.toml --source dm8_readonly
126
- ```
96
+ 也可以使用 `dsn = "${DAMENG_DSN}"`,由客户端向 MCP 进程传入环境变量。
97
+ 不要假设从桌面打开的客户端会继承终端里临时 `export` 的变量。
127
98
 
128
- **Demo Mode:**
99
+ ### 3. 添加到 MCP 客户端
129
100
 
130
- ```bash
131
- npx @bytebase/dbhub@latest --transport http --port 8080 --demo
132
- ```
101
+ 以下示例中的 `/absolute/path/to/project/.agents/dbhub.dameng.toml`
102
+ 必须替换为上一步文件的**绝对路径**。已有配置请合并,不要覆盖整个文件。
103
+
104
+ **使用 `mcpServers` JSON 格式的客户端:**
133
105
 
134
- **Restrict to loopback (recommended for production):**
106
+ 将下面条目合并到客户端的 MCP 配置中;不同客户端的配置文件位置由客户端决定。
135
107
 
136
- ```bash
137
- npx @bytebase/dbhub@latest --transport http --host 127.0.0.1 --port 8080 --demo
108
+ ```json
109
+ {
110
+ "mcpServers": {
111
+ "dbhub": {
112
+ "command": "npx",
113
+ "args": [
114
+ "--yes",
115
+ "@zz1996/dbhub-dameng@latest",
116
+ "--transport", "stdio",
117
+ "--config", "/absolute/path/to/project/.agents/dbhub.dameng.toml"
118
+ ]
119
+ }
120
+ }
121
+ }
138
122
  ```
139
123
 
140
- > The HTTP transport defaults to `--host 0.0.0.0`, exposing DBHub on every network interface. For production, bind to `127.0.0.1` and front DBHub with a reverse proxy (nginx/Caddy) or firewall — DBHub does not authenticate HTTP clients.
141
- >
142
- > The HTTP transport also has built-in DNS-rebinding protection: it only accepts requests whose `Host` is loopback, this machine's own hostname/IPs, or a name you allow via [`--allowed-hosts`](https://dbhub.ai/config/command-line#allowed-hosts). If a client behind a reverse proxy or custom DNS name gets a `403`, add that hostname with `--allowed-hosts`.
124
+ **Codex:**
143
125
 
144
- See [Command-Line Options](https://dbhub.ai/config/command-line) for all available parameters.
126
+ 将下面内容合并到项目的 `.codex/config.toml`(项目需受信任),
127
+ 或用户级的 `~/.codex/config.toml`:
145
128
 
146
- ### Multi-Database Setup
129
+ ```toml
130
+ [mcp_servers.dbhub]
131
+ command = "npx"
132
+ args = ["--yes", "@zz1996/dbhub-dameng@latest", "--transport", "stdio", "--config", "/absolute/path/to/project/.agents/dbhub.dameng.toml"]
133
+ ```
147
134
 
148
- Connect to multiple databases simultaneously using TOML configuration files. Perfect for managing production, staging, and development databases from a single DBHub instance.
135
+ 配置位置和字段可参考 [Codex 官方 MCP 文档](https://developers.openai.com/zh-Hans/docs/extend/mcp)。
136
+ Windows 上若客户端无法直接启动 `npx`,可将 `command` 改为 `npx.cmd`;
137
+ TOML/JSON 中的 Windows 路径可以使用正斜杠,例如 `C:/projects/app/.agents/dbhub.dameng.toml`。
149
138
 
150
- See [Multi-Database Configuration](https://dbhub.ai/config/toml) for complete setup instructions.
139
+ ### 4. 重连并验证
151
140
 
152
- ## Development
141
+ 在客户端重新连接 MCP,必要时重启客户端。第一次启动需要下载 npm 包。
142
+ 让 AI 执行:
153
143
 
154
- Requires Node.js >= 22.5.0 (DBHub uses the built-in `node:sqlite` module).
144
+ ```text
145
+ 请用 execute_sql 执行 SELECT 1 AS OK FROM DUAL,
146
+ 再用 search_objects 查看当前 schema 的一个表名(object_type=table、detail_level=names、limit=1)。
147
+ ```
155
148
 
156
- ```bash
157
- # Install dependencies
158
- pnpm install
149
+ 看到 SQL 返回 `OK = 1`,且对象查询没有连接错误,即完成基本连通性验证。
150
+ schema 中没有可见表时可以返回空列表。检索字段或索引时,应同时提供 `schema` 和 `table`。
159
151
 
160
- # Run in development mode
161
- pnpm dev
152
+ 终端排查启动问题时,也可以直接运行:
162
153
 
163
- # Build and run for production
164
- pnpm build && pnpm start --transport stdio --dsn "postgres://user:password@localhost:5432/dbname"
154
+ ```sh
155
+ npx --yes @zz1996/dbhub-dameng@latest --transport stdio --config /absolute/path/to/project/.agents/dbhub.dameng.toml
165
156
  ```
166
157
 
167
- See [Testing](.claude/skills/testing/SKILL.md) and [Debug](https://dbhub.ai/config/debug).
158
+ stdio 模式启动后等待 MCP 客户端请求是正常行为,这不是 SQL 交互终端;单纯启动不代表数据库查询已验证。
168
159
 
169
- ## Contributors
160
+ ## 更新与边界
170
161
 
171
- <a href="https://github.com/bytebase/dbhub/graphs/contributors">
172
- <img src="https://contrib.rocks/image?repo=bytebase/dbhub" />
173
- </a>
162
+ - 使用 `@latest` 的配置在重新启动 MCP 时获取当前版本;已经运行的进程不会热更新。
163
+ - 需要固定版本时,将 `@latest` 换成明确的 npm 版本号。
164
+ - 只读模式不能替代数据库权限,尤其不能隔离数据库函数内部的副作用。
165
+ - 达梦版覆盖普通 SQL 与元数据浏览;不支持包含内部分号的匿名 PL/SQL 块,
166
+ 暂不提供达梦的 `explain_sql`、`health_check`。
174
167
 
175
- ## Star History
168
+ [npm 包](https://www.npmjs.com/package/@zz1996/dbhub-dameng) ·
169
+ [开发与自动发布说明](https://github.com/zuozh11/dbhub-dameng/blob/main/DAMENG.md) ·
170
+ [上游 DBHub](https://github.com/bytebase/dbhub)
176
171
 
177
- <a href="https://www.star-history.com/?repos=bytebase%2Fdbhub&type=date&legend=top-left">
178
- <picture>
179
- <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=bytebase/dbhub&type=date&theme=dark&legend=top-left" />
180
- <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=bytebase/dbhub&type=date&legend=top-left" />
181
- <img alt="Star History Chart" src="https://api.star-history.com/chart?repos=bytebase/dbhub&type=date&legend=top-left" />
182
- </picture>
183
- </a>
172
+ 本项目沿用上游 MIT 许可证,详见 [LICENSE](https://github.com/zuozh11/dbhub-dameng/blob/main/LICENSE)。
@@ -1,20 +1,13 @@
1
- # Example DBHub configuration for the local Dameng/DM8 fork.
2
- # Do not commit real credentials. Prefer environment variables.
3
-
4
1
  [[sources]]
5
- id = "dm8_dev"
6
- description = "Dameng DM8 development database. Read-only access for agent schema discovery and SQL queries."
7
- dsn = "dameng://${DM8_USER}:${DM8_PASSWORD}@${DM8_HOST}:5236/${DM8_SCHEMA}"
8
- connection_timeout = 5
9
- query_timeout = 30
10
- lazy = true
2
+ id = "default"
3
+ dsn = "${DAMENG_DSN}"
11
4
 
12
5
  [[tools]]
13
6
  name = "execute_sql"
14
- source = "dm8_dev"
7
+ source = "default"
15
8
  readonly = true
16
9
  max_rows = 100
17
10
 
18
11
  [[tools]]
19
12
  name = "search_objects"
20
- source = "dm8_dev"
13
+ source = "default"
@@ -91,7 +91,9 @@ var SafeURL = class {
91
91
  }
92
92
  });
93
93
  }
94
- const atIndex = urlString.indexOf("@");
94
+ const pathStart = urlString.indexOf("/");
95
+ const authorityEnd = pathStart === -1 ? urlString.length : pathStart;
96
+ const atIndex = urlString.lastIndexOf("@", authorityEnd - 1);
95
97
  if (atIndex !== -1) {
96
98
  const auth = urlString.substring(0, atIndex);
97
99
  urlString = urlString.substring(atIndex + 1);
@@ -143,118 +145,6 @@ var SafeURL = class {
143
145
  }
144
146
  };
145
147
 
146
- // src/utils/dsn-obfuscate.ts
147
- function parseConnectionInfoFromDSN(dsn) {
148
- if (!dsn) {
149
- return null;
150
- }
151
- try {
152
- const type = getDatabaseTypeFromDSN(dsn);
153
- if (typeof type === "undefined") {
154
- return null;
155
- }
156
- if (type === "sqlite") {
157
- const prefix = "sqlite:///";
158
- if (dsn.length > prefix.length) {
159
- const rawPath = dsn.substring(prefix.length);
160
- const firstChar = rawPath[0];
161
- const isWindowsDrive = rawPath.length > 1 && rawPath[1] === ":";
162
- const isSpecialPath = firstChar === ":" || firstChar === "." || firstChar === "~" || isWindowsDrive;
163
- return {
164
- type,
165
- database: isSpecialPath ? rawPath : "/" + rawPath
166
- };
167
- }
168
- return { type };
169
- }
170
- const url = new SafeURL(dsn);
171
- const info = { type };
172
- if (url.hostname) {
173
- info.host = url.hostname;
174
- }
175
- if (url.port) {
176
- info.port = parseInt(url.port, 10);
177
- }
178
- if (url.pathname && url.pathname.length > 1) {
179
- info.database = url.pathname.substring(1);
180
- }
181
- if (url.username) {
182
- info.user = url.username;
183
- }
184
- return info;
185
- } catch {
186
- return null;
187
- }
188
- }
189
- function obfuscateDSNPassword(dsn) {
190
- if (!dsn) {
191
- return dsn;
192
- }
193
- try {
194
- const type = getDatabaseTypeFromDSN(dsn);
195
- if (type === "sqlite") {
196
- return dsn;
197
- }
198
- const url = new SafeURL(dsn);
199
- if (!url.password) {
200
- return dsn;
201
- }
202
- const obfuscatedPassword = "*".repeat(Math.min(url.password.length, 8));
203
- const protocol = dsn.split(":")[0];
204
- let result;
205
- if (url.username) {
206
- result = `${protocol}://${url.username}:${obfuscatedPassword}@${url.hostname}`;
207
- } else {
208
- result = `${protocol}://${obfuscatedPassword}@${url.hostname}`;
209
- }
210
- if (url.port) {
211
- result += `:${url.port}`;
212
- }
213
- result += url.pathname;
214
- if (url.searchParams.size > 0) {
215
- const params = [];
216
- url.forEachSearchParam((value, key) => {
217
- params.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
218
- });
219
- result += `?${params.join("&")}`;
220
- }
221
- return result;
222
- } catch {
223
- return dsn;
224
- }
225
- }
226
- function getDatabaseTypeFromDSN(dsn) {
227
- if (!dsn) {
228
- return void 0;
229
- }
230
- const protocol = dsn.split(":")[0];
231
- return protocolToConnectorType(protocol);
232
- }
233
- function protocolToConnectorType(protocol) {
234
- const mapping = {
235
- "postgres": "postgres",
236
- "postgresql": "postgres",
237
- "mysql": "mysql",
238
- "mariadb": "mariadb",
239
- "sqlserver": "sqlserver",
240
- "sqlite": "sqlite",
241
- "dameng": "dameng",
242
- "dm": "dameng"
243
- };
244
- return mapping[protocol];
245
- }
246
- function getDefaultPortForType(type) {
247
- const ports = {
248
- "postgres": 5432,
249
- "mysql": 3306,
250
- "mariadb": 3306,
251
- "sqlserver": 1433,
252
- "sqlite": void 0,
253
- "dameng": 5236
254
- };
255
- return ports[type];
256
- }
257
-
258
148
  // src/utils/sql-parser.ts
259
149
  var TokenType = { Plain: 0, Comment: 1, QuotedBlock: 2 };
260
150
  function plainToken(i) {
@@ -431,12 +321,12 @@ function scanTokenSQLServer(sql, i) {
431
321
  return scanSingleLineComment(sql, i) ?? scanMultiLineComment(sql, i) ?? scanSingleQuotedString(sql, i) ?? scanDoubleQuotedString(sql, i) ?? scanBracketQuotedIdentifier(sql, i) ?? plainToken(i);
432
322
  }
433
323
  var dialectScanners = {
324
+ dameng: scanTokenAnsi,
434
325
  postgres: scanTokenPostgres,
435
326
  mysql: scanTokenMySQL,
436
327
  mariadb: scanTokenMySQL,
437
328
  sqlite: scanTokenSQLite,
438
- sqlserver: scanTokenSQLServer,
439
- dameng: scanTokenAnsi
329
+ sqlserver: scanTokenSQLServer
440
330
  };
441
331
  function getScanner(dialect) {
442
332
  return dialect ? dialectScanners[dialect] ?? scanTokenAnsi : scanTokenAnsi;
@@ -466,6 +356,21 @@ function stripCommentsAndStrings(sql, dialect) {
466
356
  }
467
357
  return parts.join("");
468
358
  }
359
+ function blankCommentsAndStrings(sql, dialect) {
360
+ const scanToken = getScanner(dialect);
361
+ let result = "";
362
+ let i = 0;
363
+ while (i < sql.length) {
364
+ const token = scanToken(sql, i);
365
+ if (token.type === TokenType.Plain) {
366
+ result += sql[i];
367
+ } else {
368
+ result += " ".repeat(token.end - i);
369
+ }
370
+ i = token.end;
371
+ }
372
+ return result;
373
+ }
469
374
  function splitSQLStatements(sql, dialect) {
470
375
  const scanToken = getScanner(dialect);
471
376
  const statements = [];
@@ -494,10 +399,7 @@ function splitSQLStatements(sql, dialect) {
494
399
  export {
495
400
  ConnectorRegistry,
496
401
  SafeURL,
497
- parseConnectionInfoFromDSN,
498
- obfuscateDSNPassword,
499
- getDatabaseTypeFromDSN,
500
- getDefaultPortForType,
501
402
  stripCommentsAndStrings,
403
+ blankCommentsAndStrings,
502
404
  splitSQLStatements
503
405
  };
@@ -0,0 +1,121 @@
1
+ import {
2
+ SafeURL
3
+ } from "./chunk-2JL4KCP5.js";
4
+
5
+ // src/utils/dsn-obfuscate.ts
6
+ function parseConnectionInfoFromDSN(dsn) {
7
+ if (!dsn) {
8
+ return null;
9
+ }
10
+ try {
11
+ const type = getDatabaseTypeFromDSN(dsn);
12
+ if (typeof type === "undefined") {
13
+ return null;
14
+ }
15
+ if (type === "sqlite") {
16
+ const prefix = "sqlite:///";
17
+ if (dsn.length > prefix.length) {
18
+ const rawPath = dsn.substring(prefix.length);
19
+ const firstChar = rawPath[0];
20
+ const isWindowsDrive = rawPath.length > 1 && rawPath[1] === ":";
21
+ const isSpecialPath = firstChar === ":" || firstChar === "." || firstChar === "~" || isWindowsDrive;
22
+ return {
23
+ type,
24
+ database: isSpecialPath ? rawPath : "/" + rawPath
25
+ };
26
+ }
27
+ return { type };
28
+ }
29
+ const url = new SafeURL(dsn);
30
+ const info = { type };
31
+ if (url.hostname) {
32
+ info.host = url.hostname;
33
+ }
34
+ if (url.port) {
35
+ info.port = parseInt(url.port, 10);
36
+ }
37
+ if (url.pathname && url.pathname.length > 1) {
38
+ info.database = url.pathname.substring(1);
39
+ }
40
+ if (url.username) {
41
+ info.user = url.username;
42
+ }
43
+ return info;
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+ function obfuscateDSNPassword(dsn) {
49
+ if (!dsn) {
50
+ return dsn;
51
+ }
52
+ try {
53
+ const type = getDatabaseTypeFromDSN(dsn);
54
+ if (type === "sqlite") {
55
+ return dsn;
56
+ }
57
+ const url = new SafeURL(dsn);
58
+ if (!url.password) {
59
+ return dsn;
60
+ }
61
+ const obfuscatedPassword = "*".repeat(Math.min(url.password.length, 8));
62
+ const protocol = dsn.split(":")[0];
63
+ let result;
64
+ if (url.username) {
65
+ result = `${protocol}://${url.username}:${obfuscatedPassword}@${url.hostname}`;
66
+ } else {
67
+ result = `${protocol}://${obfuscatedPassword}@${url.hostname}`;
68
+ }
69
+ if (url.port) {
70
+ result += `:${url.port}`;
71
+ }
72
+ result += url.pathname;
73
+ if (url.searchParams.size > 0) {
74
+ const params = [];
75
+ url.forEachSearchParam((value, key) => {
76
+ params.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
77
+ });
78
+ result += `?${params.join("&")}`;
79
+ }
80
+ return result;
81
+ } catch {
82
+ return dsn;
83
+ }
84
+ }
85
+ function getDatabaseTypeFromDSN(dsn) {
86
+ if (!dsn) {
87
+ return void 0;
88
+ }
89
+ const protocol = dsn.split(":")[0];
90
+ return protocolToConnectorType(protocol);
91
+ }
92
+ function protocolToConnectorType(protocol) {
93
+ const mapping = {
94
+ "dameng": "dameng",
95
+ "postgres": "postgres",
96
+ "postgresql": "postgres",
97
+ "mysql": "mysql",
98
+ "mariadb": "mariadb",
99
+ "sqlserver": "sqlserver",
100
+ "sqlite": "sqlite"
101
+ };
102
+ return mapping[protocol];
103
+ }
104
+ function getDefaultPortForType(type) {
105
+ const ports = {
106
+ "dameng": 5236,
107
+ "postgres": 5432,
108
+ "mysql": 3306,
109
+ "mariadb": 3306,
110
+ "sqlserver": 1433,
111
+ "sqlite": void 0
112
+ };
113
+ return ports[type];
114
+ }
115
+
116
+ export {
117
+ parseConnectionInfoFromDSN,
118
+ obfuscateDSNPassword,
119
+ getDatabaseTypeFromDSN,
120
+ getDefaultPortForType
121
+ };