0.1.8 • Published 3 years ago

memlite v0.1.8

Weekly downloads
4
License
MIT
Repository
-
Last release
3 years ago

Memlite

Memlite is a SQLite state management library. It can be used to create, manage, and manipulate a state tree. mem stands for memory, as the SQLite database is held in memory.

Features

  • Platform/framework agnostic.
  • SQL state management (using SQLite).

Installation

npm i memlite

Quickstart

// initialize the mem
import memlite from 'memlite'

const context = mem => ({
  set(input){
    let sql = mem._db.prepare("UPDATE state set hello=?;");
    sql.run([input]);
  },
  clear(){
    mem._db.run("UPDATE state SET hello=null");
  }
})

// initialize the mem of the application
let mem = memlite.init({
  stateColumns: ["hello text"],
  features: [{ namespace: "quickstart", context: context }]
)

// access the state table
console.log(mem.state) // {hello: null}
mem.quickstart.set("world")
console.log(mem.state) // {hello: "world"}
mem.quickstart.clear()
console.log(mem.state) // {hello: null}

Documentation

Introduction

Memlite intends to provide an SQL-centric way of dealing with and building a state tree for consumption in parent applications, be it web, mobile, or desktop.

When To Use

You should reach for this library if: 1. You have a lot of local or fetched data that you would like to perform queries on. 2. You like SQL and think that it is a beautiful query language. 3. You like some magic but not too muchdo not like too much magic.

Mental Model

Memlite borrows some concepts from https://elixir-lang.org/, such as domain-driven design (in the form of feature contexts).

A mem object represents your app's current state and features at at any point in time. We change the application's state by executing functions declared in a feature's context. These functions (which may be referred to as handlers in the docs) will perform the logic required to update your app's state. These handlers do not necessarily need to update the SQL database, but could perform side effects or async data fetching. In any case, each context handler will have access to the mem object so that it can call other handlers as needed.

Each feature declared will represent a feature of your application, and would help to organize your business-logic in a feature-centric way. There are no fixed rules on file organization -- this is a library, not a framework.

Initialization

When initializing the mem, you can provide the following options:

  1. stateColumns: a list of sql columns to be added to the state table.
  2. features: refer to the Features section
  3. buildState: a function that receives the current state table as an object, and manipulates and returns a new state tree. By default, returns the state tree as is.
  4. internals: a boolean option that allows access to certain internal functions.

Accessing the Database

The SQLite database can be accessed through the mem._db property. This allows you to execute SQL statements as per the SQL.js API.

The State Table

The state table is simply a SQL table named "state" that is automatically defined on initialization. Any additional columns defined under stateColumns will be added to this table. This table exists as a singleton (meaning only one record is stored), thus any columns in the state table will be automatically mapped to an object key.

Features

A feature is made up of the following elements:

  1. namespace (string, required): a namespace on the mem to access this feature
  2. schema (string, optional): an sql schema related to this feature.
  3. context (function => object, optional): a function that accepts the mem and returns an object of context handlers that will interact with database and/or perform computations.

Namespaces

Namespaces allows you to register the context onto a namespace on the mem object. This allows for code organization and feature segregation.

For example, we can register a feature on the mem.hello namespace.

memlite.init({
  features: [{ namespace: "hello" }]
})

Schema

An sql schema can be provided for this feature. This can include one or more table definitions, indexes, triggers, etc. This string needs to be valid SQL statements, as there is no SQL syntax checking performed by this library.

For example, on our mem.todos namespace, we can create multiple tables.

const schema = `
CREATE TABLE todos (
	title TEXT,
	description TEXT,
	user_id INTEGER NOT NULL
);
CREATE TABLE todos_hierarchy (
	parent_id INTEGER NOT NULL,
	child_id INTEGER NOT NULL
);
`

memlite.init({
  features: [{ namespace: "todos", schema }]
})

In this example, we will create two tables, todos and todos_hierarchy. We can use todos_hierarchy to define task hierarchy in our todos feature.

When the database is initiated, the schemas are executed in sequential order as given in the features array. As such, schemas that depend on another feature's schema (such as triggers) should be placed after dependencies in order to get executed later.

Context

A context is a function that accepts the mem object and returns an object of context handlers.

Context handlers are functions that implement business logic. As these functions have access to mem, it allows for database reading/writing as well as accessing other context handlers.

You can also define a context handler that does not interact with the database, such as performing async datafetching.

Example

In this example, we will query the todos table to list all todos with their rowid that SQLite automatically creates. It is on the mem.todos namespace, hence we will call the list_todos() function to obtain the results from the database directly.

const schema = `
CREATE TABLE todos (
	title TEXT
);
`
const context = mem => ({
  list_todos(){
    return mem._db.run("SELECT rowid, title FROM todos");
  }
})

let mem = memlite.init({
  features: [{ namespace: "todos", schema }]
})

mem.todos.list_todos();

Developer

# install dependencies
npm i

# run tests
npm test

# dev in watch mode
npm run watch # in separate console
npm run test-watch # in separate console

# compile the library
npm run build

Architecture

TODO

License

MIT

0.1.8

3 years ago

0.1.7

3 years ago

0.1.2

3 years ago

0.1.1

3 years ago

0.1.4

3 years ago

0.1.3

3 years ago

0.1.6

3 years ago

0.1.5

3 years ago

0.1.0

3 years ago