remajo

0.0.1 • Public • Published

Remajo: REdis MApping -> Js Object

Remajo maps Redis data into javascript objects, supporting multiple levels of hierarchy. It uses a model written in JSON to specify how the data is composed, allowing you to only pull back what you're interested in.

Node Express endpoints are automatically generated for you, exposing your models as a REST API.

Usage

Install via npm:

npm install remajo --save
  1. Create a client in redis.
  2. Pass the client into remajo.builder(), along with your models.
  3. Create a resource from the models you wish to perform actions on
  4. If you wish to expose endpoints, use [resource].expose(), passing in an express router var.
//basic express setup
var express = require('express');
var app = express();
var router = express.Router();

...

var redis = require('redis');
var db = redis.createClient();
var remajo = require('remajo');

//initialize your data model
var builder = remajo.builder(client, {
  user: {
    fields: [ 'username', 'avatar' ],
    subs: [
      {type: 'theme'}
    ],
    sets: [
      {type: 'task'}
    ]
  },

  task: {
    fields: [ 'text', 'done' ]
  },

  theme: {
    fields: [ 'name', 'variant' ]
  }
});

//create a resource to allow direct list/read/create/update/delete commands
var user = builder.build('user');

//expose resource as REST endpoints
user.expose(router, '/api/users', true);
app.use('/', router);

Models

Define your object's model in JSON. Fields with an asterisk* are automatically defaulted if no value is supplied.

Type model

Key Description
set * (string: pattern) Location of Set identifying all members. Defaults to [name]:all.
incr * (string) Key where latest id of this object is stored. Remajo will INCR this field to get ids for any new object. Defaults to [name]:id.
rkey * (string: pattern) Pattern defining the key for this item. "$id" will be replaced with this object's id. Defaults to [name]:$id.
fields (array) List of fields in this object.
subs (subtype) List of fields
sets (array of subtype) Define hierarchical data by adding subset models.

Subtype

Key Description
type (string: pattern) Pattern defining the key for this item. "$id" will be replaced with this object's id.
key * (string: pattern) Location of Set identifying all members
join * (string) Key where latest id of this object is stored. Remajo will INCR this field to get ids for any new object.

Remajo supports string-value object properties, as well as properties that hold an array of another object.

Example user-defined models:

user: {
  fields: [ 'username', 'avatar' ],
  subs: [
    {type: 'theme'}
  ],
  sets: [
    {type: 'task'}
  ]
},

task: {
  fields: [ 'text', 'done' ]
},

theme: {
  fields: [ 'name', 'variant' ]
}

These models automatically receive default fields, resulting in:

user: {
  set: 'user:all',
  incr: 'user:id',
  rkey: 'user:$id',
  fields: [ 'username', 'avatar' ],
  subs: [
    {type: 'theme', key: 'theme', join: '$parent:theme'}
  ],
  sets: [
    {type: 'task', key: 'tasks', join: '$parent:tasks'}
  ]
}

task: {
  set: 'task:all',
  incr: 'task:id',
  rkey: 'task:$id',
  fields: [ 'text', 'done' ]
}

theme: {
  set: 'theme:all',
  incr: 'theme:id',
  rkey: 'theme:$id',
  fields: [ 'name', 'variant' ]
}

This model will translate into an object like the following:

{
  id: 1,
  username: 'Remajo',
  avatar: 'remajo.jpg',
  theme: {
    name: 'meranti',
    variant: 'dark'
  },
  tasks: [
    {id: 100, text: 'find food', done: 'true'},
    {id: 101, text: 'eat food', done: 'false'}
  ]
}

...and in Redis, the corresponding data looks like this:

Key Type Value
user:all set [ 1 ]
user:id string 1
user:1 hash { id: 1, username: 'Remajo', avatar: 'remajo.jpg' }
user:1:theme string [ 100 ]
theme:id string 100
theme:100 hash { id: 100, name: 'meranti', variant: 'dark' }
user:1:tasks set [ 1000, 1001 ]
task:id string 1001
task:1000 hash { id: 1000, text: 'find food', done: 'true' }
task:1001 hash { id: 1001, text: 'eat food', done: 'false' }

Remajo uses Redis Strings, Sets and Hashes to store the various pieces of your object's data. Generally, objects properties are stored in a Hash, under the key defined in the rkey pattern.

Patterns

Patterns are very simplistic for now, and only support "$id" to represent a placeholder for the object id, and $parent to represent a placeholder for the parent id.

user:$id → "user:1"

Resources

Resources are exposed by calling build() with the name of the type.

//create a resource to allow direct list/read/create/update/delete commands
var user = builder.build('user');
Action Promise returns Notes
.list() array(items) retrieve all records listed under model's 'set'
.create(obj) id
.read(id) item
.update(obj) id obj must contain id field, otherwise it will be routed to create().
.del(id) id

All actions return promises:

    user.read(1)
    .then(function(userObj) {
    	//do something with userObj
    });

Endpoints

You can add REST endpoints to your server by calling expose() on you Resource object.

//expose resource as REST endpoints
user.expose(router, '/api/users', true);
app.use('/', router);
Param Type Desc
router Express.Router
route string i.e., '/api/users'
exposeSets bool expose sets under individual paths

Routes

With a 'user' resource exposed under '/api/users', the following is exposed:

Path Method Action
/api/users GET user.list()
/api/users POST user.create()
/api/users/:id GET user.read(:id)
/api/users/:id PUT user.update(:id)
/api/users/:id DELETE user.del(:id)

Exposing subsets

The exposeSets option allows you to expose "set" subobject under an individual path. For example, with the following model:

user: {
  fields: [ 'username', 'avatar' ],
  sets: [
    {type: 'task'}
  ]
},

...these additional routes under the following path are exposed:

/api/user/:userId/tasks/:taskId

Using the API behind this route not only updates the Task, but Also updates the links to the parent User object. This make it easy to modify subset items on an individual basis.

Readme

Keywords

Package Sidebar

Install

npm i remajo

Weekly Downloads

2

Version

0.0.1

License

ISC

Last publish

Collaborators

  • chaunax