HybridWebCache
is a library for efficient cache management in web applications, supporting multiple storage mechanisms transparently (LocalStorage, IndexedDB, SessionStorage and memory). With TTL (Time-To-Live) support, the library helps optimize performance by storing and retrieving data efficiently.
- Hybrid caching
- LocalStorage
- SessionStorage
- IndexedDB
- Memory (fallback)
- Automatic expiration management (TTL)
- TypeScript support
- PWA-compatible
- Simple integration with modern frameworks
-
/src
- Main source code -
/test
- Unit tests -
/test/demo
- Web demo application
-
src/index.ts
- Entry point -
src/core/strategies
- Different storage strategies -
src/core/HybridWebCache.ts
- Main class
You can install the library using npm
or yarn
:
npm i hybrid-webcache
# or
yarn add hybrid-webcache
To use the library in a TypeScript or modern JavaScript project, you can import it directly:
import { HybridWebCache } from 'hybrid-webcache';
const cache = new HybridWebCache();
await cache.set('sessionToken', 'abc123');
const token = await cache.get<string>('sessionToken');
console.log(`Token: ${token.value}`); // Output: Token: abc123
To create a HybridWebCache instance, you need to provide a name for the database and optionally settings:
const cache = new HybridWebCache('MyApp', {
ttl: { minutes: 10, days: 1 },
removeExpired: true,
storage: StorageType.Auto
});
- Provides a unified interface for caching data using different storage backends.
- Supports TTL for cache entries to automatically expire data.
- Offers both asynchronous and synchronous methods for setting, getting, and removing cache entries.
-
constructor
: Initializes the cache with a base name and options, determining the storage engine. -
set
/setSync
: Stores a value in the cache with an optional TTL. -
get
/getSync
: Retrieves a value from the cache, optionally removing expired entries. -
unset
/unsetSync
: Removes a value from the cache. -
has
/hasSync
: Checks if a key path exists -
getAll
/getAllSync
: Retrieves all cache entries, optionally removing expired ones. -
getJson
/getJsonSync
: Returns all cache entries as a JSON object, optionally removing expired ones. -
resetWith
/resetWithSync
: Clears the cache and sets new key-value pairs.
-
baseName
: The base name for the cache, used as a prefix for keys. -
options
: Configuration options for the cache, including TTL and storage type. -
storageEngine
: The storage mechanism used for caching, determined at initialization.
Parameter | Type | Description |
---|---|---|
ttl |
TTLType |
Sets the time to live for data in the cache. Can be in minutes, hours, or days. |
removeExpired |
boolean |
Automatically removes expired items when attempting to access them. |
storage |
StorageType |
Auto , LocalStorage , IndexedDB , SessionStorage or Memory . Sets the storage engine. Auto selects the best available. |
enum StorageType {
Auto,
LocalStorage,
IndexedDB,
SessionStorage,
Memory
}
type ValueTypes = null | string | number | boolean | object | DictionaryType | ValueTypes[];
type DictionaryType = { [key: string]: ValueTypes };
type KeyValues<T extends ValueTypes> = Record<string, T>;
type KeyPath = string | Array<string>;
type TTLType = number | { seconds?: number; minutes?: number; hours?: number; days?: number };
type OptionsType = {
storage: StorageType;
ttl: Partial<TTLType>;
removeExpired: boolean;
};
interface DataSetType<T> {
value: T;
expiresAt: number;
}
interface DataGetType<T> extends DataSetType<T> {
isExpired: boolean;
}
/**
* Default Options
*
* baseName: 'HybridWebCache',
* {
* ttl: { seconds: 0, minutes: 0, hours: 1, days: 0 },
* removeExpired: true,
* storage: StorageType.Auto
* }
*/
const cache = new HybridWebCache()
-- or --
// create an instance for IndexedDB with TTL of 10 minutes and removal of expired items to default
const cache = new HybridWebCache('myCache', { storage: StorageType.IndexedDB, ttl: 10 * 60 * 1000, removeExpired: true });
await cache.set('userProfile', { name: 'Jane', age: 25 });
const profile = await cache.get<{ name: string; age: number }>('userProfile');
console.log(`User: ${profile.value.name}, Age: ${profile.value.age}`); // Output: User: Jane, Age: 25
// Set a value with a TTL of 1 hour
await cache.set('user.firstName', 'John', { hours: 1 });
cache.setSync('user.lastName', 'Doe'); //TTL = 10 minutes
// Retrieve the value
const userName = await cache.get('user.firstName');
// Outputs -> '{value: 'John', expiresAt: 999999999, isExpired: false}'
const user = cache.getSync('user').value;
// Outputs -> {user: {firstName: 'John', lastName: 'Doe' }}
cache.setSync(['user', 'age'], 33);
const user = cache.getSync('user').value;
// Outputs -> {user: {firstName: 'John', lastName: 'Doe', age: 33 }}
// Check if a key exists
const hasUser = await cache.has('user.name');
console.log(hasUser); // Outputs: true
// Remove a key
await cache.unset('user.name');
const color =
{
"name": "cerulean",
"code": {
"hex": "#003BE6",
"rgb": [0, 179, 230]
}
}
// Set a key-value
cache.setSync(['settings', 'language'], "pt-Br");
cache.getSync(['settings', 'language']).value;
// => 'pt-Br'
// Set/Add a key settings
cache.setSync("settings.default", "en");
cache.getSync("settings").value;
// => { "language": "pt-Br", "default": "en" }
cache.getAllSync();
// => { "settings": {value:{ "language": "pt-Br", "default": "en" }, expiresAt: 1733628804164, isExpired: false }}
// replace key settings
cache.setSync("settings", { theme: "dark"});
cache.getSync("settings").value;
// => { "theme": "dark" }
// Added a new key-value
cache.setSync("color", color);
cache.getSync().value;
// => { "theme": "dark", "color": { "name": "cerulean", "code": { "rgb": [0, 179, 230], "hex": "#003BE6" } } }
// Replace all key-values
cache.setSync(color);
cache.getSync().value;
// => { "name": "cerulean", "code": { "rgb": [0, 179, 230], "hex": "#003BE6" } }
// Unset a key-value
cache.unsetSync();
cache.getSync().value;
// => {}
// Set a new key-values
cache.setSync("color", color);
cache.getSync().value;
// => { "color": { "name": "cerulean", "code": { "rgb": [0, 179, 230], "hex": "#003BE6" } } }
cache.getSync("color.name").value;
// => "cerulean"
cache.getSync("color.code.hex").value;
// => "#003BE6"
cache.getSync(["color", "code"]).value;
-- or --
cache.getSync("color.code").value;
// => { "hex": "#003BE6", "rgb": [0, 179, 230] }
cache.getSync(["color", "hue"]).value;
// => undefined
// Set a key-value pair
await cache.set("color.name", "sapphire");
// Get the value at a specific key path
const value = await cache.get("color.name").value;
// => "sapphire"
// Check if a key path exists
const exists = await cache.has("color.name");
// => true
// Remove a key-value pair
await cache.unset("color.name");
await cache.getAll();
// Result Map(key, value) => { key: "code", value: {expiresAt: 1733628804164, isExpired: false, value: {"rgb": [0, 179, 230], "hex": "#003BE6" } } }
await cache.getJson();
// => {"code": {"rgb": [0, 179, 230], "hex": "#003BE6"} }
const exists = cache.hasSync("color.name");
// => false
cache.unset().then(() => {
console.log("All key-value pairs have been removed.");
})
- lodash: For object manipulation
- Typescript: For static typing
- Jest: For testing
Please make sure to read the Contributing Guide before making a pull request.
Thank you to all the people who already contributed to project!
Made with contrib.rocks.
That said, there's a bunch of ways you can contribute to this project, like by:
- 🪲 Reporting a bug
- 📄 Improving this documentation
- 🚨 Sharing this project and recommending it to your friends
- 💵 Supporting this project on GitHub Sponsors or Ko-fi
- 🌟 Giving a star on this repository
If you appreciate that, please consider donating to the Developer.