personal-dash-cl/claudash/src/services/storageService.js

196 lines
No EOL
4.8 KiB
JavaScript

import { STORAGE_KEY, DEFAULT_HISTORY_DAYS, CACHE_TTL } from '../utils/constants';
/**
* Get the storage object from localStorage
* @returns {Object} The storage object
*/
function getStorage() {
try {
const stored = localStorage.getItem(STORAGE_KEY);
return stored ? JSON.parse(stored) : { briefings: {}, cache: {} };
} catch (error) {
console.error('Error reading from localStorage:', error);
return { briefings: {}, cache: {} };
}
}
/**
* Save the storage object to localStorage
* @param {Object} storage - The storage object to save
*/
function saveStorage(storage) {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(storage));
} catch (error) {
console.error('Error saving to localStorage:', error);
}
}
/**
* Save today's briefing with condensed summary
* @param {string} date - Date in YYYY-MM-DD format
* @param {string} briefingText - The generated briefing text
* @param {Object} sourceData - Raw data from all sources
* @param {string} condensedSummary - Condensed summary for historical context (optional)
*/
export function saveBriefing(date, briefingText, sourceData, condensedSummary = null) {
const storage = getStorage();
storage.briefings[date] = {
timestamp: Date.now(),
briefing: briefingText,
sources: sourceData,
condensedSummary: condensedSummary // Store condensed version for historical lookups
};
saveStorage(storage);
// Clean up old data after saving
cleanupOldData();
}
/**
* Get a previous briefing
* @param {number} daysAgo - How many days ago
* @returns {Object|null} The briefing object or null if not found
*/
export function getPreviousBriefing(daysAgo = 1) {
const storage = getStorage();
const date = new Date();
date.setDate(date.getDate() - daysAgo);
const dateKey = date.toISOString().split('T')[0];
return storage.briefings[dateKey] || null;
}
/**
* Cache fetched source data with timestamp
* @param {string} sourceKey - Unique key for the source
* @param {any} data - Data to cache
* @param {number} ttlMinutes - Time to live in minutes
*/
export function cacheSourceData(sourceKey, data, ttlMinutes = CACHE_TTL) {
const storage = getStorage();
storage.cache[sourceKey] = {
data: data,
timestamp: Date.now(),
ttl: ttlMinutes * 60 * 1000 // Convert to milliseconds
};
saveStorage(storage);
}
/**
* Get cached data if still fresh
* @param {string} sourceKey - Unique key for the source
* @returns {any|null} Cached data or null if expired/not found
*/
export function getCachedData(sourceKey) {
const storage = getStorage();
const cached = storage.cache[sourceKey];
if (!cached) {
return null;
}
const now = Date.now();
const age = now - cached.timestamp;
if (age > cached.ttl) {
// Cache expired
delete storage.cache[sourceKey];
saveStorage(storage);
return null;
}
return cached.data;
}
/**
* Clean up old data (keep only last N days)
* @param {number} daysToKeep - Number of days to keep
*/
export function cleanupOldData(daysToKeep = null) {
const storage = getStorage();
const days = daysToKeep || parseInt(import.meta.env.REACT_APP_HISTORY_DAYS) || DEFAULT_HISTORY_DAYS;
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - days);
// Clean old briefings
if (storage.briefings) {
Object.keys(storage.briefings).forEach(date => {
if (new Date(date) < cutoffDate) {
delete storage.briefings[date];
}
});
}
// Clean expired cache entries
const now = Date.now();
if (storage.cache) {
Object.keys(storage.cache).forEach(key => {
const cached = storage.cache[key];
if (cached && (now - cached.timestamp) > cached.ttl) {
delete storage.cache[key];
}
});
}
saveStorage(storage);
}
/**
* Export all data for debugging
* @returns {Object} All stored data
*/
export function exportAllData() {
return getStorage();
}
/**
* Import dummy data (dev mode)
* @param {Object} jsonData - Data to import
*/
export function importDummyData(jsonData) {
if (jsonData && typeof jsonData === 'object') {
saveStorage(jsonData);
}
}
/**
* Clear all stored data
*/
export function clearAllData() {
localStorage.removeItem(STORAGE_KEY);
}
/**
* Get all briefings
* @returns {Object} All briefings
*/
export function getAllBriefings() {
const storage = getStorage();
return storage.briefings || {};
}
/**
* Check if we have a briefing for today
* @returns {boolean} True if today's briefing exists
*/
export function hasTodaysBriefing() {
const storage = getStorage();
const today = new Date().toISOString().split('T')[0];
return !!storage.briefings[today];
}
/**
* Get today's briefing
* @returns {Object|null} Today's briefing or null
*/
export function getTodaysBriefing() {
const storage = getStorage();
const today = new Date().toISOString().split('T')[0];
return storage.briefings[today] || null;
}