mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-21 05:53:46 +08:00
- 支持 MySQL/Oracle 租户协议在前后端统一解析 - 拒绝 Native 协议并避免误回退为 MySQL - 修复 Oracle 模式下元数据、DDL、SQL 方言识别 - 修复连接缓存键与实际协议解析优先级不一致问题 - 补充前后端协议解析与缓存隔离回归测试
145 lines
4.6 KiB
TypeScript
145 lines
4.6 KiB
TypeScript
import { connection } from '../../wailsjs/go/models';
|
|
import {
|
|
OCEANBASE_PROTOCOL_PARAM_KEYS,
|
|
resolveOceanBaseProtocolFromConfig,
|
|
} from './oceanBaseProtocol';
|
|
|
|
export type RpcConnectionConfig = connection.ConnectionConfig & { id?: string };
|
|
type ConnectionConfigInput = {
|
|
id?: string;
|
|
ssh?: Record<string, any>;
|
|
proxy?: Record<string, any>;
|
|
httpTunnel?: Record<string, any>;
|
|
[key: string]: any;
|
|
};
|
|
type SSHConfigInput = Record<string, any>;
|
|
type ProxyConfigInput = Record<string, any>;
|
|
type HttpTunnelConfigInput = Record<string, any>;
|
|
|
|
const toStringValue = (value: unknown, fallback = ''): string => {
|
|
if (typeof value === 'string') {
|
|
return value;
|
|
}
|
|
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
return String(value);
|
|
}
|
|
return fallback;
|
|
};
|
|
|
|
const toOptionalInteger = (value: unknown, fallback?: number): number | undefined => {
|
|
if (value === undefined || value === null || value === '') {
|
|
return fallback;
|
|
}
|
|
const parsed = Number(value);
|
|
if (!Number.isFinite(parsed)) {
|
|
return fallback;
|
|
}
|
|
return Math.trunc(parsed);
|
|
};
|
|
|
|
const normalizeProxyType = (value: unknown): 'socks5' | 'http' => {
|
|
return toStringValue(value).toLowerCase() === 'http' ? 'http' : 'socks5';
|
|
};
|
|
|
|
const normalizeSSHConfig = (value: unknown): connection.SSHConfig => {
|
|
const raw = (value ?? {}) as SSHConfigInput;
|
|
return new connection.SSHConfig({
|
|
host: toStringValue(raw.host),
|
|
port: toOptionalInteger(raw.port, 22) ?? 22,
|
|
user: toStringValue(raw.user),
|
|
password: toStringValue(raw.password),
|
|
keyPath: toStringValue(raw.keyPath),
|
|
});
|
|
};
|
|
|
|
const normalizeProxyConfig = (value: unknown): connection.ProxyConfig => {
|
|
const raw = (value ?? {}) as ProxyConfigInput;
|
|
const type = normalizeProxyType(raw.type);
|
|
return new connection.ProxyConfig({
|
|
type,
|
|
host: toStringValue(raw.host),
|
|
port: toOptionalInteger(raw.port, type === 'http' ? 8080 : 1080) ?? (type === 'http' ? 8080 : 1080),
|
|
user: toStringValue(raw.user),
|
|
password: toStringValue(raw.password),
|
|
});
|
|
};
|
|
|
|
const normalizeHttpTunnelConfig = (value: unknown): connection.HTTPTunnelConfig => {
|
|
const raw = (value ?? {}) as HttpTunnelConfigInput;
|
|
return new connection.HTTPTunnelConfig({
|
|
host: toStringValue(raw.host),
|
|
port: toOptionalInteger(raw.port, 8080) ?? 8080,
|
|
user: toStringValue(raw.user),
|
|
password: toStringValue(raw.password),
|
|
});
|
|
};
|
|
|
|
const withOceanBaseProtocolParam = (config: ConnectionConfigInput): ConnectionConfigInput => {
|
|
const type = toStringValue(config.type).trim().toLowerCase();
|
|
if (type !== 'oceanbase') {
|
|
return config;
|
|
}
|
|
const selectedProtocol = resolveOceanBaseProtocolFromConfig(config);
|
|
const params = new URLSearchParams(toStringValue(config.connectionParams));
|
|
for (const key of OCEANBASE_PROTOCOL_PARAM_KEYS) {
|
|
params.delete(key);
|
|
}
|
|
params.set('protocol', selectedProtocol);
|
|
return {
|
|
...config,
|
|
connectionParams: params.toString(),
|
|
};
|
|
};
|
|
|
|
export function buildRpcConnectionConfig(
|
|
config: ConnectionConfigInput,
|
|
overrides: ConnectionConfigInput = {},
|
|
): RpcConnectionConfig {
|
|
const mergedSSH = {
|
|
...(config.ssh ?? {}),
|
|
...(overrides.ssh ?? {}),
|
|
};
|
|
const mergedProxy = {
|
|
...(config.proxy ?? {}),
|
|
...(overrides.proxy ?? {}),
|
|
};
|
|
const mergedHttpTunnel = {
|
|
...(config.httpTunnel ?? {}),
|
|
...(overrides.httpTunnel ?? {}),
|
|
};
|
|
const merged: ConnectionConfigInput = {
|
|
...config,
|
|
...overrides,
|
|
ssh: mergedSSH,
|
|
proxy: mergedProxy,
|
|
httpTunnel: mergedHttpTunnel,
|
|
};
|
|
const rpcMerged = withOceanBaseProtocolParam(merged);
|
|
const { oceanBaseProtocol: _oceanBaseProtocol, ...rpcPayload } = rpcMerged;
|
|
|
|
const baseId = toStringValue(config.id).trim() || toStringValue(overrides.id).trim() || undefined;
|
|
const timeout = toOptionalInteger(rpcMerged.timeout, toOptionalInteger(config.timeout));
|
|
const redisDB = toOptionalInteger(rpcMerged.redisDB, toOptionalInteger(config.redisDB));
|
|
|
|
const rpcConfig = new connection.ConnectionConfig({
|
|
...rpcPayload,
|
|
type: toStringValue(rpcMerged.type),
|
|
host: toStringValue(rpcMerged.host),
|
|
port: toOptionalInteger(rpcMerged.port, toOptionalInteger(config.port, 0)) ?? 0,
|
|
user: toStringValue(rpcMerged.user),
|
|
password: toStringValue(rpcMerged.password),
|
|
database: toStringValue(rpcMerged.database),
|
|
useSSH: rpcMerged.useSSH === true,
|
|
ssh: normalizeSSHConfig(rpcMerged.ssh),
|
|
useProxy: rpcMerged.useProxy === true,
|
|
proxy: normalizeProxyConfig(rpcMerged.proxy),
|
|
useHttpTunnel: rpcMerged.useHttpTunnel === true,
|
|
httpTunnel: normalizeHttpTunnelConfig(rpcMerged.httpTunnel),
|
|
timeout,
|
|
redisDB,
|
|
}) as RpcConnectionConfig;
|
|
|
|
rpcConfig.id = baseId;
|
|
return rpcConfig;
|
|
}
|