mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-06-20 21:00:41 +00:00
feat: implement vault synchronization and decryption improvements
- Added background synchronization for vault core data, including optional folder updates. - Introduced a new API endpoint to retrieve the vault revision date. - Enhanced vault synchronization logic to utilize a caching mechanism for improved performance. - Created a new vault cache module to handle IndexedDB storage for vault core snapshots. - Implemented a worker for asynchronous decryption of vault data, improving UI responsiveness. - Updated main application settings to adjust query stale time for better data freshness. - Refactored vault-related API functions to support cache keys for more efficient data retrieval.
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import type { Cipher, Folder, Send } from '../types';
|
||||
import { getVaultRevisionDate } from './auth';
|
||||
import { loadCachedVaultCoreSnapshot, saveCachedVaultCoreSnapshot, type VaultCoreSnapshot } from '../vault-cache';
|
||||
import { parseJson, type AuthedFetch } from './shared';
|
||||
|
||||
interface VaultSyncResponse {
|
||||
@@ -7,13 +9,53 @@ interface VaultSyncResponse {
|
||||
sends?: Send[];
|
||||
}
|
||||
|
||||
const pendingVaultCoreRequests = new WeakMap<AuthedFetch, Promise<VaultSyncResponse>>();
|
||||
const pendingVaultCoreRequests = new Map<string, Promise<VaultCoreSnapshot>>();
|
||||
const memoryVaultCoreCache = new Map<string, { revisionStamp: number; snapshot: VaultCoreSnapshot }>();
|
||||
|
||||
export async function loadVaultCoreSyncSnapshot(authedFetch: AuthedFetch): Promise<VaultSyncResponse> {
|
||||
const existing = pendingVaultCoreRequests.get(authedFetch);
|
||||
function normalizeSnapshot(body: VaultSyncResponse | null | undefined): VaultCoreSnapshot {
|
||||
return {
|
||||
ciphers: Array.isArray(body?.ciphers) ? body!.ciphers! : [],
|
||||
folders: Array.isArray(body?.folders) ? body!.folders! : [],
|
||||
};
|
||||
}
|
||||
|
||||
export async function getCachedVaultCoreSnapshot(cacheKey: string): Promise<VaultCoreSnapshot | null> {
|
||||
const normalizedKey = String(cacheKey || '').trim();
|
||||
if (!normalizedKey) return null;
|
||||
const memory = memoryVaultCoreCache.get(normalizedKey);
|
||||
if (memory) return memory.snapshot;
|
||||
const cached = await loadCachedVaultCoreSnapshot(normalizedKey);
|
||||
if (!cached?.snapshot) return null;
|
||||
memoryVaultCoreCache.set(normalizedKey, {
|
||||
revisionStamp: cached.revisionStamp,
|
||||
snapshot: cached.snapshot,
|
||||
});
|
||||
return cached.snapshot;
|
||||
}
|
||||
|
||||
export async function loadVaultCoreSyncSnapshot(authedFetch: AuthedFetch, cacheKey: string): Promise<VaultCoreSnapshot> {
|
||||
const normalizedKey = String(cacheKey || '').trim();
|
||||
if (!normalizedKey) return { ciphers: [], folders: [] };
|
||||
|
||||
const existing = pendingVaultCoreRequests.get(normalizedKey);
|
||||
if (existing) return existing;
|
||||
|
||||
const request = (async () => {
|
||||
const revisionStamp = await getVaultRevisionDate(authedFetch);
|
||||
const memory = memoryVaultCoreCache.get(normalizedKey);
|
||||
if (memory?.revisionStamp === revisionStamp) {
|
||||
return memory.snapshot;
|
||||
}
|
||||
|
||||
const cached = await loadCachedVaultCoreSnapshot(normalizedKey);
|
||||
if (cached?.revisionStamp === revisionStamp && cached.snapshot) {
|
||||
memoryVaultCoreCache.set(normalizedKey, {
|
||||
revisionStamp,
|
||||
snapshot: cached.snapshot,
|
||||
});
|
||||
return cached.snapshot;
|
||||
}
|
||||
|
||||
const resp = await authedFetch('/api/sync?excludeSends=true&excludeDomains=true', {
|
||||
cache: 'no-store',
|
||||
headers: {
|
||||
@@ -23,15 +65,18 @@ export async function loadVaultCoreSyncSnapshot(authedFetch: AuthedFetch): Promi
|
||||
});
|
||||
if (!resp.ok) throw new Error('Failed to load vault');
|
||||
const body = await parseJson<VaultSyncResponse>(resp);
|
||||
return body || {};
|
||||
const snapshot = normalizeSnapshot(body);
|
||||
memoryVaultCoreCache.set(normalizedKey, { revisionStamp, snapshot });
|
||||
void saveCachedVaultCoreSnapshot(normalizedKey, revisionStamp, snapshot);
|
||||
return snapshot;
|
||||
})();
|
||||
|
||||
pendingVaultCoreRequests.set(authedFetch, request);
|
||||
pendingVaultCoreRequests.set(normalizedKey, request);
|
||||
try {
|
||||
return await request;
|
||||
} finally {
|
||||
if (pendingVaultCoreRequests.get(authedFetch) === request) {
|
||||
pendingVaultCoreRequests.delete(authedFetch);
|
||||
if (pendingVaultCoreRequests.get(normalizedKey) === request) {
|
||||
pendingVaultCoreRequests.delete(normalizedKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user