feat(docs): generate driver downloads from agent registries

This commit is contained in:
二丫讲梵 2026-08-03 17:01:15 +08:00 committed by GitHub
parent 7fbee89144
commit 5104d48346
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 64 additions and 13 deletions

View File

@ -16,8 +16,8 @@ export CONFIRM
node_modules/.modules.yaml: package.json pnpm-lock.yaml
$(PNPM) install --frozen-lockfile
docs/node_modules/.modules.yaml: docs/package.json docs/pnpm-lock.yaml
cd docs && $(PNPM) install --frozen-lockfile --ignore-workspace
docs/node_modules/.modules.yaml: docs/package.json docs/pnpm-lock.yaml docs/pnpm-workspace.yaml $(wildcard docs/patches/*.patch)
cd docs && $(PNPM) install --frozen-lockfile
help:
@printf '%s\n' 'DBX development targets:'
@ -59,7 +59,7 @@ install:
$(PNPM) install --frozen-lockfile
docs-install:
cd docs && $(PNPM) install --frozen-lockfile --ignore-workspace
cd docs && $(PNPM) install --frozen-lockfile
check-tauri-dev-port:
@if lsof -nP -iTCP:$(TAURI_DEV_PORT) -sTCP:LISTEN >/dev/null 2>&1; then \

View File

@ -19,7 +19,7 @@ const i18n = {
drivers: "Database Drivers",
driversDesc: "Single-driver .tar.zst packages for Java agents. Install the matching JRE separately when it is not already available.",
nativeAgents: "Native Agents",
nativeAgentsDesc: "Platform-specific .tar.zst packages for DuckDB, Oracle, KingBase, and XuguDB. Import the package directly in Driver Manager.",
nativeAgentsDesc: "Platform-specific .tar.zst packages for DuckDB, Oracle, KingBase, XuguDB, and RabbitMQ. Import the package directly in Driver Manager.",
jre: "Java Runtime (JRE)",
jreDesc: "JRE packages used by Java agent-based database drivers such as SQL Server and Dameng.",
download: "Download",
@ -55,7 +55,7 @@ const i18n = {
drivers: "数据库驱动",
driversDesc: "Java Agent 的单驱动 .tar.zst 包;目标机器尚未安装 JRE 时需要另外安装一次对应 JRE。",
nativeAgents: "原生 Agent",
nativeAgentsDesc: "DuckDB、Oracle、人大金仓和虚谷的按平台 .tar.zst 单驱动包,可直接在驱动管理中导入。",
nativeAgentsDesc: "DuckDB、Oracle、人大金仓、虚谷和 RabbitMQ 的按平台 .tar.zst 单驱动包,可直接在驱动管理中导入。",
jre: "Java 运行时 (JRE)",
jreDesc: "Java Agent 驱动所需的 JRE 环境,例如 SQL Server、达梦等连接会使用。",
download: "下载",

View File

@ -31,7 +31,7 @@ test("non-release assets retain their official download link", () => {
test("catalog falls back from R2 to CNB without using GitHub API", async () => {
const requestedUrls: string[] = [];
const accessVersion = driverVersions.access;
const accessVersion = "9.9.9";
vi.stubGlobal(
"fetch",
vi.fn(async (input: string | URL | Request) => {
@ -70,6 +70,7 @@ test("catalog falls back from R2 to CNB without using GitHub API", async () => {
assert.deepEqual(requestedUrls, ["https://dl.dbxio.com/agents/agent-registry.json", "https://cnb.cool/dbxio.com/dbx/-/releases/download/agents-latest/agent-registry.json"]);
assert.equal(catalog?.drivers[0]?.key, "access");
assert.equal(catalog?.drivers[0]?.version, accessVersion);
assert.equal(catalog?.jres[0]?.platformKey, "macos-aarch64");
assert.equal(catalog?.bundles[0]?.platformKey, "macos-aarch64");
assert.equal(catalog?.bundles[0]?.url, "https://github.com/t8y2/dbx/releases/download/agents-v0.2.64/dbx-agents-offline-macos-aarch64.zip");
@ -158,3 +159,22 @@ test("DuckDB native tar.zst packages appear in the native catalog", () => {
},
]);
});
test("RabbitMQ native tar.zst packages appear in the native catalog", () => {
const entries = buildNativeAgentEntries([
{
name: "dbx-agent-rabbitmq-0.1.1-windows-x64.tar.zst",
browser_download_url: "https://example.com/dbx-agent-rabbitmq-0.1.1-windows-x64.tar.zst",
size: 4096,
},
]);
assert.deepEqual(entries.map(({ key, platformKey, filename }) => ({ key, platformKey, filename })), [
{
key: "rabbitmq",
platformKey: "windows-x64",
filename: "dbx-agent-rabbitmq-0.1.1-windows-x64.tar.zst",
},
]);
assert.equal(entries[0]?.label, "RabbitMQ");
});

View File

@ -26,6 +26,8 @@ interface AgentRegistryArtifact {
interface AgentRegistryDriver {
version?: string;
min_app_version?: string;
jre?: string;
jar?: AgentRegistryArtifact;
native?: Record<string, AgentRegistryArtifact>;
}
@ -89,7 +91,9 @@ const GITHUB_RELEASE_DOWNLOAD_PREFIX = "https://github.com/t8y2/dbx/releases/dow
const CNB_RELEASE_DOWNLOAD_PREFIX = "https://cnb.cool/dbxio.com/dbx/-/releases/download/";
const MIN_APP_VERSION = "0.6.0";
const driverVersionMap = driverVersions as Record<string, string>;
const nativeDriverKeys = new Set(["duckdb", "oracle", "kingbase", "xugu"]);
const nativeDriverKeys = ["duckdb", "oracle", "kingbase", "xugu", "rabbitmq"] as const;
const nativeDriverKeySet = new Set<string>(nativeDriverKeys);
const nativeDriverKeyPattern = nativeDriverKeys.join("|");
const platformLabels: Record<string, string> = {
"macos-aarch64": "macOS (Apple Silicon)",
@ -127,6 +131,7 @@ const driverLabels: Record<string, string> = {
neo4j: "Neo4j",
"oceanbase-oracle": "OceanBase Oracle Mode",
oracle: "Oracle",
rabbitmq: "RabbitMQ",
saphana: "SAP HANA",
snowflake: "Snowflake",
sundb: "SunDB",
@ -142,7 +147,7 @@ const driverLabels: Record<string, string> = {
};
const currentDriverKeys = Object.keys(driverVersionMap).sort((a, b) => labelForDriver(a).localeCompare(labelForDriver(b)));
const currentJavaDriverKeys = currentDriverKeys.filter((key) => !nativeDriverKeys.has(key));
const currentJavaDriverKeys = currentDriverKeys.filter((key) => !nativeDriverKeySet.has(key));
const jreVersions: Record<string, string> = {
"21": "21",
@ -224,7 +229,14 @@ function assetMap(assets: GitHubReleaseAsset[]): Map<string, GitHubReleaseAsset>
}
export function buildAgentDownloadCatalogFromRegistry(registry: AgentRegistry): AgentDownloadCatalog {
return buildAgentDownloadCatalog(registryReleaseAssets(registry));
const assets = registryReleaseAssets(registry);
return {
jdbcPlugin: buildJdbcPluginDownloadEntry(),
bundles: buildOfflineBundleEntries(assets),
drivers: buildDriverEntriesFromRegistry(registry),
jres: buildJreEntries(assets),
nativeAgents: buildNativeAgentEntries(assets),
};
}
export function buildAgentDownloadCatalog(assets: GitHubReleaseAsset[]): AgentDownloadCatalog {
@ -287,14 +299,33 @@ export function buildDriverEntries(assets: GitHubReleaseAsset[]): DriverDisplayE
.filter((entry): entry is DriverDisplayEntry => entry !== null);
}
function buildDriverEntriesFromRegistry(registry: AgentRegistry): DriverDisplayEntry[] {
return Object.entries(registry.drivers ?? {})
.map(([key, driver]) => {
const jar = driver.jar;
if (nativeDriverKeySet.has(key) || !jar?.url || jar.size <= 0) return null;
return {
key,
label: labelForDriver(key),
version: driver.version ?? driverVersionMap[key] ?? "",
minAppVersion: driver.min_app_version ?? MIN_APP_VERSION,
jar: { url: jar.url, size: jar.size },
jre: driver.jre ?? "21",
};
})
.filter((entry): entry is DriverDisplayEntry => entry !== null)
.sort((a, b) => a.label.localeCompare(b.label));
}
export function buildNativeAgentEntries(assets: GitHubReleaseAsset[]): NativeAgentDisplayEntry[] {
const entries = new Map<string, NativeAgentDisplayEntry & { packaged: boolean }>();
const platforms = "macos-aarch64|macos-x64|linux-aarch64|linux-x64|windows-aarch64|windows-x64";
for (const asset of assets) {
const packageMatch = new RegExp(`^dbx-agent-(duckdb|oracle|kingbase|xugu)-(.+)-(${platforms})\\.(?:tar\\.zst|zip)$`).exec(asset.name);
const versionedMatch = new RegExp(`^dbx-agent-(duckdb|oracle|kingbase|xugu)-(.+)-(${platforms})(?:\\.exe)?$`).exec(asset.name);
const legacyMatch = new RegExp(`^dbx-agent-(duckdb|oracle|kingbase|xugu)-(${platforms})(?:\\.exe)?$`).exec(asset.name);
const packageMatch = new RegExp(`^dbx-agent-(${nativeDriverKeyPattern})-(.+)-(${platforms})\\.(?:tar\\.zst|zip)$`).exec(asset.name);
const versionedMatch = new RegExp(`^dbx-agent-(${nativeDriverKeyPattern})-(.+)-(${platforms})(?:\\.exe)?$`).exec(asset.name);
const legacyMatch = new RegExp(`^dbx-agent-(${nativeDriverKeyPattern})-(${platforms})(?:\\.exe)?$`).exec(asset.name);
const match = packageMatch ?? versionedMatch ?? legacyMatch;
if (!match) continue;
@ -302,7 +333,7 @@ export function buildNativeAgentEntries(assets: GitHubReleaseAsset[]): NativeAge
const key = match[1];
const version = legacyMatch ? (driverVersionMap[key] ?? "") : match[2];
const platformKey = legacyMatch ? match[2] : match[3];
if (!nativeDriverKeys.has(key)) continue;
if (!nativeDriverKeySet.has(key)) continue;
const entryKey = `${key}:${platformKey}`;
const existing = entries.get(entryKey);
if (existing?.packaged && !packaged) continue;