Top Related Projects
💾 Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.
Cross-browser storage for all use cases, used across the web.
Simple and fast JSON database
IndexedDB, but with promises
A Minimalistic Wrapper for IndexedDB
Quick Overview
ImmortalDB is a JavaScript library that provides a resilient key-value store for the browser. It utilizes multiple storage mechanisms (localStorage, IndexedDB, and cookies) to ensure data persistence across different scenarios, including private browsing and browser restarts.
Pros
- Highly resilient storage solution that combines multiple storage mechanisms
- Automatic fallback to alternative storage methods if one fails
- Simple API that mimics localStorage for ease of use
- Supports both synchronous and asynchronous operations
Cons
- Increased complexity compared to using a single storage method
- Potential performance overhead due to multiple storage operations
- Limited to browser environments
- May not be necessary for applications with simple storage needs
Code Examples
Setting a value:
import { ImmortalDB } from 'immortal-db';
await ImmortalDB.set('key', 'value');
Getting a value:
import { ImmortalDB } from 'immortal-db';
const value = await ImmortalDB.get('key', 'defaultValue');
console.log(value);
Removing a value:
import { ImmortalDB } from 'immortal-db';
await ImmortalDB.remove('key');
Getting Started
To use ImmortalDB in your project, follow these steps:
-
Install the package:
npm install immortal-db
-
Import and use ImmortalDB in your JavaScript code:
import { ImmortalDB } from 'immortal-db'; // Set a value await ImmortalDB.set('username', 'JohnDoe'); // Get a value const username = await ImmortalDB.get('username'); console.log(username); // Remove a value await ImmortalDB.remove('username');
ImmortalDB provides both synchronous and asynchronous methods. The asynchronous methods (like those shown above) are recommended for better performance and compatibility.
Competitor Comparisons
💾 Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.
Pros of localForage
- More mature and widely adopted project with a larger community
- Supports multiple storage backends (IndexedDB, WebSQL, localStorage)
- Provides a simple key-value API with support for storing complex data types
Cons of localForage
- Larger file size and potentially more overhead
- Less focus on data persistence across browser sessions and tab closures
Code Comparison
localForage:
localforage.setItem('key', 'value').then(function () {
return localforage.getItem('key');
}).then(function (value) {
console.log(value);
}).catch(function (err) {
console.log(err);
});
ImmortalDB:
await ImmortalDB.set('key', 'value');
const value = await ImmortalDB.get('key');
console.log(value);
Key Differences
- ImmortalDB focuses on data persistence across browser sessions and tab closures, while localForage primarily aims to provide a unified API for different storage backends.
- localForage offers more storage options and a larger feature set, while ImmortalDB prioritizes simplicity and robustness.
- ImmortalDB uses a Promise-based API by default, whereas localForage supports both callback and Promise-based approaches.
Both libraries serve different use cases and have their own strengths. Choose based on your specific requirements for data persistence, browser support, and storage flexibility.
Cross-browser storage for all use cases, used across the web.
Pros of store.js
- Broader browser support, including older versions of IE
- Fallback mechanisms for various storage types (localStorage, globalStorage, userData)
- Simpler API with fewer methods, potentially easier for beginners
Cons of store.js
- Less active development and maintenance
- Lacks advanced features like encryption and multi-tab synchronization
- No built-in expiration functionality for stored items
Code Comparison
store.js:
store.set('user', { name: 'Marcus' })
store.get('user')
store.remove('user')
store.clearAll()
ImmortalDB:
await db.set('user', { name: 'Marcus' })
await db.get('user')
await db.remove('user')
await db.clear()
Key Differences
- ImmortalDB uses Promises and async/await for all operations, while store.js uses synchronous methods
- ImmortalDB offers built-in encryption and multi-tab synchronization
- store.js provides a more extensive fallback system for older browsers
- ImmortalDB has a larger API with additional features like
setMany()
andgetMany()
Use Cases
- Choose store.js for projects requiring support for very old browsers or a simpler storage API
- Opt for ImmortalDB when security, multi-tab support, and modern JavaScript features are priorities
Both libraries serve as client-side storage solutions, but ImmortalDB offers more advanced features and security measures, while store.js focuses on broad compatibility and simplicity.
Simple and fast JSON database
Pros of lowdb
- Supports Node.js and browser environments
- Offers a simple API inspired by Lodash
- Allows for easy data persistence to JSON files
Cons of lowdb
- Less focus on data durability and persistence across browser sessions
- May require additional setup for complex data structures
- Limited built-in support for encryption or data security
Code Comparison
ImmortalDB:
const db = new ImmortalDB();
await db.set('key', 'value');
const value = await db.get('key');
lowdb:
const adapter = new JSONFile('db.json');
const db = new Low(adapter);
await db.read();
db.data ||= { posts: [] };
db.data.posts.push({ id: 1, title: 'lowdb is awesome' });
await db.write();
Key Differences
ImmortalDB focuses on providing a durable key-value store for web browsers, emphasizing data persistence across sessions and tabs. It uses multiple storage mechanisms to ensure data survival.
lowdb, on the other hand, is a lightweight JSON database that can be used in both Node.js and browser environments. It offers a more flexible API for working with JSON data and is better suited for applications that require simple data persistence and manipulation.
While ImmortalDB excels in browser-based durability, lowdb provides a more versatile solution for general-purpose JSON data storage and manipulation across different JavaScript environments.
IndexedDB, but with promises
Pros of idb
- Provides a more comprehensive and low-level API for IndexedDB
- Offers better TypeScript support and type definitions
- Actively maintained with regular updates and improvements
Cons of idb
- Requires more setup and configuration compared to ImmortalDB
- Has a steeper learning curve for developers new to IndexedDB
- Lacks built-in support for multiple storage mechanisms
Code Comparison
ImmortalDB:
import ImmortalDB from 'immortal-db';
await ImmortalDB.set('key', 'value');
const value = await ImmortalDB.get('key');
idb:
import { openDB } from 'idb';
const db = await openDB('myDatabase', 1, {
upgrade(db) {
db.createObjectStore('myStore');
},
});
await db.put('myStore', 'value', 'key');
const value = await db.get('myStore', 'key');
ImmortalDB provides a simpler API for basic key-value storage, while idb offers more control and flexibility for complex database operations. ImmortalDB abstracts away the underlying storage mechanisms, making it easier to use but less customizable. idb, on the other hand, provides a more direct interface to IndexedDB, allowing for advanced features and better performance optimization at the cost of increased complexity.
A Minimalistic Wrapper for IndexedDB
Pros of Dexie.js
- More comprehensive IndexedDB wrapper with advanced querying capabilities
- Supports complex data structures and relationships
- Active development and larger community support
Cons of Dexie.js
- Steeper learning curve due to more complex API
- Larger file size and potentially higher overhead
Code Comparison
ImmortalDB:
const db = new ImmortalDB();
await db.set('key', 'value');
const value = await db.get('key');
Dexie.js:
const db = new Dexie('MyDatabase');
db.version(1).stores({ items: '++id, name, price' });
await db.items.add({ name: 'apple', price: 1.5 });
const items = await db.items.where('price').above(1).toArray();
Summary
Dexie.js is a more feature-rich IndexedDB wrapper suitable for complex data management in web applications. It offers advanced querying and support for relationships between objects. However, it comes with a steeper learning curve and larger footprint compared to ImmortalDB.
ImmortalDB, on the other hand, provides a simpler key-value storage solution with built-in redundancy across multiple storage mechanisms. It's easier to use for basic storage needs but lacks the advanced features of Dexie.js.
Choose Dexie.js for complex data management requirements, and ImmortalDB for simpler, redundant storage needs in web applications.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
ImmortalDB
ImmortalDB is a resilient key-value store for the browser.
ImmortalDB is the best way to store persistent key-value data in the browser. Data saved to ImmortalDB is redundantly stored in Cookies, IndexedDB, and LocalStorage, and relentlessly self heals if any data therein is deleted or corrupted.
For example, clearing cookies is a common user action, even for non-technical users. And browsers unceremoniously delete IndexedDB, LocalStorage, and/or SessionStorage without warning under storage pressure.
ImmortalDB is resilient in the face of such events.
In this way, ImmortalDB is like Evercookie, but
-
Is actively maintained and well documented.
-
Provides a simple, modern, Promise-based API.
-
Strikes an equitable balance between reliability and respect for the user. Data is stored reliably but can also be voluntarily purged if the user designedly clears cookies and application storage.
-
Doesn't use nefarious exploits nor deprecated third party plugins like Flash, Silverlight, or Java. Only standard, ratified HTML5 APIs are used.
-
Doesn't vandalize performance or the user experience. For example, Evercookie's CSS History Knocking can beget a deluge of background HTTP requests, and loading Silverlight or Flash can raise unsought permission modals or thrash the user's disk.
How ImmortalDB works.
When you store a key-value pair in ImmortalDB, that key and value are saved redundantly in the browser's cookies, IndexedDB, and LocalStorage data stores.
When a value is retrieved via its key, ImmortalDB
- Looks up that key in every data store.
- Counts each unique returned value.
- Determines the most commonly returned unique value as the 'correct' value.
- Returns this correct value.
Then ImmortalDB self-heals: if any data store(s) returned a value different than the determined correct value, or no value at all, the correct value is rewritten to that store. In this way, consensus, reliability, and redundancy is maintained.
API
Set
ImmortalDB's API is simple. To store a value, use set(key, value)
:
import { ImmortalDB } from 'immortal-db'
await ImmortalDB.set('key', 'value')
key
and value
must be
DOMStrings.
ImmortalDB.set(key, value)
also always returns value
, so it can be chained or
embedded, like
const countPlusOne = (await ImmortalDB.set('count', numberOfClowns)) + 1
Get
To retrieve a value, use get(key, default=null)
:
const value = await ImmortalDB.get('key', default=null)
get()
returns the value associated with key
, if key
exists. If key
doesn't exist, default
is returned. key
must be a
DOMString.
Remove
Finally, to remove a key, use remove(key)
:
ImmortalDB.set('hi', 'bonjour')
console.log(await ImmortalDB.get('hi')) // Prints 'bonjour'.
await ImmortalDB.remove('hi')
console.log(await ImmortalDB.get('hi')) // Prints 'null'.
key
must be a
DOMString.
Data Stores
The data stores that ImmortalDB stores data in can also be configured. For example, this is how to store data reliably in cookies and LocalStorage only:
import { ImmortalStorage, CookieStore, LocalStorageStore } from 'immortal-db'
const stores = [await CookieStore(), await LocalStorageStore()]
const db = new ImmortalStorage(stores)
await db.set(key, JSON.stringify({1:1}))
By default, stores used by ImmortalDB
are:
CookieStore
-> Keys and values are stored indocument.cookie
.IndexedDbStore
-> Keys and values are stored inwindow.indexedDB
.LocalStorageStore
-> Keys and values are stored inwindow.localStorage
.
Other, optional stores are:
SessionStorageStore
-> Keys and values are stored inwindow.sessionStorage
.
New storage implementations can easily be added, too; they need only
implement the async methods get(key, default)
, set(key, value)
, and
remove(key)
.
Installation
Installing ImmortalDB with npm is easy.
$ npm install immortal-db
Or include dist/immortal-db[.min].js
and use window.ImmortalDB
directly.
<html>
<head>
<script src="immortal-db.min.js"></script>
<script>
;(async () => {
const db = ImmortalDB.ImmortalDB
await db.set('hi', 'lolsup')
})()
</script>
</head>
...
</html>
Development
To test ImmortalDB, run
npm run start
This starts a webpack dev server and opens ImmortalDB's testing website, http://localhost:9234/.
Once tested, to produce new production-ready files immortal-db.js
and
immortal-db.min.js
in dist/
, run
npm run build
Top Related Projects
💾 Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.
Cross-browser storage for all use cases, used across the web.
Simple and fast JSON database
IndexedDB, but with promises
A Minimalistic Wrapper for IndexedDB
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot