feat(core): split foundational capabilities into dedicated crates

This commit is contained in:
t8y2
2026-09-18 13:00:56 +08:00
parent d50f5175d6
commit bc00431834
402 changed files with 4386 additions and 3367 deletions
+4 -2
View File
@@ -30,6 +30,8 @@ export const STATIC_LABEL_SPECS = {
"tests-only": { color: "bfd4f2", description: "Changes only tests, fixtures, or snapshots" },
};
const CORE_CRATE_PATH = /^crates\/dbx-(?:core|drivers|sql|formats|types|platform|ai-provider|plugin-runtime)\//;
const TYPE_LABELS = new Set(["bug", "enhancement", "documentation", "maintenance"]);
const LABEL_PALETTE = [
"0e8a16",
@@ -133,7 +135,7 @@ export function inferAreaLabels(changedFiles) {
|| file.startsWith("src-tauri/"))) {
labels.add("area/desktop");
}
if (has((file) => file.startsWith("crates/dbx-core/") || file.startsWith("packages/node-core/"))) {
if (has((file) => CORE_CRATE_PATH.test(file) || file.startsWith("packages/node-core/"))) {
labels.add("area/core");
}
if (has((file) => file.startsWith("crates/dbx-web/") || file.startsWith("examples/web-api/"))) {
@@ -220,7 +222,7 @@ export function inferDatabaseTypes(changedFiles, knownDatabaseTypes) {
if (file.startsWith("plugins/jdbc/")) add("jdbc");
if (file.startsWith("apps/desktop/src/") || file.startsWith("crates/dbx-core/src/")) {
if (file.startsWith("apps/desktop/src/") || CORE_CRATE_PATH.test(file)) {
for (const [pattern, databaseType] of DATABASE_PATH_TOKENS) {
if (pattern.test(file)) add(databaseType);
}
+20 -1
View File
@@ -104,13 +104,32 @@ test("recognizes conventional titles with a full-width colon", () => {
assert.deepEqual(result.labels, ["area/core", "bug"]);
});
test("recognizes extracted core crates and their database sources", () => {
const result = evaluatePullRequestLabels({
title: "fix(sql): preserve PostgreSQL query contracts",
changedFiles: [
"crates/dbx-drivers/src/db/postgres.rs",
"crates/dbx-sql/src/sql.rs",
"crates/dbx-types/src/types.rs",
"crates/dbx-platform/src/process.rs",
"crates/dbx-ai-provider/src/ai.rs",
"crates/dbx-formats/src/csv_export.rs",
"crates/dbx-plugin-runtime/src/plugins.rs",
],
knownDatabaseTypes,
});
assert.deepEqual(result.labels, ["area/core", "bug", "db/postgres"]);
assert.deepEqual(result.databaseTypes, ["postgres"]);
});
test("collapses broad area and database changes", () => {
const result = evaluatePullRequestLabels({
title: "feat: add cross-runtime geometry support",
changedFiles: [
"agents/drivers/mysql/build.gradle",
"apps/desktop/src/components/grid/GeometryViewer.vue",
"crates/dbx-core/src/db/postgres.rs",
"crates/dbx-drivers/src/db/postgres.rs",
"crates/dbx-mcp/src/main.rs",
"crates/dbx-web/src/main.rs",
"docs/content/docs/geometry.mdx",
+17 -3
View File
@@ -324,6 +324,9 @@ jobs:
# PR caches are large and branch-scoped; restore them from main without saving per-PR copies.
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Core architecture contracts
run: node --test scripts/core-architecture.test.mjs
- name: Cargo fmt check
run: cargo fmt --check
@@ -555,7 +558,13 @@ jobs:
- 'package.json'
- '.oxfmtrc.json'
- 'scripts/run-check.mjs'
- 'crates/dbx-core/src/docs/**'
- 'crates/dbx-core/src/**'
- 'crates/dbx-drivers/src/**'
- 'crates/dbx-sql/src/**'
- 'crates/dbx-formats/src/**'
- 'crates/dbx-types/src/**'
- 'crates/dbx-plugin-runtime/src/**'
- 'crates/dbx-ai-provider/**'
- 'crates/dbx-core/assets/docs-export.*'
- '.github/workflows/ci.yml'
packages:
@@ -571,6 +580,9 @@ jobs:
- '.github/workflows/ci.yml'
rust:
- 'crates/**'
- 'plugins/connection-types/**'
- 'plugins/dialects/**'
- 'scripts/core-architecture.test.mjs'
- 'src-tauri/**'
- 'vendor/**'
- 'Cargo.toml'
@@ -590,6 +602,7 @@ jobs:
- '.github/workflows/ci.yml'
agents:
- 'agents/**'
- 'crates/dbx-drivers/assets/agent-protocol-v2.json'
- 'crates/dbx-core/Cargo.toml'
- 'Cargo.toml'
- 'Cargo.lock'
@@ -631,8 +644,9 @@ jobs:
- 'src-tauri/windows/nsis/**'
- 'src-tauri/src/commands/update.rs'
- 'crates/dbx-core/Cargo.toml'
- 'crates/dbx-core/src/db/postgres.rs'
- 'crates/dbx-core/src/update.rs'
- 'crates/dbx-drivers/**'
- 'crates/dbx-platform/**'
- 'crates/dbx-core/src/host/update.rs'
- 'Cargo.toml'
- 'Cargo.lock'
- 'vendor/ctor/**'
Generated
+165 -21
View File
@@ -2076,6 +2076,24 @@ dependencies = [
"zip",
]
[[package]]
name = "dbx-ai-provider"
version = "0.1.0"
dependencies = [
"base64 0.22.1",
"bytes",
"dbx-platform",
"futures",
"httpdate",
"log",
"reqwest 0.12.28",
"serde",
"serde_json",
"tempfile",
"tokio",
"uuid",
]
[[package]]
name = "dbx-cli"
version = "0.4.90"
@@ -2096,11 +2114,9 @@ version = "0.1.0"
dependencies = [
"aes 0.8.4",
"aes-gcm 0.10.3",
"anyhow",
"arc-swap",
"argon2",
"async-trait",
"aws-sdk-dynamodb",
"base64 0.22.1",
"bytes",
"calamine",
@@ -2108,31 +2124,27 @@ dependencies = [
"chrono",
"crc",
"csv",
"dbx-sqlite-worker",
"dbx-ai-provider",
"dbx-drivers",
"dbx-formats",
"dbx-platform",
"dbx-plugin-runtime",
"dbx-sql",
"dbx-types",
"deadpool-postgres",
"ed25519-dalek 2.2.0",
"encoding_rs",
"flate2",
"font-kit",
"fs2",
"futures",
"httpdate",
"insta",
"json5",
"jsonwebtoken",
"libsqlite3-hotbundle",
"log",
"minijinja",
"mongodb",
"mysql_async",
"mysql_common",
"nix",
"notify",
"openssl",
"pageant",
"percent-encoding",
"portpicker",
"postgres-openssl",
"prometheus-parse",
"quick-xml 0.37.5",
"rayon",
@@ -2141,14 +2153,10 @@ dependencies = [
"reqwest 0.12.28",
"rumqttc",
"rusqlite",
"russh",
"rust_decimal",
"rustls 0.23.43",
"rustls-pemfile 2.2.0",
"semver",
"serde",
"serde_json",
"serde_yaml",
"serde_yaml_ng",
"sha1 0.10.7",
"sha2 0.10.9",
@@ -2157,6 +2165,59 @@ dependencies = [
"sysinfo",
"tar",
"tempfile",
"tokio",
"tokio-postgres",
"tokio-util",
"uuid",
"webpki-roots 0.26.11",
"windows-sys 0.61.2",
"zip",
"zstd",
]
[[package]]
name = "dbx-drivers"
version = "0.1.0"
dependencies = [
"aws-sdk-dynamodb",
"base64 0.22.1",
"bytes",
"chrono",
"crc",
"csv",
"dbx-platform",
"dbx-sql",
"dbx-sqlite-worker",
"dbx-types",
"deadpool-postgres",
"flate2",
"futures",
"json5",
"libsqlite3-hotbundle",
"log",
"mongodb",
"mysql_async",
"mysql_common",
"nix",
"openssl",
"pageant",
"percent-encoding",
"portpicker",
"postgres-openssl",
"redis",
"regex",
"reqwest 0.12.28",
"rusqlite",
"russh",
"rust_decimal",
"rustls 0.23.43",
"rustls-pemfile 2.2.0",
"serde",
"serde_json",
"sha2 0.10.9",
"sqlparser",
"tar",
"tempfile",
"tiberius",
"tokio",
"tokio-openssl",
@@ -2165,17 +2226,26 @@ dependencies = [
"tokio-util",
"tracing",
"tracing-subscriber",
"unicode-ident",
"unicode-width",
"utoipa",
"uuid",
"webpki-roots 0.26.11",
"windows-sys 0.61.2",
"winnow 1.0.4",
"zip",
"zstd",
]
[[package]]
name = "dbx-formats"
version = "0.1.0"
dependencies = [
"calamine",
"chrono",
"serde",
"serde_json",
"tempfile",
"uuid",
"zip",
]
[[package]]
name = "dbx-mcp"
version = "0.4.90"
@@ -2201,6 +2271,68 @@ dependencies = [
"uuid",
]
[[package]]
name = "dbx-platform"
version = "0.1.0"
dependencies = [
"futures",
"nix",
"reqwest 0.12.28",
"serde",
"tokio",
"uuid",
]
[[package]]
name = "dbx-plugin-runtime"
version = "0.1.0"
dependencies = [
"base64 0.22.1",
"bytes",
"chrono",
"dbx-platform",
"dbx-types",
"ed25519-dalek 2.2.0",
"fs2",
"futures",
"log",
"reqwest 0.12.28",
"semver",
"serde",
"serde_json",
"sha2 0.10.9",
"tempfile",
"tokio",
"uuid",
"zip",
]
[[package]]
name = "dbx-sql"
version = "0.1.0"
dependencies = [
"chrono",
"dbx-types",
"encoding_rs",
"insta",
"log",
"notify",
"percent-encoding",
"rayon",
"regex",
"rusqlite",
"serde",
"serde_json",
"serde_yaml",
"sqlparser",
"tempfile",
"tokio",
"unicode-ident",
"unicode-width",
"utoipa",
"winnow 1.0.4",
]
[[package]]
name = "dbx-sqlite-worker"
version = "0.1.1"
@@ -2211,6 +2343,18 @@ dependencies = [
"sqlparser",
]
[[package]]
name = "dbx-types"
version = "0.1.0"
dependencies = [
"percent-encoding",
"serde",
"serde_json",
"serde_yaml_ng",
"utoipa",
"uuid",
]
[[package]]
name = "dbx-web"
version = "0.6.16"
+1 -1
View File
@@ -1,6 +1,6 @@
[workspace]
resolver = "2"
members = ["src-tauri", "crates/dbx-core", "crates/dbx-web", "crates/dbx-mcp", "crates/dbx-cli", "crates/dbx-sqlite-worker"]
members = ["src-tauri", "crates/dbx-core", "crates/dbx-drivers", "crates/dbx-sql", "crates/dbx-plugin-runtime", "crates/dbx-formats", "crates/dbx-types", "crates/dbx-platform", "crates/dbx-ai-provider", "crates/dbx-web", "crates/dbx-mcp", "crates/dbx-cli", "crates/dbx-sqlite-worker"]
exclude = ["vendor/tauri-plugin-updater", "vendor/ctor", "vendor/dirs-sys", "vendor/pageant", "vendor/rumqttc", "vendor/tiberius", "vendor/wry"]
[patch.crates-io]
@@ -7,7 +7,7 @@ import java.util.List;
/**
* Decode PostGIS EWKB / WKB byte streams (and PGgeometry / hex strings) into
* OGC Well-Known Text. Behaves identically to the Rust implementation in
* {@code crates/dbx-core/src/db/postgres.rs::ewkb_to_wkt}, including the
* {@code crates/dbx-drivers/src/db/postgres.rs::ewkb_to_wkt}, including the
* {@code Z} / {@code M} / {@code ZM} dimension suffixes and {@code EMPTY}
* geometries. Used by the JDBC agent layer so that PostgresLike databases
* such as HighGo / KingBase / Vastbase / openGauss / GaussDB return WKT for
@@ -79,7 +79,7 @@ public abstract class PostgresLikeAgent extends AbstractJdbcAgent {
/**
* Wrap {@link AbstractJdbcAgent#resultValue} so PostGIS-style {@code geometry}
* and {@code geography} columns are decoded into WKT (matching the native
* tokio_postgres path in {@code crates/dbx-core/src/db/postgres.rs}).
* tokio_postgres path in {@code crates/dbx-drivers/src/db/postgres.rs}).
*/
private JdbcExecutor.ColumnAwareResultValueReader geometryAwareResolver() {
return (rs, index, sqlType, columnTypeName) -> {
@@ -22,7 +22,7 @@ class EwkbWktDecoderTest {
// ──────────────────────────────────────────────────────────────────────
// Cross-checked against the Rust ewkb_to_wkt tests in
// crates/dbx-core/src/db/postgres.rs (same hex inputs, same expected WKT).
// crates/dbx-drivers/src/db/postgres.rs (same hex inputs, same expected WKT).
// ──────────────────────────────────────────────────────────────────────
@Test
@@ -4413,7 +4413,7 @@ function globalInstructionsTooLong(): boolean {
}
// Agent turn limit for DBX's API-backed agent loop. CLI providers enforce their own limits.
// Mirrors DEFAULT/MIN/MAX_MAX_AGENT_TURNS in crates/dbx-core/src/agent_loop.rs —
// Mirrors DEFAULT/MIN/MAX_MAX_AGENT_TURNS in crates/dbx-core/src/ai/agent_loop.rs —
// keep in sync; the backend clamp on save/load is the actual source of truth.
const editMaxAgentTurns = ref<number | undefined>(undefined);
const maxAgentTurnsSaving = ref(false);
@@ -1001,7 +1001,7 @@ describe("RedisKeyBrowser continuation ownership (issue #7779)", () => {
// `iterations` (aka `max_iterations`) is the 6th positional arg the frontend
// sends to `redisScanKeysBatch` — the same unit the backend spends as real
// Redis SCAN calls (see `crates/dbx-core/src/db/redis_driver.rs`).
// Redis SCAN calls (see `crates/dbx-drivers/src/db/redis_driver.rs`).
function totalIterationsRequested(): number {
return mocks.redisScanKeysBatch.mock.calls.reduce((sum: number, call: unknown[]) => sum + (call[5] as number), 0);
}
@@ -220,7 +220,7 @@ describe("useSidebarTableMutationRuntime SAP HANA schema-scoped actions", () =>
it("classifies a JDBC-agent-routed timeout (SAP HANA/Oracle/DB2/SQL Server) as timed-out, not failed, even though its message has no timeout wording", async () => {
const { feature } = runtime("");
// AgentCallError::Timeout carries no `detail` (crates/dbx-core/src/backend_error.rs),
// AgentCallError::Timeout carries no `detail` (crates/dbx-drivers/src/backend_error.rs),
// so BackendErrorException.message degrades to a generic fallback with no
// "timed out" text — only the structured backendError distinguishes it.
const agentTimeoutError = {
@@ -2,7 +2,7 @@
* Issue #6189 — SQL Server "focus jumps to the message result".
*
* Background:
* - `crates/dbx-core/src/db/sqlserver.rs:523-542` synthesizes a pseudo result with a
* - `crates/dbx-drivers/src/db/sqlserver.rs:523-542` synthesizes a pseudo result with a
* single "Message" column and `server_message: true` for any batch segment that
* produced only server messages (PRINT / "DBCC execution completed" / ...).
* - `stores/queryStore.ts:4727` then picks the first result that HAS COLUMNS as the
+1 -1
View File
@@ -7,7 +7,7 @@ import { ANNOTATION_FILE_KEYS, COLUMN_ANNOTATION_KEYS, GROUP_ANNOTATION_KEYS, PR
// that Rust does not declare turns every save into a deserialization error at
// runtime. vue-tsc cannot see across the language boundary, so this reads the
// Rust source and compares the field sets directly.
const rustSource = readFileSync(path.resolve(__dirname, "../../../../../crates/dbx-core/src/docs/annotations.rs"), "utf8");
const rustSource = readFileSync(path.resolve(__dirname, "../../../../../crates/dbx-core/src/data/docs/annotations.rs"), "utf8");
function rustFields(structName: string): string[] {
const start = rustSource.indexOf(`pub struct ${structName} {`);
+1 -1
View File
@@ -1,4 +1,4 @@
// Mirrors crates/dbx-core/src/docs/snapshot.rs. There is no Rust->TS codegen
// Mirrors crates/dbx-core/src/data/docs/snapshot.rs. There is no Rust->TS codegen
// in this repo, so this file is maintained by hand — see
// __tests__/fixtureConformance.spec.ts, which validates it against a snapshot
// generated by the real Rust code and fails if the two drift apart.
+11 -11
View File
@@ -46,7 +46,7 @@ const STRUCTURED_BACKEND_ERROR_KEYS = [
"backendErrors.unknown",
] as const;
// Reproduces the exact string crates/dbx-core/src/agent_service.rs builds on
// Reproduces the exact string crates/dbx-drivers/src/agent_service.rs builds on
// Windows: `\` line continuations strip the newline plus the following indent.
const WINDOWS_JRE_REMOVE_ERROR = [
"Failed to remove the old JRE directory: C:\\dbx\\jre21",
@@ -123,7 +123,7 @@ const CASES: { name: string; message: string; key: string; params?: Record<strin
key: "mongo.import.legacyInsertUnsupported",
},
{
// crates/dbx-core/src/mongodb_import_export.rs attributes a batch-level failure to a row.
// crates/dbx-core/src/data/mongodb_import_export.rs attributes a batch-level failure to a row.
name: "MongoDB Legacy insertMany unsupported on a located row",
message: "row 1: MongoDB Legacy Agent does not support insertMany; upgrade or reinstall the MongoDB Legacy driver",
key: "mongo.import.legacyInsertUnsupported",
@@ -602,15 +602,15 @@ describe("backend error wording is pinned to the Rust sources", () => {
const rust = (path: string) => readFileSync(new URL(`../../../../../${path}`, import.meta.url), "utf8");
test.each([
["crates/dbx-core/src/query_result_export.rs", "Streaming export is unsupported for this query. Simplify it or use a supported driver."],
["crates/dbx-core/src/query_result_export.rs", "Streaming export needs a result-set session, but this driver returned no session_id."],
["crates/dbx-core/src/mongodb_import_export.rs", "MongoDB Legacy Agent does not support insertMany; upgrade or reinstall the MongoDB Legacy driver"],
["crates/dbx-core/src/mongodb_import_export.rs", "MongoDB Legacy Agent returned an invalid find cursor"],
["crates/dbx-core/src/mongo_ops.rs", "MongoDB Legacy Agent rejected "],
["crates/dbx-core/src/agent_service.rs", "Failed to remove the old JRE directory: "],
["crates/dbx-core/src/agent_service.rs", "is in use by drivers: "],
["crates/dbx-core/src/agent_service.rs", "agent-registry.json not found in the ZIP; not a valid offline driver package."],
["crates/dbx-core/src/mq/adapters/kafka.rs", "Kafka does not support unloading topics"],
["crates/dbx-core/src/data/query_result_export.rs", "Streaming export is unsupported for this query. Simplify it or use a supported driver."],
["crates/dbx-core/src/data/query_result_export.rs", "Streaming export needs a result-set session, but this driver returned no session_id."],
["crates/dbx-core/src/data/mongodb_import_export.rs", "MongoDB Legacy Agent does not support insertMany; upgrade or reinstall the MongoDB Legacy driver"],
["crates/dbx-core/src/data/mongodb_import_export.rs", "MongoDB Legacy Agent returned an invalid find cursor"],
["crates/dbx-core/src/query/mongo_ops.rs", "MongoDB Legacy Agent rejected "],
["crates/dbx-drivers/src/agent_service.rs", "Failed to remove the old JRE directory: "],
["crates/dbx-drivers/src/agent_service.rs", "is in use by drivers: "],
["crates/dbx-drivers/src/agent_service.rs", "agent-registry.json not found in the ZIP; not a valid offline driver package."],
["crates/dbx-core/src/admin/mq/adapters/kafka.rs", "Kafka does not support unloading topics"],
["crates/dbx-web/src/auth.rs", "Please try again in {remaining}s"],
["crates/dbx-web/src/routes/agents.rs", "Close these database connections before updating drivers: "],
["src-tauri/src/commands/agents.rs", "Close these database connections before updating drivers: "],
+3 -3
View File
@@ -128,7 +128,7 @@ const patterns: [RegExp, string][] = [
// SSH keyboard-interactive prompts (for example JumpServer TOTP).
[/^(?:SSH layer \d+ failed:\s*)?SSH keyboard-interactive authentication was cancelled$/, "connection.sshTotpCancelled"],
// Query result export limits (crates/dbx-core/src/query_result_export.rs)
// Query result export limits (crates/dbx-core/src/data/query_result_export.rs)
[/^Streaming export is unsupported for this query\. Simplify it or use a supported driver\.$/, "exportProgress.streamingUnsupported"],
// MongoDB Legacy agent failures: messages raised by the agent arrive wrapped in "Agent RPC
// error (<code>): ", and the import path prefixes the row a batch-level failure belongs to.
@@ -146,7 +146,7 @@ const patterns: [RegExp, string][] = [
// Legacy bundled DuckDB error kept for compatibility with older backends.
[/^The previous DuckDB query is still stopping\. Please try again shortly\.$/, "editor.duckdbDraining"],
// Driver / JRE management (crates/dbx-core/src/agent_service.rs, routes/agents.rs)
// Driver / JRE management (crates/dbx-drivers/src/agent_service.rs, routes/agents.rs)
// The Windows variant is multi-line, so it must be tried before the single-line one.
[/^Failed to remove the old JRE directory: (.+)\nPossible causes:[\s\S]*\(original error: ([\s\S]+)\)$/, "driverStore.jreDirRemoveFailedWindows"],
[/^Failed to remove the old JRE directory: (.+) \(original error: ([\s\S]+)\)$/, "driverStore.jreDirRemoveFailed"],
@@ -154,7 +154,7 @@ const patterns: [RegExp, string][] = [
[/^agent-registry\.json not found in the ZIP; not a valid offline driver package\.$/, "driverStore.offlinePackageRegistryMissing"],
[/^Close these database connections before updating drivers: (.+)$/, "driverStore.driverUpdateBlocked"],
// Message queues (crates/dbx-core/src/mq/adapters/kafka.rs)
// Message queues (crates/dbx-core/src/admin/mq/adapters/kafka.rs)
[/^Kafka does not support unloading topics$/, "mqClients.unloadTopicUnsupportedKafka"],
// Filesystem (src-tauri/src/commands/fs_open.rs)
+2 -2
View File
@@ -7,7 +7,7 @@
- `app`, `tabs`, `sidebar`, `connection`: shell, navigation, and connection UI state helpers.
- `database`, `metadata`, `schema`, `table`: relational database metadata, capabilities, DDL, and table-object helpers.
- `sql`, `sql/semantic`, `editor`, `query`, `history`, `savedSql`: SQL editing, execution, diagnostics, history, and saved SQL behavior.
Keep fixed SQL completion statements and their database-specific variants in `sql/sqlSnippetTemplates.ts`; cross-check row-limiting families against `crates/dbx-core/src/sql_dialect/capabilities.rs` and authoritative dialect documentation, and never replace a user-customized built-in body with a generated default.
Keep fixed SQL completion statements and their database-specific variants in `sql/sqlSnippetTemplates.ts`; cross-check row-limiting families against `crates/dbx-sql/src/sql_dialect/capabilities.rs` and authoritative dialect documentation, and never replace a user-customized built-in body with a generated default.
- `dataGrid`: result/grid rendering, editing, previews, pagination, and export helpers tied to the grid.
- `ai`, `mcp`: AI assistant and MCP configuration helpers.
- `redis`, `mongo`, `elasticsearch`, `etcd`, `kv`, `mq`, `nacos`, `zookeeper`, `webdav`: non-relational or service-specific helpers.
@@ -38,5 +38,5 @@ Schema Diff review and execution must preserve these invariants:
Regression coverage belongs in:
- `packages/app-tests/schemaDiff.test.ts`
- `crates/dbx-core/src/query.rs`
- `crates/dbx-core/src/query/mod.rs`
- `src-tauri/src/commands/query.rs`
@@ -101,7 +101,7 @@ describe("isNumericColumnType", () => {
it("covers the full cross-database numeric whitelist used by the alignment classifier", () => {
// Cross-database coverage matrix. Every entry here MUST stay in sync with
// the Rust classifier in crates/dbx-core/src/xlsx_export.rs so that the
// the Rust classifier in crates/dbx-formats/src/xlsx_export.rs so that the
// grid, the front-end XLSX exporter and the Rust XLSX exporter agree.
const numericTypesByDatabase: Record<string, string[]> = {
mysql: ["tinyint", "smallint", "mediumint", "int", "integer", "bigint", "float", "double", "decimal", "dec", "fixed"],
@@ -70,7 +70,7 @@ describe("databaseObjectCapabilities", () => {
it("exposes materialized views for StarRocks only", () => {
// StarRocks has a dedicated MV listing/classification path in
// crates/dbx-core/src/db/mysql.rs (`list_starrocks_tables` +
// crates/dbx-drivers/src/db/mysql.rs (`list_starrocks_tables` +
// `classify_starrocks_materialized_views`).
expect(sidebarObjectKindsForDatabase("starrocks")).toContain("MATERIALIZED_VIEW");
+1 -1
View File
@@ -19,7 +19,7 @@ const VECTOR_DB_TYPES: ReadonlySet<DatabaseType> = new Set([
"milvus",
"weaviate",
"chromadb",
// If modifying this, also update is_vector_db() in crates/dbx-core/src/agent_tools.rs.
// If modifying this, also update is_vector_db() in crates/dbx-core/src/ai/agent_tools.rs.
]);
export function isVectorDbType(dbType: DatabaseType): boolean {
+1 -1
View File
@@ -1,4 +1,4 @@
// Mirrors DEFAULT/MIN/MAX_MAX_AGENT_TURNS in crates/dbx-core/src/agent_loop.rs.
// Mirrors DEFAULT/MIN/MAX_MAX_AGENT_TURNS in crates/dbx-core/src/ai/agent_loop.rs.
// The backend clamp remains the source of truth for persisted values.
export const MAX_AGENT_TURNS_DEFAULT = 30;
export const MAX_AGENT_TURNS_MIN = 5;
@@ -106,7 +106,7 @@ const contracts: Contract[] = [
const sourceCache = new Map<string, string>();
function source(file: string): string {
if (!sourceCache.has(file)) sourceCache.set(file, readFileSync(join(process.cwd(), "crates/dbx-core/src/consul", file), "utf8"));
if (!sourceCache.has(file)) sourceCache.set(file, readFileSync(join(process.cwd(), "crates/dbx-core/src/admin/consul", file), "utf8"));
return sourceCache.get(file)!;
}
@@ -6,7 +6,7 @@ const http = readFileSync(new URL("../http.ts", import.meta.url), "utf8");
const api = readFileSync(new URL("../api.ts", import.meta.url), "utf8");
const tauriRegistry = readFileSync(new URL("../../../../../../src-tauri/src/lib.rs", import.meta.url), "utf8");
const webRegistry = readFileSync(new URL("../../../../../../crates/dbx-web/src/main.rs", import.meta.url), "utf8");
const coreOps = readFileSync(new URL("../../../../../../crates/dbx-core/src/document_ops.rs", import.meta.url), "utf8");
const coreOps = readFileSync(new URL("../../../../../../crates/dbx-core/src/query/document_ops.rs", import.meta.url), "utf8");
function functionBody(source: string, operation: string): string {
const start = source.indexOf(`export async function ${operation}(`);
@@ -123,7 +123,7 @@ export function spannerSchemaDisplayName(schema: string): string {
/**
* Percent-encode a Spanner resource path for display, keeping the `/` separators
* intact — they are structure, not data. Mirrors `encode_spanner_resource_path`
* in crates/dbx-core/src/models/connection.rs.
* in crates/dbx-types/src/models/connection.rs.
*
* Every other database type keeps whole-value encoding, where a slash inside a
* database name really is data and should be escaped.
@@ -267,7 +267,7 @@ const ORACLE_STICKY_TRANSACTION_TYPES: ReadonlySet<string> = new Set(["oracle",
/** Databases whose manual-transaction toolbar hides Commit/Rollback until an
* unproven statement dirties the session. Mirrors the Rust proof gate
* (crates/dbx-core/src/query.rs + sql_risk.rs `prove_read_only_for_database`).
* (crates/dbx-core/src/query/mod.rs + sql_risk.rs `prove_read_only_for_database`).
* Every member must also be in TRANSACTION_SUPPORTED_TYPES above: a database
* cannot reach manual mode (and this UX) without explicit transaction control
* (#9018). Family members like doris/kingbase join only when their transaction
@@ -68,7 +68,7 @@ const DATABASE_TYPE_OBJECTS = new Map<DatabaseType, SidebarObjectKind[]>([
["duckdb", TABLE_VIEW_OBJECTS],
["clickhouse", TABLE_VIEW_OBJECTS],
// Doris: backend listing path still uses the generic SHOW TABLES path (see
// `list_tables_once` for `PoolKind::Mysql` in crates/dbx-core/src/schema.rs)
// `list_tables_once` for `PoolKind::Mysql` in crates/dbx-core/src/schema/mod.rs)
// and lacks a MV classifier. Keep Doris on TABLE_VIEW_OBJECTS until a
// Doris-specific MV listing/classification lands, otherwise the UI advertises
// MV support that the backend cannot route.
@@ -2,7 +2,7 @@
* Read/write classification for Elasticsearch-compatible REST requests.
*
* Mirrors `classify_search_engine_query_risk` in
* `crates/dbx-core/src/query_execution_sql.rs` so the desktop guards (read-only
* `crates/dbx-sql/src/query_execution_sql.rs` so the desktop guards (read-only
* unlock, production safety) agree with the backend read-only gate instead of
* treating every `GET`/`POST` request as an unrecognized — and therefore
* unsafe — statement.
@@ -2,7 +2,7 @@ import type { PluginFieldCondition, PluginFormField, PluginFormFieldValue } from
/**
* Canonical string form of a form value, matching the Rust host
* (`condition_value_text` in `crates/dbx-core/src/plugins/manifest.rs`).
* (`condition_value_text` in `crates/dbx-plugin-runtime/src/plugins/manifest.rs`).
* `false` renders as `"false"` and `22.0` as `"22"`.
*/
export function pluginConditionValueText(value: PluginFormFieldValue): string {
@@ -243,7 +243,7 @@ export class PluginHostBridge {
/**
* Parse `host.network:<origin>` permission entries into CSP connect-src
* origins. Must stay aligned with `parse_host_network_permission` in
* crates/dbx-core/src/plugins/manifest.rs.
* crates/dbx-plugin-runtime/src/plugins/manifest.rs.
*/
export function pluginNetworkOrigins(permissions: readonly string[] | undefined): string[] {
const origins = new Set<string>();
@@ -1,4 +1,4 @@
// Mirrors dbx-core `redis_database_index()` (crates/dbx-core/src/db/redis_driver.rs):
// Mirrors dbx-core `redis_database_index()` (crates/dbx-drivers/src/db/redis_driver.rs):
// a Redis database is a numeric index. Anything else (e.g. redis-cli flags like
// "0 --tls --insecure" pasted into the field or imported from a dirty URL) fails
// to parse on the backend and silently falls back to db 0, so every frontend
+1 -1
View File
@@ -151,7 +151,7 @@ export function resolveNewQueryTable(input: ResolveNewQueryTableInput): NewQuery
*
* Time-series engines get the same rolling-window scoping the sidebar
* quick-open uses (see `default_time_series_predicate` in
* `crates/dbx-core/src/sql_dialect/table_select.rs`). Without a `time`
* `crates/dbx-sql/src/sql_dialect/table_select.rs`). Without a `time`
* predicate InfluxDB scans every shard (v1/v2) or every Parquet file
* (v3), which turns "let me draft a query against this table" into a
* full-history scan the moment the user hits Run. VictoriaMetrics
+126
View File
@@ -0,0 +1,126 @@
# DBX Rust 模块边界
## 依赖方向
`dbx-core` 是应用编排层,不再承载所有底层实现。桌面、Web、CLI、MCP
继续通过 core 调用连接、查询、导入导出等业务;独立工具可直接使用下层 crate。
```text
desktop / web / cli / mcp
│
dbx-core
├── dbx-drivers ── dbx-sql ── dbx-types
│ ├── dbx-types
│ ├── dbx-platform
│ └── dbx-sqlite-worker (protocol, no runtime defaults)
├── dbx-plugin-runtime ── dbx-types + dbx-platform
├── dbx-ai-provider ── dbx-platform
├── dbx-formats
├── dbx-sql / dbx-types
└── dbx-platform
```
下层 crate 不得反向依赖 core,包括 build 和 dev 依赖。涉及多层的测试放在
`dbx-core/tests/`,避免为了测试把数据库连接引入 SQL、类型或格式 crate。
`scripts/core-architecture.test.mjs` 校验 workspace 依赖、功能转发、源码归属、
构建输入和前端测试引用路径;CI 的 Rust 检查执行此守卫。
## 所有权
| Crate | 拥有的实现 | 不应引入 |
| --- | --- | --- |
| `dbx-types` | 连接配置、数据库身份、查询与元数据 DTO、JS 安全 JSON、MQTT/GridFS 数据记录 | 连接池、应用状态、驱动 SDK |
| `dbx-sql` | 解析、方言注册与加载、SQL 风险、DDL/DML、结构差异计划 | 查询执行、凭据、core 业务 |
| `dbx-drivers` | 原生驱动、隧道、JDBC/Agent 运行与分发、超时取消、SQLite 元数据读取 | 导入/迁移编排、应用配置持久化 |
| `dbx-formats` | CSV/XLSX/文本/时间格式与 ZIP 编码 | 数据库请求、连接管理 |
| `dbx-ai-provider` | 模型与 CLI 适配器、流式协议、事件和 token 用量 | 数据库工具执行和 Agent 业务循环 |
| `dbx-plugin-runtime` | manifest、签名与安装、Marketplace、子进程会话及 host 请求 | 数据库驱动实现、core 应用状态 |
| `dbx-platform` | 进程、路径、代理、下载、版本比较与共享用户提示网关 | 数据库身份和业务规则 |
`dbx-sql` 包含方言文件加载/监听,因此不是完全无 I/O 的函数库;边界是“不执行数据库业务”。
平台的 `host-prompts`、`downloads` 和类型库的 `mq-admin` 等能力显式启用,
避免只使用类型或纯格式的消费者意外加载驱动或应用层。
## Core 业务目录
```text
dbx-core/src/
lib.rs 对外模块与旧 API 兼容导出
connection/ 连接路由、凭据、运行配置、JDBC 配置、任务监督
query/ 查询编排、取消、文档/Redis/HBase 操作、事务与对象缓存
schema/ 元数据编排、运行时 SQLite 表重建
data/ 导入导出、迁移、比较、备份、文档与脚本工作流
ai/ 数据库 Agent 循环、工具、解释、模板与 MCP 策略
admin/ Nacos、Consul、MQ、MQTT
persistence/ 本地存储、历史、保存的 SQL、配置与云同步
safety/ 生产安全、写入解锁和风险指标
host/ 更新、变更日志和外部应用集成
db/ 驱动兼容导出与 Cloudflare D1 业务接口覆盖
```
目录内存放实际实现,不以 `#[path]` 把旧根目录伪装成新目录。已存在但未声明的
实验文件不会因迁移而自动启用。
Cloudflare D1 的批量导入依赖迁移逻辑,保留在 `data/cloudflare_d1/`;HTTP 驱动、
SQL 限制与词法处理位于 drivers。SQLite 表重建执行留在 core,SQL 生成位于 sql。
数据库查询驱动的 CSV 导出编排留在 core,CSV 编码位于 formats。
## 兼容性
- 原有 `dbx_core::models`、`dbx_core::types`、`dbx_core::db`、`dbx_core::sql*`、
`dbx_core::ai`、`dbx_core::plugins` 及业务模块路径继续通过重导出可用。
- 同一 DTO、连接池、提示请求和插件类型不复制定义;旧路径与新 crate 具有相同类型身份。
`public_api_compatibility` 测试覆盖这些跨层身份。
- 协议、序列化字段、默认配置、数据库语义、安装目录与进程生命周期不因搬迁而改变。
原测试随实现迁移;依赖 core 的跨层测试移入 core 集成测试目录。
- `test-support` 仅提供原有 stub/测试钩子,由 dev-dependency 启用,不在生产依赖启用。
- 模块路径产生的日志 target 和 Rust 调试类型名会随 crate/目录变化。自定义
`RUST_LOG=dbx_core=debug` 不会覆盖新 crate;需要加入
`dbx_drivers=debug,dbx_sql=debug,dbx_plugin_runtime=debug,dbx_ai_provider=debug,dbx_platform=debug`
等目标。默认桌面日志级别及 Web 默认过滤策略保持原样。
## Features 与资源
core 保留原来的 default feature 集合,并向实际实现 crate 转发
`duckdb-sidecar`、`dynamodb`、`mq-admin`、`openapi` 与 SQLite 能力。
`sqlite-bundled`、`sqlite-sqlcipher`、`sqlite-multiple-ciphers` 是不同的 SQLite
后端选择,不要用 workspace `--all-features` 代替合法组合测试。
- `dbx-types/build.rs` 消费 `plugins/connection-types/`。
- `dbx-sql/build.rs` 消费 `plugins/dialects/`。
- Pi MCP bridge 随 AI provider;Agent v2 协议 JSON 随 drivers,并与 Java resource 对照。
- 数据库文档导出的 JS/CSS 仍在 `dbx-core/assets/`,由 `pnpm build:docs-export` 生成。
- Docker 的依赖缓存阶段必须包含所有 workspace manifest 和 stub,实际构建阶段
必须包含方言与连接类型目录。Nix 保留整个仓库源码输入。
## 验证
本机不启动数据库/引擎或 Docker 实例。单元测试包含内存 SQLite 与本地协议模拟器;
真实数据库验证复用 SSH 测试服务器上的专用测试实例,使用 SSH 隧道访问。
Linux 的文件权限回归测试应由非 root 用户执行;root 可绕过目录写权限,会让测试
前提失效。测试进程的代理应排除 localhost,避免本地 HTTP 模拟器请求被转发。
```sh
pnpm test:architecture
cargo check -p dbx-core --no-default-features --all-targets
env -u DOCKER_CONTEXT \
DOCKER_HOST=unix:///tmp/dbx-disabled-docker.sock \
RUST_MIN_STACK=33554432 \
cargo test -p dbx-core -p dbx-drivers -p dbx-sql \
-p dbx-types -p dbx-formats -p dbx-platform \
-p dbx-ai-provider -p dbx-plugin-runtime \
--no-default-features --features dbx-core/sqlite-bundled --lib
cargo test -p dbx-core --no-default-features --features sqlite-bundled \
--test public_api_compatibility --test connection_url_compatibility \
--test agent_recovery_contract
```
交付验证还应覆盖桌面/Web/CLI/MCP 消费者、合法 feature 组合、前端类型与源码契约、
Agent 安装/恢复以及远程数据库查询/元数据/导入导出。`#[ignore]` 的 live 测试需要其
声明的测试环境变量;未运行的 live 用例不算通过。禁止把静态构建输入检查描述成
Docker/Nix 镜像已构建,也不能把单元测试通过描述成所有数据库版本均已实测。
拆分的直接收益是可独立检查的依赖边界、实现所有权与回归范围;编译时间、内存和
运行速度的提升需要同环境 benchmark,不能仅凭目录拆分推断。
+13 -1
View File
@@ -4,7 +4,19 @@ Rust crates for DBX live here.
## Directories
- `dbx-core/` - shared database core, drivers, schema/query logic, import/export, transfer, and plugin support.
- `dbx-core/` - application orchestration: connections, queries, schema operations, data workflows, AI tools, administration, persistence, safety, and host services.
- `dbx-types/` - shared connection, query, metadata, and serialization contracts; generated database identities.
- `dbx-sql/` - SQL parsing, dialects, analysis, risk classification, DDL/DML generation, and schema diff planning.
- `dbx-drivers/` - native database adapters, database Agents, tunnels, execution budgets, and driver lifecycle.
- `dbx-formats/` - data formatting and file encoders, independent of database connections.
- `dbx-ai-provider/` - AI provider clients, CLI adapters, streaming, and token usage.
- `dbx-plugin-runtime/` - plugin packages, signatures, marketplace, subprocess sessions, and host requests.
- `dbx-platform/` - shared process, path, proxy, download, version, and host-prompt primitives.
- `dbx-web/` - the Docker/web backend service binary published as `dbx-web`.
- `dbx-cli/` - the command-line application.
- `dbx-mcp/` - the MCP service library and binary.
- `dbx-sqlite-worker/` - the isolated SQLite file-host worker and protocol.
The workspace root is defined in the repository-level `Cargo.toml`.
See [ARCHITECTURE.md](ARCHITECTURE.md) for dependency rules, compatibility exports, feature selection, and validation commands.
+23
View File
@@ -0,0 +1,23 @@
[package]
name = "dbx-ai-provider"
version = "0.1.0"
edition = "2021"
license = "Apache-2.0"
publish = false
[dependencies]
dbx-platform = { path = "../dbx-platform" }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = ["arbitrary_precision", "preserve_order"] }
futures = "0.3"
reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "rustls-tls", "socks"] }
tokio = { version = "1", features = ["process", "io-util", "sync", "time", "rt", "macros"] }
log = "0.4"
uuid = { version = "1", features = ["v4", "serde"] }
base64 = "0.22"
bytes = "1"
httpdate = "1"
tempfile = "3"
[dev-dependencies]
tokio = { version = "1", features = ["test-util", "rt-multi-thread"] }
@@ -2132,7 +2132,7 @@ async fn ollama_model_completion_support(
Ok(crate::ai_model_filter::ollama_completion_capability(&data))
}
pub(crate) async fn ollama_selected_model_tool_support(config: &AiConfig) -> Result<Option<bool>, String> {
pub async fn ollama_selected_model_tool_support(config: &AiConfig) -> Result<Option<bool>, String> {
let model_id = config.model.trim();
if model_id.is_empty() {
return Err("Model is required".to_string());
@@ -2724,7 +2724,7 @@ fn truncate_diagnostic(value: &str, max_chars: usize) -> String {
/// its scheme because proxies often echo that token without `Bearer`/`Basic`.
/// Other custom header values retain the [`MIN_SECRET_CHARS`] guard so ordinary
/// diagnostics are not mangled by short values such as a version marker.
pub(crate) fn sensitive_values(config: &AiConfig) -> Vec<String> {
pub fn sensitive_values(config: &AiConfig) -> Vec<String> {
let mut secrets: Vec<String> = Vec::new();
push_secret(&mut secrets, normalized_api_key(config), true);
for (name, value) in &config.custom_headers {
@@ -2771,7 +2771,7 @@ fn push_secret(secrets: &mut Vec<String>, value: &str, allow_short: bool) {
/// body that echoes `?key=…` cannot leak either. This is the single gate every
/// provider error string must pass through before it reaches the UI, a log
/// target, or a shared report; callers truncate the result as needed.
pub(crate) fn redact_secrets(value: &str, secrets: &[String]) -> String {
pub fn redact_secrets(value: &str, secrets: &[String]) -> String {
let mut redacted = value.to_string();
for secret in secrets {
if redacted.contains(secret.as_str()) {
@@ -134,7 +134,7 @@ async fn codex_process_env(config: &AiConfig, command: &CodexCommandSpec) -> Res
config,
command,
node_runtime_dir.as_deref(),
crate::update::system_proxy_url().as_deref(),
dbx_platform::proxy::system_proxy_url().as_deref(),
&inherited_env_keys,
)
}
+18
View File
@@ -0,0 +1,18 @@
#![recursion_limit = "256"]
pub use dbx_platform::{path_utils, process};
pub mod agent_events;
pub mod ai;
pub mod ai_claude_code_cli;
pub mod ai_cli_agent;
pub mod ai_codebuddy_cli;
pub mod ai_codex_cli;
pub mod ai_cursor_cli;
pub mod ai_effort;
pub mod ai_grok_cli;
mod ai_model_filter;
pub mod ai_opencode_cli;
pub mod ai_pi_agent_cli;
pub mod ai_qoder_cli;
pub mod token_usage;
+21 -42
View File
@@ -6,66 +6,51 @@ license = "Apache-2.0"
[features]
default = ["duckdb-sidecar", "dynamodb", "mq-admin", "sqlite-sqlcipher", "system-fonts"]
duckdb-sidecar = []
dynamodb = ["dep:aws-sdk-dynamodb"]
mq-admin = ["dep:rumqttc"]
sqlite-sqlcipher = ["rusqlite/bundled-sqlcipher-vendored-openssl"]
sqlite-multiple-ciphers = ["dep:libsqlite3-hotbundle"]
duckdb-sidecar = ["dbx-sql/duckdb-sidecar", "dbx-drivers/duckdb-sidecar"]
dynamodb = ["dbx-drivers/dynamodb"]
mq-admin = ["dep:rumqttc", "dbx-types/mq-admin", "dbx-drivers/mq-admin"]
sqlite-sqlcipher = ["rusqlite/bundled-sqlcipher-vendored-openssl", "dbx-drivers/sqlite-sqlcipher"]
sqlite-multiple-ciphers = ["dbx-drivers/sqlite-multiple-ciphers"]
# Keeps bundled SQLite for consumers that enable no other sqlite source
# (dbx-cli, dbx-mcp); do not combine with the cipher features.
sqlite-bundled = ["rusqlite/bundled"]
openapi = ["dep:utoipa"]
sqlite-bundled = ["rusqlite/bundled", "dbx-drivers/sqlite-bundled"]
openapi = ["dbx-types/openapi", "dbx-sql/openapi"]
system-fonts = ["font-kit"]
[dependencies]
dbx-drivers = { path = "../dbx-drivers", default-features = false }
dbx-sql = { path = "../dbx-sql", default-features = false }
dbx-plugin-runtime = { path = "../dbx-plugin-runtime" }
dbx-formats = { path = "../dbx-formats" }
dbx-types = { path = "../dbx-types", default-features = false }
dbx-ai-provider = { path = "../dbx-ai-provider" }
dbx-platform = { path = "../dbx-platform", features = ["host-prompts", "downloads"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = ["arbitrary_precision", "preserve_order"] }
semver = "1"
ed25519-dalek = "2"
fs2 = "0.4"
utoipa = { version = "5.5", optional = true }
unicode-width = "0.2"
unicode-ident = "1"
serde_yaml_ng = "0.10"
json5 = "0.4"
regex = "1"
winnow = "1.0"
rayon = "1"
percent-encoding = "2"
encoding_rs = "0.8"
log = "0.4"
tracing = "0.1"
tracing-subscriber = "0.3"
tokio = { version = "1", features = ["full"] }
tokio-util = { version = "0.7", features = ["compat"] }
chrono = { version = "0.4", features = ["serde"] }
httpdate = "1"
rust_decimal = { version = "1", features = ["serde"] }
anyhow = "1"
uuid = { version = "1", features = ["v4", "serde"] }
tokio-postgres = { version = "0.7", features = ["with-chrono-0_4", "with-uuid-1", "with-serde_json-1"] }
deadpool-postgres = { version = "0.14", features = ["rt_tokio_1"] }
tokio-postgres-rustls = "0.13"
postgres-openssl = "0.5"
openssl = { version = "0.10", features = ["vendored"] }
webpki-roots = "0.26"
rusqlite = { version = "0.32", default-features = false, features = ["load_extension", "backup", "functions", "column_decltype"] }
libsqlite3-hotbundle = { git = "https://github.com/zipg/libsqlite3-hotbundle.git", rev = "7f12f203b4f4694a273410bd9b02d77f82b6114e", features = ["cipher-sqlcipher"], optional = true }
dbx-sqlite-worker = { path = "../dbx-sqlite-worker", default-features = false }
mysql_async = { version = "0.37", default-features = false, features = ["default-rustls", "client_ed25519", "chrono", "rust_decimal"] }
sqlparser = { version = "0.62.0", features = ["visitor"] }
redis = { version = "0.32.2", features = ["tokio-comp", "tls-rustls", "tls-rustls-insecure", "tokio-rustls-comp", "sentinel", "cluster-async"] }
rustls = { version = "0.23", features = ["aws-lc-rs"] }
rustls-pemfile = "2.2"
tiberius = { version = "0.12.3", default-features = false, features = ["tds73", "chrono", "rust_decimal", "rustls", "sql-browser-tokio"] }
reqwest = { version = "0.12", default-features = false, features = ["cookies", "json", "stream", "rustls-tls", "socks"] }
prometheus-parse = "=0.2.5"
futures = "0.3"
mongodb = { version = "3.2.5", features = ["socks5-proxy"] }
aws-sdk-dynamodb = { version = "=1.104.0", optional = true }
rumqttc = { version = "0.24", features = ["websocket"], optional = true }
russh = "0.60"
pageant = "0.2"
portpicker = "0.1.1"
csv = "1"
calamine = { version = "0.30.1", features = ["dates"] }
@@ -86,27 +71,21 @@ flate2 = "1"
crc = "3"
sha1 = "0.10"
tar = "0.4"
zstd = "0.13"
sysinfo = { version = "0.32", features = ["system"] }
serde_yaml = "0.9"
minijinja = "2"
notify = { version = "7", default-features = false, features = ["macos_kqueue"] }
arc-swap = "1"
insta = { version = "1", features = ["json", "glob"] }
tempfile = "3"
[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.61", features = ["Win32_Storage_FileSystem", "Win32_Foundation", "Win32_Security"] }
[dev-dependencies]
zstd = "0.13"
dbx-drivers = { path = "../dbx-drivers", default-features = false, features = ["test-support"] }
dbx-plugin-runtime = { path = "../dbx-plugin-runtime", features = ["test-support"] }
dbx-platform = { path = "../dbx-platform", features = ["test-support"] }
tokio = { version = "1", features = ["test-util"] }
[target.'cfg(all(unix, not(target_os = "redox")))'.dependencies]
nix = { version = "0.31.3", features = ["user"] }
[dev-dependencies]
mysql_common = { git = "https://github.com/t8y2/rust_mysql_common.git", rev = "47740d85a8277167a5717afac785d37b46a36296", default-features = false }
tokio = { version = "1", features = ["test-util"] }
tokio-openssl = "0.6"
[build-dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_yaml_ng = "0.10"
+6
View File
@@ -0,0 +1,6 @@
pub mod consul;
#[cfg(feature = "mq-admin")]
pub mod mq;
#[cfg(feature = "mq-admin")]
pub mod mqtt;
pub mod nacos;
@@ -8,10 +8,10 @@
//! src-tauri/src/commands/mqtt_cmd.rs (Tauri command 入口)
//! │
//! ▼
//! crates/dbx-core/src/mqtt/service.rs (共享核心逻辑)
//! crates/dbx-core/src/admin/mqtt/service.rs (共享核心逻辑)
//! │
//! ▼
//! crates/dbx-core/src/mqtt/client.rs (rumqttc 客户端封装)
//! crates/dbx-core/src/admin/mqtt/client.rs (rumqttc 客户端封装)
//! │
//! ▼
//! MQTT Broker (EMQX / Mosquitto / HiveMQ / ...)
@@ -19,4 +19,4 @@
pub mod client;
pub mod service;
pub mod types;
pub use dbx_types::mqtt as types;

Some files were not shown because too many files have changed in this diff Show More