feat(redis): add configurable key namespace separator

This commit is contained in:
t8y2 committed 2026-06-10 17:46:48 +08:00
1 parent 14d11a9933
commit d353d4673f
20 files changed
+64 -20

No files matched your search

@@ -119,6 +119,7 @@ const defaultForm = (): ConnectionForm => ({
redis_sentinel_password: "",
redis_sentinel_tls: false,
redis_cluster_nodes: "",
redis_key_separator: ":",
etcd_endpoints: "",
read_only: false,
visible_databases: undefined,
@@ -545,6 +546,7 @@ watch(
redis_sentinel_password: config.redis_sentinel_password || "",
redis_sentinel_tls: config.redis_sentinel_tls || false,
redis_cluster_nodes: config.redis_cluster_nodes || "",
redis_key_separator: config.redis_key_separator || ":",
etcd_endpoints: config.etcd_endpoints || "",
read_only: config.read_only || false,
visible_databases: config.visible_databases,
@@ -1057,6 +1059,7 @@ function connectionConfigForSubmit(id: string): ConnectionConfig {
config.redis_sentinel_password = undefined;
config.redis_sentinel_tls = undefined;
config.redis_cluster_nodes = undefined;
config.redis_key_separator = undefined;
} else if (config.redis_connection_mode === "sentinel") {
config.redis_sentinel_master = config.redis_sentinel_master?.trim() || "";
config.redis_sentinel_nodes = normalizeRedisSentinelNodes(config.redis_sentinel_nodes || "");
@@ -1088,6 +1091,9 @@ function connectionConfigForSubmit(id: string): ConnectionConfig {
config.redis_sentinel_tls = undefined;
config.redis_cluster_nodes = undefined;
}
if (config.db_type === "redis") {
config.redis_key_separator = config.redis_key_separator?.trim() || ":";
}
if (config.db_type === "etcd") {
config.etcd_endpoints = normalizeEndpointLines(config.etcd_endpoints || "");
const firstEndpoint = firstEtcdEndpoint(config.etcd_endpoints);
@@ -2376,6 +2382,10 @@ function openExternalUrl(url: string) {
<Label class="text-right">{{ t("connection.password") }}</Label>
<Input v-model="form.password" type="password" class="col-span-3" :placeholder="t('connection.databasePlaceholder')" />
</div>
<div class="grid grid-cols-4 items-center gap-4">
<Label class="text-right text-xs">{{ t("connection.redisKeySeparator") }}</Label>
<Input v-model="form.redis_key_separator" class="col-span-3 h-8 text-xs" placeholder=":" />
</div>
</template>
<!-- etcd: endpoints, user, password, TLS -->
@@ -104,6 +104,7 @@ const effectivePattern = computed(() => (searchMode.value === "key" ? redisKeySe
const isSearchMode = computed(() => (searchMode.value === "key" ? effectivePattern.value !== "*" : valueQuery.value !== ""));
const searchPlaceholder = computed(() => (searchMode.value === "key" ? (fuzzyKeySearch.value ? t("redis.fuzzyPattern") : t("redis.pattern")) : t("redis.valueSearchPlaceholder")));
const loadingEmptyText = computed(() => (searchMode.value === "value" && valueQuery.value ? t("redis.searchingValues") : t("redis.loadingKeys")));
const redisKeySeparator = computed(() => connectionStore.getConfig(props.connectionId)?.redis_key_separator || ":");
const lastTotalKeys = ref(0);
const fetchAllProgressText = computed(() => {
if (!isFetchingAll.value) return "";
@@ -151,7 +152,7 @@ function countLeaves(node: RedisKeyTreeNode): number {
}
function rebuildTree(expandAll = false) {
const nextTree = buildRedisKeyTree(flatKeys.value, props.db);
const nextTree = buildRedisKeyTree(flatKeys.value, props.db, redisKeySeparator.value);
treeKeys.value = nextTree;
const nextExpanded = new Set<string>();
@@ -172,7 +173,7 @@ function rebuildTree(expandAll = false) {
function mergeTree(newKeys: RedisKeyInfo[]) {
if (newKeys.length === 0) return;
treeKeys.value = mergeKeysIntoRedisKeyTree(treeKeys.value, newKeys, props.db);
treeKeys.value = mergeKeysIntoRedisKeyTree(treeKeys.value, newKeys, props.db, redisKeySeparator.value);
const availableExpanded = collectExpandedGroupIds(treeKeys.value);
const nextExpanded = new Set<string>();