samjs
v0.4.0
Published
Created to connect **S**ocket.io, **A**ngularJS and **M**ongoDB.
Downloads
19
Readme
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