lodat
v0.0.14
Published
Powerful persistent store for Javascript
Downloads
22
Maintainers
Readme
lodat (Local Database)
Powerful persistent store for Javascript. Compatible with (localStorage, sessionStorage, AsyncStorage, and many more)
Installation
npm install lodat --save
Getting started
Making a simple counter app using Lodat
import lodat from "lodat";
// create lodat db with some options
const db = lodat({
// by default, lodat stores data in memory
// in this case, we want to store data in localStorage,
// of course, we can specify other storages: sessionStorage, AsyncStorage or customized storage
storage: localStorage,
// specify initial data
initial: { count: 1 },
// this action will be called after db created
// note: this is a functional generator, we will take a look at this later on (please refer Generator Function)
*init() {
render();
},
});
// handle db updating
db.subscribe(render);
function* getCount({ get }) {
return yield get("count");
}
function* increase({ set }) {
yield set("count", (prev) => prev + 1);
}
async function render() {
const count = await db.exec(getCount);
document.body.innerHTML = `<h1>Counter: ${count}</h1>`;
}
setInterval(() => {
db.exec(increase);
}, 1000);
Using schema
import lodat from "lodat";
const db = lodat({
schemas: {
// "todos" is context prop name, its map to "todo" schema
todos: "todo",
},
});
function* addTodo(context) {
return yield context.todos.create({ title: "new todo" });
}
function* removeTodo(context, key) {
yield context.todos.remove(key);
}
const newTodo = await db.exec(addTodo);
db.exec(removeTodo, newTodo.key);
Querying entity
function* getCompletedTodos(context) {
return yield context.todos.all((todo) => todo.completed);
}
function* getFirstCompletedTodos(context) {
return yield context.todos.get((todo) => todo.completed);
}
function* getTodoByKey(context, key) {
return yield context.todos.get(key);
}
Storing data in cookie
import { CookieStorage } from "cookie-storage";
const db = lodat({ storage: new CookieStorage() });
Examples
Performance testing (TBD)
Lodat is about 10x faster than lowdb Add and update 1000 todos
References
lodat(options)
options:
| name | type | description | | :------- | ----------------------------------------- | -------------------------------------------------------- | | name | string | database name (def = '') | | storage | Storage object | specify storage type will be used (def = memoryStorage) | | debounce | number | specify writing debouncing (def = 0, no debouncing) | | initial | any | specify default data | | init | Generator Function | specify an action will be executed in initializing phase | | schemas | string[] | list of schema names | | schemas | { prop: 'schema name' } | schema mappings |
Return: Database instance
Database props
| name | return | description | | :----------------------- | -------------------- | ------------------------------------------------------------------------------------------------------ | | exec(executor, payload?) | Promise | execute an executor with specified payload. Executor must be Generator Function | | subscribe(listener) | Unsubscribe function | add a change listener. It will be called any time an data manipulated | | clear() | void | clear all data | | flush() | void | flush all pending writes to storage |
Context props
| name | type/return | description | | :----------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | | schema(name) | Schema object | get specified schema by its name | | get(name) | Yield | get value of specified database prop | | set(name, value) | Yield | set value of specified database prop | | set(name, reducerFn) | Yield | set value of specified database prop using reducerFn, the reducerFn retrieves previous value as first argument | | exec(executor, payload?) | Yield | execute an executor with specified payload. Executor must be Generator Function | | fork(executor, payload?) | Yield | execute an executor with specified payload and dont block current execution. Executor must be Generator Function |
Schema props
| name | type/return | description | | :---------------------- | -------------------- | ---------------------------------------------------------------------------------------- | | name | string | schema name | | create(props) | Yield | create new entity with specified props | | exist(entityKey) | Yield | check entity existing by its key | | remove(...entityKeys) | Yield | remove multiple entities by their keys | | count() | Yield | return a number of entity in the schema | | all() | Yield<Entity[]> | return all entities in the schema | | all(limit) | Yield<Entity[]> | return first N entities in the schema | | all(entityKeys) | Yield<Entity[]> | return all entities that matches given keys | | all(predicateFn) | Yield<Entity[]> | return all entities that matches given predicateFn | | all(predicateFn, limit) | Yield<Entity[]> | return first N entities that matches given predicateFn | | get(entityKey) | Yield | get entity by key | | get(predicateFn) | Yield | get first entity that matches given predicateFn | | clear() | Yield | clear all entities in the schema | | update(entity, props) | Yield | update specified entity with new props, if no props changed, nothing to write to storage | | subscribe(listener) | Unsubscribe function | add a change listener. It will be called any time an entity manipulated |
Generator Function
Lodat uses generator function to control reading or writing data flows and async execution (no async/await needed). Below is simple generator function.
function* generatorFunction(generatorContext, payload) {
// a generatorContext provides many util methods, please refer Context props section for further info
// retrieve return value from yield expression
const returnValueOfDoSomething = yield generatorContext.doSomething(payload);
// retrieve resolved value from promise
const resolvedValue = yield ApiCall(payload);
}