import { create } from 'zustand' function computeApiHost(): string { const apiUrl = new URL(location.toString()) if ((globalThis as any).p3xrDevMode === true) { const apiPort = (globalThis as any).p3xrApiPort || '7843' return `http://${apiUrl.hostname}:${apiPort}` } return `${apiUrl.protocol}//${apiUrl.host}` } type ConnectionState = 'none' | 'connecting' | 'connected' type CurrentPage = 'connections' | 'database' | 'pulse' | 'profiler' | 'pubsub' | 'analysis' | 'search' | 'timeseries' | 'info' | 'settings' | 'unknown' interface RedisState { apiHost: string connection: any | undefined connections: { list: any[] } cfg: any | undefined version: string | undefined currentDatabase: number | undefined databaseIndexes: number[] keysRaw: string[] keysInfo: any search: string page: number info: any dbsize: number | undefined monitor: boolean commands: string[] commandsMeta: Record modules: any[] hasRediSearch: boolean hasReJSON: boolean hasTimeSeries: boolean hasBloom: boolean theme: string | undefined redisConnections: Record keysInfoFetchedAt: number redisChanged: boolean failed: boolean reducedFunctions: boolean // --- Console drawer + connection-state awareness (Pass 1 of features-smarter) --- connectionState: ConnectionState currentPage: CurrentPage consoleDrawerOpen: boolean resetConnections: () => void setConnectionState: (s: ConnectionState) => void setCurrentPage: (p: CurrentPage) => void setConsoleDrawerOpen: (open: boolean) => void toggleConsoleDrawer: () => void } function getStoredDrawerOpen(): boolean { try { return localStorage.getItem('p3xr-console-drawer-open') === 'true' } catch { return false } } export const useRedisStateStore = create((set, get) => ({ apiHost: computeApiHost(), connection: undefined, connections: { list: [] }, cfg: undefined, version: undefined, currentDatabase: undefined, databaseIndexes: [], keysRaw: [], keysInfo: undefined, search: '', page: 1, info: undefined, dbsize: undefined, monitor: false, commands: [], commandsMeta: {}, modules: [], hasRediSearch: false, hasReJSON: false, hasTimeSeries: false, hasBloom: false, theme: undefined, redisConnections: {}, keysInfoFetchedAt: Date.now(), redisChanged: false, failed: false, reducedFunctions: false, connectionState: 'none', currentPage: 'unknown', consoleDrawerOpen: getStoredDrawerOpen(), resetConnections: () => set({ connections: { list: [] } }), setConnectionState: (s) => set({ connectionState: s }), setCurrentPage: (p) => set({ currentPage: p }), setConsoleDrawerOpen: (open) => { try { localStorage.setItem('p3xr-console-drawer-open', String(open)) } catch {} set({ consoleDrawerOpen: open }) }, toggleConsoleDrawer: () => { const next = !get().consoleDrawerOpen try { localStorage.setItem('p3xr-console-drawer-open', String(next)) } catch {} set({ consoleDrawerOpen: next }) }, })) // --- Computed helpers (matching Angular computed signals) --- // Import settings inline to avoid top-level circular dep import { useSettingsStore } from './settings.store' export function getFilteredKeys(): string[] { const { keysRaw, search } = useRedisStateStore.getState() const { searchClientSide, searchStartsWith } = useSettingsStore.getState() let keys = keysRaw.slice() if (searchClientSide && typeof search === 'string' && search.length > 0) { keys = searchStartsWith ? keys.filter((k: string) => k.startsWith(search)) : keys.filter((k: string) => k.includes(search)) } return keys } export function getPaginatedKeys(): string[] { const { page } = useRedisStateStore.getState() const { pageCount } = useSettingsStore.getState() const keys = getFilteredKeys() if (keys.length <= pageCount) return keys const start = (page - 1) * pageCount return keys.slice(start, start + pageCount) } export function getPages(): number { const { pageCount } = useSettingsStore.getState() return Math.ceil(getFilteredKeys().length / pageCount) }