next-shared-state
Version:
Enhanced state sharing for Next.js with IndexedDB persistence and URL data transfer between pages and components.
116 lines (115 loc) • 3.93 kB
JavaScript
// src/createStore.ts
import { useState, useEffect } from "react";
import { setMemory, getMemory } from "./memoryStore";
import { URLTransfer } from "./urlTransfer";
import { enhancedIndexedDB } from "./enhancedIndexedDB";
import { TTL } from "./ttlPresets";
function parseTTL(ttl) {
if (ttl === undefined)
return undefined;
if (typeof ttl === "string" && TTL[ttl] !== undefined) {
return TTL[ttl];
}
if (typeof ttl === "number") {
return ttl;
}
if (typeof ttl === "string") {
const match = ttl.match(/^(\d+)\s*(minute|hour|day|week|month|year)s?$/i);
if (match) {
const value = parseInt(match[1]);
const unit = match[2].toLowerCase();
const multipliers = {
minute: 60 * 1000,
hour: 60 * 60 * 1000,
day: 24 * 60 * 60 * 1000,
week: 7 * 24 * 60 * 60 * 1000,
month: 30 * 24 * 60 * 60 * 1000,
year: 365 * 24 * 60 * 60 * 1000,
};
return value * multipliers[unit];
}
const simpleNumber = parseInt(ttl);
if (!isNaN(simpleNumber)) {
return simpleNumber * 60 * 1000;
}
}
return undefined;
}
export function useSharedData(key, initialValue, options = {}) {
const [value, setValue] = useState(() => {
if (typeof window !== "undefined") {
const urlData = URLTransfer.extractFromURL();
if (urlData && urlData[key] !== undefined) {
return urlData[key];
}
}
const memoryValue = getMemory(key);
if (memoryValue !== undefined)
return memoryValue;
return initialValue;
});
useEffect(() => {
const loadFromIndexedDB = async () => {
if (options.persist === "indexedDB") {
try {
const persisted = await enhancedIndexedDB.get(key);
if (persisted !== null) {
setValue(persisted);
setMemory(key, persisted);
}
}
catch (error) {
console.warn("Failed to load from IndexedDB:", error);
}
}
};
loadFromIndexedDB();
}, [key, options.persist]);
useEffect(() => {
if (value !== undefined) {
setMemory(key, value);
if (options.persist === "indexedDB") {
const ttlMs = parseTTL(options.ttl);
enhancedIndexedDB
.set(key, value, {
ttl: ttlMs,
category: options.category,
})
.catch((error) => {
console.warn("Failed to persist to IndexedDB:", error);
});
}
}
}, [key, value, options.persist, options.ttl, options.category]);
return [value, setValue];
}
export function setSharedData(key, value, options = {}) {
setMemory(key, value);
if (options.persist === "indexedDB") {
const ttlMs = parseTTL(options.ttl);
enhancedIndexedDB
.set(key, value, {
ttl: ttlMs,
category: options.category,
})
.catch((error) => {
console.warn("Failed to persist to IndexedDB:", error);
});
}
}
export function createTransferURL(path, data) {
return URLTransfer.createTransferURL(path, data);
}
export async function clearPersistedData(category) {
return enhancedIndexedDB.clear(category);
}
export async function getPersistedKeys() {
return enhancedIndexedDB.getKeys();
}
export async function exportAllData() {
return enhancedIndexedDB.exportData();
}
export async function importData(jsonData) {
return enhancedIndexedDB.importData(jsonData);
}
export { enhancedIndexedDB as indexedDBStore, TTL };