Files
Netcatty/application/state/useVaultState.ts
bincxz 885d837fda feat: Implement agents architecture and core functionality
- Added agents overview documentation outlining the project structure and roles.
- Implemented `useSessionState` for managing terminal sessions and workspaces.
- Developed `useSettingsState` for handling user settings and theme management.
- Created `useVaultState` for managing hosts, SSH keys, snippets, and custom groups.
- Introduced domain logic for host normalization and sanitization.
- Defined models for Host, SSHKey, Snippet, TerminalSession, and Workspace.
- Implemented workspace management functions including creation, insertion, and pruning.
- Established local storage adapter for persistent data management.
- Integrated Gemini AI service for terminal simulation and command generation.
- Developed sync service for backing up and restoring configuration to/from GitHub Gists.
2025-12-08 01:29:49 +08:00

121 lines
3.7 KiB
TypeScript

import { useCallback, useEffect, useState } from 'react';
import { Host, SSHKey, Snippet } from '../../domain/models';
import { normalizeDistroId, sanitizeHost } from '../../domain/host';
import { INITIAL_HOSTS, INITIAL_SNIPPETS } from '../../infrastructure/config/defaultData';
import {
STORAGE_KEY_GROUPS,
STORAGE_KEY_HOSTS,
STORAGE_KEY_KEYS,
STORAGE_KEY_SNIPPET_PACKAGES,
STORAGE_KEY_SNIPPETS,
} from '../../infrastructure/config/storageKeys';
import { localStorageAdapter } from '../../infrastructure/persistence/localStorageAdapter';
type ExportableVaultData = {
hosts: Host[];
keys: SSHKey[];
snippets: Snippet[];
customGroups: string[];
};
export const useVaultState = () => {
const [hosts, setHosts] = useState<Host[]>([]);
const [keys, setKeys] = useState<SSHKey[]>([]);
const [snippets, setSnippets] = useState<Snippet[]>([]);
const [customGroups, setCustomGroups] = useState<string[]>([]);
const [snippetPackages, setSnippetPackages] = useState<string[]>([]);
useEffect(() => {
const savedHosts = localStorageAdapter.read<Host[]>(STORAGE_KEY_HOSTS);
const savedKeys = localStorageAdapter.read<SSHKey[]>(STORAGE_KEY_KEYS);
const savedGroups = localStorageAdapter.read<string[]>(STORAGE_KEY_GROUPS);
const savedSnippets = localStorageAdapter.read<Snippet[]>(STORAGE_KEY_SNIPPETS);
const savedSnippetPackages = localStorageAdapter.read<string[]>(STORAGE_KEY_SNIPPET_PACKAGES);
if (savedHosts?.length) {
const sanitized = savedHosts.map(sanitizeHost);
setHosts(sanitized);
localStorageAdapter.write(STORAGE_KEY_HOSTS, sanitized);
} else {
updateHosts(INITIAL_HOSTS);
}
if (savedKeys) setKeys(savedKeys);
if (savedSnippets) setSnippets(savedSnippets);
else updateSnippets(INITIAL_SNIPPETS);
if (savedGroups) setCustomGroups(savedGroups);
if (savedSnippetPackages) setSnippetPackages(savedSnippetPackages);
}, []);
const updateHosts = (data: Host[]) => {
const cleaned = data.map(sanitizeHost);
setHosts(cleaned);
localStorageAdapter.write(STORAGE_KEY_HOSTS, cleaned);
};
const updateKeys = (data: SSHKey[]) => {
setKeys(data);
localStorageAdapter.write(STORAGE_KEY_KEYS, data);
};
const updateSnippets = (data: Snippet[]) => {
setSnippets(data);
localStorageAdapter.write(STORAGE_KEY_SNIPPETS, data);
};
const updateSnippetPackages = (data: string[]) => {
setSnippetPackages(data);
localStorageAdapter.write(STORAGE_KEY_SNIPPET_PACKAGES, data);
};
const updateCustomGroups = (data: string[]) => {
setCustomGroups(data);
localStorageAdapter.write(STORAGE_KEY_GROUPS, data);
};
const updateHostDistro = (hostId: string, distro: string) => {
const normalized = normalizeDistroId(distro);
setHosts(prev => {
const next = prev.map(h => h.id === hostId ? { ...h, distro: normalized } : h);
localStorageAdapter.write(STORAGE_KEY_HOSTS, next);
return next;
});
};
const exportData = useCallback((): ExportableVaultData => ({
hosts,
keys,
snippets,
customGroups,
}), [hosts, keys, snippets, customGroups]);
const importData = (payload: Partial<ExportableVaultData>) => {
if (payload.hosts) updateHosts(payload.hosts);
if (payload.keys) updateKeys(payload.keys);
if (payload.snippets) updateSnippets(payload.snippets);
if (payload.customGroups) updateCustomGroups(payload.customGroups);
};
const importDataFromString = (jsonString: string) => {
const data = JSON.parse(jsonString);
importData(data);
};
return {
hosts,
keys,
snippets,
customGroups,
snippetPackages,
updateHosts,
updateKeys,
updateSnippets,
updateSnippetPackages,
updateCustomGroups,
updateHostDistro,
exportData,
importDataFromString,
};
};