tiny-rdm/frontend/src/stores/connections.js

438 lines
14 KiB
JavaScript

import { defineStore } from 'pinia'
import { get, isEmpty, uniq } from 'lodash'
import {
CreateGroup,
DeleteConnection,
DeleteGroup,
ExportConnections,
GetConnection,
ImportConnections,
ListConnection,
RenameGroup,
SaveConnection,
SaveLastDB,
SaveRefreshInterval,
SaveSortedConnection,
} from 'wailsjs/go/services/connectionService.js'
import { ConnectionType } from '@/consts/connection_type.js'
import { KeyViewType } from '@/consts/key_view_type.js'
import useBrowserStore from 'stores/browser.js'
import { i18nGlobal } from '@/utils/i18n.js'
const useConnectionStore = defineStore('connections', {
/**
* @typedef {Object} ConnectionItem
* @property {string} key
* @property {string} label display label
* @property {string} name database name
* @property {number} type
* @property {boolean} cluster is cluster node
* @property {ConnectionItem[]} children
*/
/**
* @typedef {Object} ConnectionProfile
* @property {string} defaultFilter
* @property {string} keySeparator
* @property {string} markColor
* @property {number} refreshInterval
*/
/**
* @typedef {Object} ConnectionState
* @property {string[]} groups
* @property {ConnectionItem[]} connections
* @property {Object.<string, ConnectionProfile>} serverProfile
*/
/**
*
* @returns {ConnectionState}
*/
state: () => ({
groups: [], // all group name set
connections: [], // all connections
serverProfile: {}, // all server profile in flat list
}),
getters: {},
actions: {
/**
* load all store connections struct from local profile
* @param {boolean} [force]
* @returns {Promise<void>}
*/
async initConnections(force) {
if (!force && !isEmpty(this.connections)) {
return
}
const conns = []
const groups = []
const profiles = {}
const { data = [{ groupName: '', connections: [], refreshInterval: 5 }] } = await ListConnection()
for (const conn of data) {
if (conn.type !== 'group') {
// top level
conns.push({
key: '/' + conn.name,
label: conn.name,
name: conn.name,
type: ConnectionType.Server,
cluster: get(conn, 'cluster.enable', false),
// isLeaf: false,
})
profiles[conn.name] = {
defaultFilter: conn.defaultFilter,
keySeparator: conn.keySeparator,
markColor: conn.markColor,
refreshInterval: conn.refreshInterval,
}
} else {
// custom group
groups.push(conn.name)
const subConns = get(conn, 'connections', [])
const children = []
for (const item of subConns) {
const value = conn.name + '/' + item.name
children.push({
key: value,
label: item.name,
name: item.name,
type: ConnectionType.Server,
cluster: get(item, 'cluster.enable', false),
// isLeaf: false,
})
profiles[item.name] = {
defaultFilter: item.defaultFilter,
keySeparator: item.keySeparator,
markColor: item.markColor,
refreshInterval: item.refreshInterval,
}
}
conns.push({
key: conn.name + '/',
label: conn.name,
type: ConnectionType.Group,
children,
})
}
}
this.connections = conns
this.serverProfile = profiles
this.groups = uniq(groups)
},
/**
* get connection by name from local profile
* @param name
* @returns {Promise<ConnectionProfile|null>}
*/
async getConnectionProfile(name) {
try {
const { data, success } = await GetConnection(name)
if (success) {
this.serverProfile[name] = {
defaultFilter: data.defaultFilter,
keySeparator: data.keySeparator,
markColor: data.markColor,
}
return data
}
} finally {
}
return null
},
/**
* create a new default connection
* @param {string} [name]
* @returns {{}}
*/
newDefaultConnection(name) {
return {
group: '',
name: name || '',
addr: '127.0.0.1',
port: 6379,
username: '',
password: '',
defaultFilter: '*',
keySeparator: ':',
connTimeout: 60,
execTimeout: 60,
dbFilterType: 'none',
dbFilterList: [],
keyView: KeyViewType.Tree,
loadSize: 10000,
markColor: '',
alias: {},
ssl: {
enable: false,
allowInsecure: true,
sni: '',
certFile: '',
keyFile: '',
caFile: '',
},
ssh: {
enable: false,
addr: '',
port: 22,
loginType: 'pwd',
username: '',
password: '',
pkFile: '',
passphrase: '',
},
sentinel: {
enable: false,
master: 'mymaster',
username: '',
password: '',
},
cluster: {
enable: false,
},
}
},
mergeConnectionProfile(dest, src) {
const mergeObj = (destObj, srcObj) => {
for (const k in srcObj) {
const t = typeof srcObj[k]
if (t === 'string') {
destObj[k] = srcObj[k] || destObj[k] || ''
} else if (t === 'number') {
destObj[k] = srcObj[k] || destObj[k] || 0
} else if (t === 'object') {
mergeObj(destObj[k], srcObj[k] || {})
} else {
destObj[k] = srcObj[k]
}
}
return destObj
}
return mergeObj(dest, src)
},
/**
* get database server by name
* @param name
* @returns {ConnectionItem|null}
*/
getConnection(name) {
const conns = this.connections
for (let i = 0; i < conns.length; i++) {
if (conns[i].type === ConnectionType.Server && conns[i].key === name) {
return conns[i]
} else if (conns[i].type === ConnectionType.Group) {
const children = conns[i].children
for (let j = 0; j < children.length; j++) {
if (children[j].type === ConnectionType.Server && conns[i].key === name) {
return children[j]
}
}
}
}
return null
},
/**
* create a new connection or update current connection profile
* @param {string} name set null if create a new connection
* @param {{}} param
* @returns {Promise<{success: boolean, [msg]: string}>}
*/
async saveConnection(name, param) {
const { success, msg } = await SaveConnection(name, param)
if (!success) {
return { success: false, msg }
}
// reload connection list
await this.initConnections(true)
return { success: true }
},
/**
* save connection after sort
* @returns {Promise<void>}
*/
async saveConnectionSorted() {
const mapToList = (conns) => {
const list = []
for (const conn of conns) {
if (conn.type === ConnectionType.Group) {
const children = mapToList(conn.children)
list.push({
name: conn.label,
type: 'group',
connections: children,
})
} else if (conn.type === ConnectionType.Server) {
list.push({
name: conn.name,
})
}
}
return list
}
const s = mapToList(this.connections)
SaveSortedConnection(s)
},
/**
* remove connection
* @param name
* @returns {Promise<{success: boolean, [msg]: string}>}
*/
async deleteConnection(name) {
// close connection first
const browser = useBrowserStore()
await browser.closeConnection(name)
const { success, msg } = await DeleteConnection(name)
if (!success) {
return { success: false, msg }
}
await this.initConnections(true)
return { success: true }
},
/**
* create a connection group
* @param name
* @returns {Promise<{success: boolean, [msg]: string}>}
*/
async createGroup(name) {
const { success, msg } = await CreateGroup(name)
if (!success) {
return { success: false, msg }
}
await this.initConnections(true)
return { success: true }
},
/**
* rename connection group
* @param name
* @param newName
* @returns {Promise<{success: boolean, [msg]: string}>}
*/
async renameGroup(name, newName) {
if (name === newName) {
return { success: true }
}
const { success, msg } = await RenameGroup(name, newName)
if (!success) {
return { success: false, msg }
}
await this.initConnections(true)
return { success: true }
},
/**
* delete group by name
* @param {string} name
* @param {boolean} [includeConn]
* @returns {Promise<{success: boolean, [msg]: string}>}
*/
async deleteGroup(name, includeConn) {
const { success, msg } = await DeleteGroup(name, includeConn === true)
if (!success) {
return { success: false, msg }
}
await this.initConnections(true)
return { success: true }
},
/**
* save last selected database
* @param {string} name
* @param {number} db
* @return {Promise<{success: boolean, [msg]: string}>}
*/
async saveLastDB(name, db) {
const { success, msg } = await SaveLastDB(name, db)
if (!success) {
return { success: false, msg }
}
return { success: true }
},
/**
* get default key filter pattern by server name
* @param name
* @return {string}
*/
getDefaultKeyFilter(name) {
const { defaultFilter = '*' } = this.serverProfile[name] || {}
return defaultFilter
},
/**
* get default key separator by server name
* @param name
* @return {string}
*/
getDefaultSeparator(name) {
const { keySeparator = ':' } = this.serverProfile[name] || {}
return keySeparator
},
/**
* get default status refresh interval by server name
* @param {string} name
* @return {number}
*/
getRefreshInterval(name) {
const { refreshInterval = 5 } = this.serverProfile[name] || {}
return refreshInterval
},
/**
* set and save default refresh interval
* @param {string} name
* @param {number} interval
* @return {Promise<{success: boolean}|{msg: undefined, success: boolean}>}
*/
async saveRefreshInterval(name, interval) {
const profile = this.serverProfile[name] || {}
profile.refreshInterval = interval
const { success, msg } = await SaveRefreshInterval(name, interval)
if (!success) {
return { success: false, msg }
}
return { success: true }
},
async exportConnections() {
const {
success,
msg,
data: { path = '' },
} = await ExportConnections()
if (!success) {
if (!isEmpty(msg)) {
$message.error(msg)
return
}
}
$message.success(i18nGlobal.t('dialogue.handle_succ'))
},
async importConnections() {
const { success, msg } = await ImportConnections()
if (!success) {
if (!isEmpty(msg)) {
$message.error(msg)
return
}
}
$message.success(i18nGlobal.t('dialogue.handle_succ'))
},
},
})
export default useConnectionStore