Pulse/frontend-modern/src/hooks/usePersistentSignal.ts
rcourtman 6eb1a10d9b Refactor: Code cleanup and localStorage consolidation
This commit includes comprehensive codebase cleanup and refactoring:

## Code Cleanup
- Remove dead TypeScript code (types/monitoring.ts - 194 lines duplicate)
- Remove unused Go functions (GetClusterNodes, MigratePassword, GetClusterHealthInfo)
- Clean up commented-out code blocks across multiple files
- Remove unused TypeScript exports (helpTextClass, private tag color helpers)
- Delete obsolete test files and components

## localStorage Consolidation
- Centralize all storage keys into STORAGE_KEYS constant
- Update 5 files to use centralized keys:
  * utils/apiClient.ts (AUTH, LEGACY_TOKEN)
  * components/Dashboard/Dashboard.tsx (GUEST_METADATA)
  * components/Docker/DockerHosts.tsx (DOCKER_METADATA)
  * App.tsx (PLATFORMS_SEEN)
  * stores/updates.ts (UPDATES)
- Benefits: Single source of truth, prevents typos, better maintainability

## Previous Work Committed
- Docker monitoring improvements and disk metrics
- Security enhancements and setup fixes
- API refactoring and cleanup
- Documentation updates
- Build system improvements

## Testing
- All frontend tests pass (29 tests)
- All Go tests pass (15 packages)
- Production build successful
- Zero breaking changes

Total: 186 files changed, 5825 insertions(+), 11602 deletions(-)
2025-11-04 21:50:46 +00:00

75 lines
2.1 KiB
TypeScript

import { Accessor, Setter, createEffect, createSignal } from 'solid-js';
import { logger } from '@/utils/logger';
export type PersistentSignalOptions<T> = {
/**
* Custom serialization function. Defaults to `String(value)`.
*/
serialize?: (value: T) => string;
/**
* Custom deserialization function. Defaults to casting the stored string.
*/
deserialize?: (value: string) => T;
/**
* Optional equality comparison passed to Solid's `createSignal`.
*/
equals?: (prev: T, next: T) => boolean;
/**
* Alternate storage implementation (defaults to `window.localStorage`).
*/
storage?: Storage;
};
/**
* Creates a Solid signal that persists its value to localStorage (or a custom storage).
* The signal reads the initial value synchronously from storage when available.
*/
export function usePersistentSignal<T>(
key: string,
defaultValue: T,
options: PersistentSignalOptions<T> = {},
): [Accessor<T>, Setter<T>] {
const storage =
options.storage ?? (typeof window !== 'undefined' ? window.localStorage : undefined);
const serialize = options.serialize ?? ((value: T) => String(value));
const deserialize = options.deserialize ?? ((value: string) => value as unknown as T);
const initialValue = (() => {
if (!storage) {
return defaultValue;
}
try {
const raw = storage.getItem(key);
if (raw === null) {
return defaultValue;
}
return deserialize(raw);
} catch (err) {
logger.warn(`[usePersistentSignal] Failed to read "${key}" from storage`, err);
return defaultValue;
}
})();
const signalOptions = options.equals ? { equals: options.equals } : undefined;
const [value, setValue] = createSignal<T>(initialValue, signalOptions);
createEffect(() => {
if (!storage) {
return;
}
const current = value();
try {
if (current === undefined || current === null) {
storage.removeItem(key);
} else {
storage.setItem(key, serialize(current));
}
} catch (err) {
logger.warn(`[usePersistentSignal] Failed to persist "${key}"`, err);
}
});
return [value, setValue];
}