samjs

0.4.0 • Public • Published

SAM.js

Created to connect Socket.io, AngularJS and MongoDB.

Now it is database and view framework agnostic, leaving a socket.io framework.

Browser client: samjs-client

Features

  • only websockets
  • plugable
  • useful defaults
  • multiple databases simultaniously

data modeling

  • options
    source-code-based / kept-in-memory data. Used to set low-level options of the app, can only be changed by restarting. Not accessible due websockets.

  • configs
    file-based / kept-in-memory data For structural data specific for your app, should be only changed sparsely by few persons.

  • models
    Can be custom in-memory models or plugable database-based models. Should be used for all data which changes on regular basis.

Getting Started

npm install --save samjs
npm install --save-dev samjs-client

Simple example with koa server

samjs = require "samjs"
koa = require("koa")()
 
server = require("http").createServer(koa.callback())
 
samjs
.plugins()
.options()
.configs({name:"item"})
.models()
.startup(server)
 
server.listen(3000)
#to close
#samjs.shutdown()
 
// in browser with e.g. webpack
samjs = require("samjs-client")()
samjs.config.set("item", "value")
.then(function(){
  //success
})
.catch(function(){
  //failure
})
// some other client  
samjs.config.on("item",function(){
  //item changed
  samjs.config.get("item")
  .then(function(response){
    response == "value" // true
  })
  .catch(function(){
    //failure
  })
}

Available plugins

Name Description
samjs-auth adds a configs-based user management, authentification mechanismen and authorization system for configs.
samjs-files adds a model and interface for file/folder interaction
samjs-files-auth adds authorization for samjs-files
samjs-mongo adds a model and interface for mongodb interaction
samjs-mongo-auth adds authorization for samjs-mongo
samjs-auth-mongo moves user management to mongodb. Adds groups.
samjs-mongo-isOwner Plugin for managing user owned documents in samjs-mongo.

docs

Samjs is configured by several functions which must be called in order. Startup order:

samjs.plugins().options().configs().models().startup().io.listen(8080)

Function: plugins

takes one or more plugin objects or an array of plugin objects. Returns samjs.

samjs.plugins(require("samjs-files"),require("samjs-auth"))
// or
samjs.plugins([require("samjs-files"),require("samjs-auth")])

See plugin api for detailed information to write your own plugin

Function: options

takes a options object to overwrite the default values. Returns samjs.

// only default in core is samjs.options.config == "config.json"
// to overwrite:
samjs.options({config:"settings.json"})

Function: configs

takes one or more config objects or an array of config objects. Returns samjs.

samjs.configs({name:"paths"},{name:"users"})
// or
samjs.configs([{name:"paths"},{name:"users"}])

Props of a config object:

Name type default description
name String - (required) name of the config object. To access the config object after setup :samjs.configs[name]
access Object {read:false,write:false} allowes to access this config value by client
test Function - Function to test values for validity. Must return a promise which resolves on success and rejects on error.
isRequired Boolean false includes this config object in configuration phase. (see lifecycle)
hooks Object - functions to get called on specific interactions with this config object.

actions:

After setup, each config object has 3 available actions: set,get,test. Each has a server-side version: _set,_get,_test, which are not checking for authentification.

hooks:

hooks are functions which are called on specific actions. They always have to return their arguments.

Name arguments description
beforeCreate options manipulate the options object before creation
afterCreate options manipulate the options object after creation
beforeSet {data, socket} used to authenticate a set request
before_Set {data, oldData} used to manipulate a set request
afterSet {data, oldData, socket} called after a successfull set request from client
after_Set {data, oldData} called after each successfull set request
beforeGet {socket} used to authenticate a get request
after_Get data called after a successfull _get request
afterGet {data, socket} called after a successfull get request from client
beforeTest {data, socket} used to authenticate a test request
afterTest {data, socket} called after a successfull test request from client

example (how samjs-auth basically works):

samjs.configs({name:"paths", hooks: {
  beforeSet: function(obj) {
    if (obj.client.auth != null
      && obj.client.auth.user != null
      && obj.client.auth.user.username == "root") {
        return obj
    }
    throw new Error "no permission"
  }}
})

Function: models

takes one or more model objects or an array of model objects. Returns samjs.

samjs.models(model1,model2)
// or
samjs.models([model1,model2])

Props of a model object:

Name type default description
name String - (required) name of the model object. To access the model object after setup :samjs.models[name]
interfaces Object or array - see below.
isRequired Boolean false includes this model object in installation phase. (see lifecycle)
installInterface Function - a socket.io interface which is used in installation phase if isRequired is true (see installInterface)
test Function - a function to test if installation requirement is met, if isRequired is true
db String - use a model-structure and interface from a plugin

interfaces

Interfaces can be either a array or a key-value store

// all interfaces in an array will listen one the "someModel" socket.io namespace
samjs.models({
  name: "someModel"
  value: "someValue"
  interfaces: [
    // will be in the "someModel" socket.io namespace
    function(socket){
      var model = this
      // model.name == "someModel" // true
      socket.on("get",function(request){
        if (request.token != null){
          socket.emit("get."+.request.token,{success:true, content:model.value})
        }
      })
    }
  ]
  })
// if you need to use another namespace use an object instead
samjs.models({
  name: "someModel"
  interfaces: {
    // either provide a single interface or a array of interfaces
    // will be in the "someOtherNamespace" socket.io namespace
    someOtherNamespace: function(socket){ //doSomething }
  }
  })

installInterface

samjs.models({
  name: "someModel"
  installInterface: function(socket){
    var model = this # will be bound to model instance
    # will be in the 'install' socket-io namespace, specific listeners are required
    socket.on "someModel.set", function(request) =>
      if (request.token != null && request.content != null){
        # no authentification, will be only accessible in install mode
        model.test(request.content)
        .then(function(value){model.value = value})
        .then(function(value){return {success:true, content: value}}
        .catch(function(e){return {success:false, content: e.message}}
        .then(function(response){
          socket.emit("boilerplate.set."+request.token, response)
          if(response.success){
            samjs.state.checkInstalled() # will trigger a check if installation is finished
            }
          }
        }
    # must return a dispose function
    return function(){socket.removeAllListeners("someModel.set")}
  }
})

Function: startup

takes a optional httpServer, returns samjs.

samjs.startup(someServer)
someServer.listen(8080)
// or
samjs.startup()
samjs.io.listen(8080)

Function: shutdown

returns samjs. Shuts samjs and socket.io down.

Function reset

returns samjs. Resets samjs instance. Useful for unit testing.

Lifecycle

samjs emits several events during its lifecycle:

example:

samjs.once("options",function(){console.log("options got called")})

Synchronous (configuration / after startup)

Name Description
beforePlugins emitted before samjs.plugins() is executed
plugins emitted after samjs.plugins() is executed
beforeOptions emitted before samjs.options() is executed
options emitted after samjs.options() is executed
beforeConfigs emitted before samjs.configs() is executed
configs emitted after samjs.configs() is executed
beforeModels emitted before samjs.models() is executed
models emitted after samjs.models() is executed
beforeStartup emitted before samjs.startup() is executed
startup emitted after samjs.startup() is executed
beforeShutdown emitted before samjs.shutdown() is executed
shutdown emitted after samjs.shutdown() is executed
beforeReset emitted before samjs.reset() is executed
reset emitted after samjs.reset() is executed

Asynchronous (startup)

samjs.startup works like this:

Is samjs configured? (all configs with `isRequired` are set properly)
- start configuration if not
Execute all `startup` functions of all plugins
Execute all `startup` functions of all models
Is samjs installed? (all models with `isRequired` are set properly)
- start installation if not
expose all socket.io interfaces

Events:

Name Description
beforeConfigure emitted before configuration is set up and ready
configure emitted after configuration is set up and ready
configured emitted after configuration is done or when no configuration was necessary
beforeInstall emitted before installation is set up and ready
install emitted after installation is set up and ready
installed emitted after installation is done or when no installation was necessary
started emitted when samjs is properly started up

There are additional state promises which will fullfill once a state is reached:

Name Description
onceConfigure fullfilled once in configuration mode
onceConfigured fullfilled once configuration is finished
onceInstall fullfilled once in installation mode
onceInstalled fullfilled once installation is finished
onceStarted fullfilled once samjs is properly started up
onceConfigureOrInstall fullfilled once in configuration or installation mode

example

samjs.state.onceStarted.then(function(){
  // do something
  })

Plugin api

see source code of samjs-plugin-boilerplate for a complete plugin api

Readme

Keywords

none

Package Sidebar

Install

npm i samjs

Weekly Downloads

2

Version

0.4.0

License

MIT

Last publish

Collaborators

  • paulpflug