Don't forgot to follow the project's author, Ezz, and consider starring the project to show your ❤️ and support.
Imagine that you're working on an application that required to use browser storages depends on browser support, data amount, or a case that required to choose storage on runtime.
You're frequently changing your backend service and for a reason, you want to switch from firebase to another cool thing, and a problem arise where you afraid from changing due to different functionality, ...etc.
Facilitate the way to sync the data from the browser storage (WebSql, IndexDB) to the server either in Web worker or in the default browser context.
(write once and change without worry)
How to think of it! you have a key value pairs object and you want to treat it as model where you can save, update, retrive and delete the data from.
-
Sync storages
- Local storage
- Session storage
- In Memory storage ( simple plain object {} )
-
Async storages
- IndexedDB (using idb)
- KeyValue store (idb-keyval)
1. database.collection(string name); // fetch the collection if exist or create new one
2. database.clear(); // clear out the entire database
3. collection.create(T obj) // store POJO and patch auto increment id as number
4. collection.update(Entity < T > entity) // replace the old Entity object with new Entity Object
5. collection.delete(number id) // delete and entity object using it's id
6. collection.set(Entity < T > entity) // replace an entity if exist or create new one
7. collection.clear() // clear out the entire collection
8. collection.get((T entity, number index) => boolean) // query for a specific entity and return the first match
First kind of database that implements the blocking operation like LocalStorage
const pojo = {
name: 'MyName',
age: 10
};
const db = new SyncDatabase(new Localstorage('MyStorage'))
const collection = db.collection('MyCollection');
const entity = collection.create(pojo);
collection.delete(entity.id);
Second kind of database that implements the non-blocking operation like IndexedDB
, Http
and any Storage that doesn't block the execution
const pojo = {
name: 'MyName',
age: 10
};
const db = new AsyncDatabase(new IndexDB('MyObjectStore'));
const collection = db.collection('MyCollection');
const entity = await collection.create(pojo);
await collection.delete(entity.id);
In order to use custom storage all that you need is to Implement the either the IAsyncStorage
interface or ISyncStorage
depends on your needs
class BackendStorage implements IAsyncStorage {
get<T>(name: string): Promise<Entity<T>> {
return fetch( `url/${name}` )
.then(res => res.json());
}
clear(name?: string): Promise<void> {
return fetch( `url/${name}` , {
method: 'POST',
body: JSON.stringify([])
})
.then(res => res.json());
}
set<T>(name: string, value: Entity<T>[]): Promise<void> {
return fetch( `url/${name}` , {
method: 'POST',
body: JSON.stringify(value)
})
.then(res => res.json());
}
}
const database = new AsyncDatabase(new BackendStorage());
const collection = database.collection('MyCollection');
please note that the url/${name}
name part is the collection name
Up until now, you learned how to use the offered Storages with Database and how we can store multiple collections within each storage but what if you just want to deal with LocalStorage directly or InMemoryStorage! All storages implement ISyncStorage, therefore, the offered API's are the same
const storage = new Storage('NameSpace');
storage.set('myKey', [{}]) // save the [{}] inside the localstorage;
storage.get('myKey') // retrieve the associated value from localstorage.NameSpace
storage.delete('myKey') // delete the associated value
storage.clear(); // clear out the entire NameSpace
- Angular
Angular uses a dependency injection framework to handle instances instantiating so we need to adhere to that way in order to get the same instance from the root module Note: lazy loading modules working differently which implies that lazyloaded module instances are different from eager modules instances
providers: [
{
provide: LocalStorage,
useValue: new LocalStorage('StorageName'),
},
{
provide: SessionStorage,
useValue: new SessionStorage('StorageName'),
}
]
SSR will required additional setup by the way since LocalStorage, SessionStorage not available in server side
Should you use this library? I think the above reasons are not desired all of this, in general, overengineer the code is a bad thing, so you really need to think twice before immediately digging with it.
- This library built on top of typescript so it's fully supported for types,
- The only way to install through npm (NO CDN).
- It could be used in Node Js since it's plain functions and objects nothing related to a browser unless you decided to use browser things.
- Entity! just a fancy name.
Don't hesitate to open issues and make a pull request to help improve code
- Fork it!
- Create your feature branch:
git checkout -b my-new-feature
- Commit your changes:
git commit -m 'Add some feature'
- Push to the branch:
git push origin my-new-feature
- Submit a pull request :D
This library will be maintained under the semantic versioning guidelines.
Releases will be numbered with the following format:
<major>.<minor>.<patch>
For more information on SemVer, please visit semver.
- Support transactions
- Better error handling
- Limit collection size