A file cache and sync component.
npm install @dwidge/file-cache-expouseFileUri and useFileCacheSync for seamless integration into React applications.
maxCache limit, the system evicts the oldest cached file that is not in the pending, mounted, or recent lists. An error is thrown if all cached items are pending, preventing data loss.
useFileUri hooks are prioritized.
downloadFile function to retrieve remote files given a file ID. This involves fetching signed URLs, verifying the downloaded binary, and converting it to a DataURI.
uploadFile function to push pending files to remote storage. Successful uploads remove the file ID from the pending list while keeping the file in the cache.
sync() function orchestrates synchronization:
maxCache.
maxCache and the cacheable list, removing files that are no longer cacheable or exceed the dynamic threshold (maxCache - pendingCount).
useFileUri hooks.
FileCacheProvider component makes the following API available via React Context:
maxCache: number - Maximum total items to cache.
maxPending: number (optional) - Maximum pending items to cache.
maxMounted: number (optional) - Maximum mounted items to auto-fetch when online.
maxRecent: number - Maximum recent items to keep in cache.
isOnline: boolean - Flag indicating online status, enabling auto-fetching of mounted ids.
getCacheableIds: (maxItemsToCache: number) => Promise (optional) - Function to fetch cacheable file IDs, ordered by recency.
uploadFile: (id: FileId, data: DataUri | Deleted) => Promise (optional) - Function to upload a file.
downloadFile: (id: FileId) => Promise (optional) - Function to download a file.
cacheStorage: ManagedUriStorage (optional) - Custom storage implementation.
pendingIds: AsyncState (optional) - Custom pending IDs state.
useItem(fileId?: FileId): () => AsyncState | Disabled - Hook to get a file's DataURI and setter.
useCacheList(): () => FileId[] | Loading - Hook to get an array of cached file IDs.
usePendingList(): () => FileId[] | Loading - Hook to get an array of pending file IDs.
useRecentList(): () => FileId[] | Loading - Hook to get an array of recent file IDs.
sync(options?: { signal?: AbortSignal; onProgress?: (progress: number) => void }): () => Promise | undefined - Function to trigger synchronization.
reset(): () => Promise | undefined - Function to reset the file cache. Dangerous - it will clear pending files too, but useful for secure logout.
tsx
import React from "react";
import {
FileCacheProvider,
useFileUri,
useFileCacheSync,
} from "./fileCache/provider";
import App from "./App";
// Replace these with your actual implementations.
const getFileUrls = async ({ id }: { id: string }) => ({
id,
getUrl: https://example.com/files/${id},
putUrl: https://example.com/files/${id},
mime: "image/png",
size: 12345,
sha256: "abcdef1234567890",
updatedAt: (Date.now() / 1000) | 0,
});
const uploadFile = async (id: string, dataUri: string) => {
console.log(Uploading file ${id} with data: ${dataUri});
};
const downloadFile = async (id: string) => {
// Simulate download logic.
return data:image/png;base64,...;
};
const Root = () => (
maxCache={50}
maxPending={10}
maxRecent={10}
isOnline={true}
getCacheableIds={async (max) => {
// Example: Return a static list or fetch from API.
return ["file-1", "file-2", "file-3", "file-4", "file-5"].slice(0, max);
}}
uploadFile={uploadFile}
downloadFile={downloadFile}
>
);
export default Root;
`
Using the Hooks
`tsx
import React from "react";
import { useFileUri, useFileCacheSync } from "./fileCache/provider";
const FileDisplay: React.FC<{ fileId: string }> = ({ fileId }) => {
const [dataUri, setDataUri] = useFileUri(fileId);
const handleFileChange = (event: React.ChangeEvent) => {
const file = event.target.files?.[0];
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
setDataUri(reader.result as string);
};
reader.readAsDataURL(file);
}
};
const handleDelete = () => {
setDataUri(null);
};
return (
{dataUri ? (
<>
src={dataUri}
alt="Cached file"
style={{ maxWidth: "200px", maxHeight: "200px" }}
/>
>
) : (
<>
Loading file...
>
)}
);
};
const SyncButton: React.FC = () => {
const sync = useFileCacheSync();
return ;
};
export default function App() {
return (
File Cache Demo
);
}
`
$3
- Provides access to a file's DataURI from the cache.
- Returns null if the file is not cached.
- Utilizes local and remote synchronization to ensure the cache is updated.
- Returns an async state tuple [dataUri, setDataUri].
$3
- Returns the sync function.
- Calling sync() triggers:
1. Upload of pending files.
2. Refresh of the cache with recently accessed and updated files from the remote source, respecting cache limits and pending priorities.
$3
- Returns an array of file IDs currently in the cache.
- Useful for displaying cached files or managing cache state.
$3
- Returns an array of file IDs that are pending upload.
- Allows monitoring and management of pending uploads.
$3
- Returns an array of file IDs that have been recently accessed.
- Helps in understanding file usage patterns and cache prioritization.
$3
- Returns the reset function.
- Calling reset()` clears the entire file cache, including cached files and all lists (pending, recent, mounted).