Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

lodat

linq2js38ISC0.0.14TypeScript support: included

Powerful persistent store for Javascript

indexeddb, localstorage, local-storage, sessionstorage, session-storage, store, storage, offlinestorage, offline-storage, asyncstorage, async-storage, json

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);
}
import { CookieStorage } from "cookie-storage";

const db = lodat({ storage: new CookieStorage() });

Examples

  1. Todo App

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<any> get value of specified database prop
set(name, value) Yield<void> set value of specified database prop
set(name, reducerFn) Yield<void> set value of specified database prop using reducerFn, the reducerFn retrieves previous value as first argument
exec(executor, payload?) Yield<void> execute an executor with specified payload. Executor must be Generator Function
fork(executor, payload?) Yield<void> 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<Entity> create new entity with specified props
exist(entityKey) Yield<bool> check entity existing by its key
remove(...entityKeys) Yield<void> remove multiple entities by their keys
count() Yield<number> 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<Entity> get entity by key
get(predicateFn) Yield<Entity> get first entity that matches given predicateFn
clear() Yield<void> clear all entities in the schema
update(entity, props) Yield<void> 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);
}