Skip to content

Commit

Permalink
updated docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Ziinc committed Jul 11, 2021
1 parent 98accaf commit ebc09a2
Showing 1 changed file with 50 additions and 39 deletions.
89 changes: 50 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# 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.

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).
- SQL state masnagement (using SQLite).

## Installation

```bash
npm i memlite
```
Expand Down Expand Up @@ -46,20 +46,27 @@ 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.
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.
3. You like some magic but not too much.
#### Mental Model
Memlite borrows some concepts from [https://elixir-lang.org/](Elixir), 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.
Memlite allows 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` from the view layer. These context functions may perform side effects as well, such as async data fetching and loading into the database.
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.
Each context handler has access to the `mem` object, allowing it to call other context functions as needed.
There are no fixed rules on file organization -- this is a li
brary, not a framework.
### Initialization
Expand All @@ -82,29 +89,33 @@ The state table is simply a SQL table named "state" that is automatically define
A feature is made up of the following elements:
1. **namespace** (string, required): a namespace on the `mem` to access this feature
3. **schema** (string, optional): an sql schema related to this feature.
4. **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.
1. **namespace** (string, required): a namespace on the `mem` to access this feature, for feature segregation.
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 that will interact with the 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.
#### Namespace
For example, we can register a feature on the `mem.hello` namespace.
```js
memlite.init({
features: [{ namespace: "hello" }]
})
const app = memlite.init({
features: [{ namespace: "hello" }],
});

// access the feature
app.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.
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.
```js
const schema = `
const todoFeature = {
namespace: todos,
schema: `
CREATE TABLE todos (
title TEXT,
description TEXT,
Expand All @@ -114,40 +125,40 @@ CREATE TABLE todos_hierarchy (
parent_id INTEGER NOT NULL,
child_id INTEGER NOT NULL
);
`
`,
};

memlite.init({
features: [{ namespace: "todos", schema }]
})
const app = memlite.init({ features: [todoFeature] });
```
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.
A context is a function that accepts the `mem` object and returns an object of **functions**.
Context functions implement state updating logic. As these functions have access to `mem`, it allows for database reading/writing as well as accessing other context functions.
You can also define a context handler that does not interact with the database, such as performing async datafetching.
You can also define a context function 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.
```js
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 }]
})
```js
const todoFeature = {
namespace: "todos",
schema: "CREATE TABLE todos (title TEXT);",
context: (mem) => ({
list_todos() {
return mem._db.run("SELECT rowid, title FROM todos");
},
}),
};

let mem = memlite.init({ features: [todoFeature] });

mem.todos.list_todos();
```
Expand Down

0 comments on commit ebc09a2

Please sign in to comment.