diff --git a/packages/api/src/controllers/databaseConnections.js b/packages/api/src/controllers/databaseConnections.js index a83cc6d02..e58685736 100644 --- a/packages/api/src/controllers/databaseConnections.js +++ b/packages/api/src/controllers/databaseConnections.js @@ -161,6 +161,26 @@ module.exports = { return res.result || null; }, + loadKeyInfo_meta: true, + async loadKeyInfo({ conid, database, key }) { + const opened = await this.ensureOpened(conid, database); + const res = await this.sendRequest(opened, { msgtype: 'loadKeyInfo', key }); + if (res.errorMessage) { + console.error(res.errorMessage); + } + return res.result || null; + }, + + loadKeyTableRange_meta: true, + async loadKeyTableRange({ conid, database, key, cursor, count }) { + const opened = await this.ensureOpened(conid, database); + const res = await this.sendRequest(opened, { msgtype: 'loadKeyTableRange', key, cursor, count }); + if (res.errorMessage) { + console.error(res.errorMessage); + } + return res.result || null; + }, + updateCollection_meta: true, async updateCollection({ conid, database, changeSet }) { const opened = await this.ensureOpened(conid, database); diff --git a/packages/api/src/proc/databaseConnectionProcess.js b/packages/api/src/proc/databaseConnectionProcess.js index 9b5721d95..6e124019c 100644 --- a/packages/api/src/proc/databaseConnectionProcess.js +++ b/packages/api/src/proc/databaseConnectionProcess.js @@ -194,6 +194,28 @@ async function handleLoadKeys({ msgid, root }) { } } +async function handleLoadKeyInfo({ msgid, key }) { + await waitConnected(); + const driver = requireEngineDriver(storedConnection); + try { + const result = await driver.loadKeyInfo(systemConnection, key); + process.send({ msgtype: 'response', msgid, result }); + } catch (err) { + process.send({ msgtype: 'response', msgid, errorMessage: err.message }); + } +} + +async function handleLoadKeyTableRange({ msgid, key, cursor, count }) { + await waitConnected(); + const driver = requireEngineDriver(storedConnection); + try { + const result = await driver.loadKeyTableRange(systemConnection, key, cursor, count); + process.send({ msgtype: 'response', msgid, result }); + } catch (err) { + process.send({ msgtype: 'response', msgid, errorMessage: err.message }); + } +} + async function handleUpdateCollection({ msgid, changeSet }) { await waitConnected(); const driver = requireEngineDriver(storedConnection); @@ -260,6 +282,8 @@ const messageHandlers = { updateCollection: handleUpdateCollection, collectionData: handleCollectionData, loadKeys: handleLoadKeys, + loadKeyInfo: handleLoadKeyInfo, + loadKeyTableRange: handleLoadKeyTableRange, sqlPreview: handleSqlPreview, ping: handlePing, syncModel: handleSyncModel, diff --git a/packages/tools/src/stringTools.ts b/packages/tools/src/stringTools.ts index 47aecea40..dc8fa14dd 100644 --- a/packages/tools/src/stringTools.ts +++ b/packages/tools/src/stringTools.ts @@ -59,3 +59,28 @@ export function safeJsonParse(json, defaultValue?, logError = false) { export function isJsonLikeLongString(value) { return _isString(value) && value.length > 100 && value.match(/^\s*\{.*\}\s*$|^\s*\[.*\]\s*$/); } + +export function getIconForRedisType(type) { + switch (type) { + case 'dir': + return 'img folder'; + case 'string': + return 'img type-string'; + case 'hash': + return 'img type-hash'; + case 'set': + return 'img type-set'; + case 'list': + return 'img type-list'; + case 'zset': + return 'img type-zset'; + case 'stream': + return 'img type-stream'; + case 'binary': + return 'img type-binary'; + case 'ReJSON-RL': + return 'img type-rejson'; + default: + return null; + } +} diff --git a/packages/types/engines.d.ts b/packages/types/engines.d.ts index 8d2268165..cb161f726 100644 --- a/packages/types/engines.d.ts +++ b/packages/types/engines.d.ts @@ -76,6 +76,8 @@ export interface EngineDriver { }[] >; loadKeys(pool, root: string): Promise; + loadKeyInfo(pool, key): Promise; + loadKeyTableRange(pool, key, cursor, count): Promise; analyseFull(pool: any, serverVersion): Promise; analyseIncremental(pool: any, structure: DatabaseInfo, serverVersion): Promise; dialect: SqlDialect; diff --git a/packages/web/src/datagrid/DbKeyTableControl.svelte b/packages/web/src/datagrid/DbKeyTableControl.svelte new file mode 100644 index 000000000..4fe260991 --- /dev/null +++ b/packages/web/src/datagrid/DbKeyTableControl.svelte @@ -0,0 +1,41 @@ + + + ({ + fieldName, + header: fieldName, + })), + ]} + {rows} +/> diff --git a/packages/web/src/forms/TextField.svelte b/packages/web/src/forms/TextField.svelte index 59a0b0ed4..2200f01c6 100644 --- a/packages/web/src/forms/TextField.svelte +++ b/packages/web/src/forms/TextField.svelte @@ -2,10 +2,19 @@ import { onMount } from 'svelte'; export let value; - export let focused; - export let domEditor; + export let focused = false; + export let domEditor = undefined; if (focused) onMount(() => domEditor.focus()); - + diff --git a/packages/web/src/stores.ts b/packages/web/src/stores.ts index 70215782b..3d51e9f2a 100644 --- a/packages/web/src/stores.ts +++ b/packages/web/src/stores.ts @@ -93,6 +93,7 @@ export const loadingPluginStore = writable({ loaded: false, loadingPackageName: null, }); +export const activeDbKeysStore = writableWithStorage({}, 'activeDbKeysStore'); export const currentThemeDefinition = derived([currentTheme, extensions], ([$currentTheme, $extensions]) => $extensions.themes.find(x => x.themeClassName == $currentTheme) diff --git a/packages/web/src/tabs/DbKeyDetailTab.svelte b/packages/web/src/tabs/DbKeyDetailTab.svelte index e1cfa83fd..8897cb8bd 100644 --- a/packages/web/src/tabs/DbKeyDetailTab.svelte +++ b/packages/web/src/tabs/DbKeyDetailTab.svelte @@ -8,10 +8,81 @@ + +{#await apiCall('database-connections/load-key-info', { conid, database, key, refreshToken })} + +{:then keyInfo} +
+
+ +
+ {keyInfo.type} +
+ + {key} + TTL:{keyInfo.ttl} + { + refreshToken += 1; + }} + /> +
+ +
+ {#if keyInfo.tableColumns} + + + + + PROPS + + {:else} + + {/if} +
+
+{/await} + + diff --git a/packages/web/src/widgets/DbKeysTreeNode.svelte b/packages/web/src/widgets/DbKeysTreeNode.svelte index 2e188e185..f9e992b5f 100644 --- a/packages/web/src/widgets/DbKeysTreeNode.svelte +++ b/packages/web/src/widgets/DbKeysTreeNode.svelte @@ -1,7 +1,10 @@ { @@ -66,6 +45,10 @@ database, }, }); + $activeDbKeysStore = { + ...$activeDbKeysStore, + [`${conid}:${database}`]: item.key, + }; } }} extInfo={item.count ? `(${item.count})` : null} diff --git a/plugins/dbgate-plugin-redis/src/backend/driver.js b/plugins/dbgate-plugin-redis/src/backend/driver.js index dbab004a0..f03d0f84d 100644 --- a/plugins/dbgate-plugin-redis/src/backend/driver.js +++ b/plugins/dbgate-plugin-redis/src/backend/driver.js @@ -182,7 +182,7 @@ const driver = { const type = await pool.type(key); switch (type) { case 'list': { - const res = await pool.lrange(key, cursor, start + count); + const res = await pool.lrange(key, cursor, cursor + count); return { cursor: res.length > count ? cursor + count : 0, items: res.map((value) => ({ value })).slice(0, count),