node-xmpp-joap

Jabber Object Access Protocol (XEP-0075) library for node-xmpp

node-xmpp-joap

Jabber Object Access Protocol XEP-0075 library for node-xmpp.

With package manager npm:

npm install node-xmpp-joap
joap = require "node-xmpp-joap"
xmpp = require "node-xmpp"
 
app = new joap.Application new xmpp.Component
  jid       : "mycomponent"
  password  : "secret"
  host      : "127.0.0.1"
  port      : "8888"
 
app.use (req, res, next) ->
  console.log "received a #{req.type} request"
  next()
app.read (req, res, next) ->
  console.log "received a read request"
  res.end { foo: "bar" }

is equivalent to

app.use (req, res, next) ->
  if req.type is 'read'
    console.log "received a read request"
    res.end { foo: "bar" }
  else
    next()
xmpp = require "node-xmpp"
joap = require "node-xmpp-joap"
 
comp = new xmpp.Component
  jid       : "mycomponent"
  password  : "secret"
  host      : "127.0.0.1"
  port      : "8888"
 
class User
  constructor: (@id, options={}) ->
 
# create a new manager instance 
mgr = new joap.Manager comp
 
# add a class 
mgr.addClass "User"User,
  required: ["name""age"]
  protected: ["id"]
  constructorAttributes: ["id""options"]
 
# implement the ACL by overriding the method 
mgr.hasPermission = (action, next) ->
  if myACLRules(action) then next nullaction
  else next (new joap.Error "You are not allowed to do that :-P")403
xmpp = require "node-xmpp"
joap = require "node-xmpp-joap"
 
comp = new xmpp.Component
  jid       : "mycomponent"
  password  : "secret"
  host      : "127.0.0.1"
  port      : "8888"
 
# create a new client instance 
= new joap.Client comp
 
# requesting the server description 
c.describe "joap.server.tld"(err, iq, parsedDescription) ->
 
# requesting a class description 
c.describe "user@server.tld"(err, iq, parsedDescription) ->
 
# creating a new instance 
c.add "use@server.tld"{ name:"My Name" }(err, iq, instanceAddress) ->
 
# reading an instance 
c.read "user@server.tld/instanceId"(err, iq, parsedResult) ->
 
# reading only a few properties of an instance 
c.read "user@server.tld/instanceId"["email""age"](err, iq, parsedResult) ->
 
# modifying properties of an instance 
c.edit "user@server.tld/instanceId"{ age: 27 }(err, iq) ->
 
# deleting an instance 
c.delete "user@server.tld/instanceId"(err, iq) ->
 
# searching for instances 
c.search "user@server.tld"{age: 60} erriqarrayOfInstanceIDs) ->
 
# performing a method call 
c.methodCall "myMethod""user@server.tld/instanceId"["param1","param2"](err, iq, result) ->

If you want to persist the objects in a database you can simply override the methods saveInstance, loadInstance and deleteInstance. In this example we use nStore.

nStore  = require "nstore"
 
# create database 
users = nStore.new './data/users.db'(err) ->
 
  if err?
    console.error err
  else
 
    # override 
    mgr.saveInstance = (action, obj, next) ->
      if action.class is "User"
        users.save obj.idobj(err) -> next erraction
      else
        next (new Error "Storage for this class is not available")a
 
    # override 
    mgr.loadInstance = (action, next) ->
      if action.class is "User"
        users.get id(err, inst) -> next erractioninst
      else
        next (new Error "Storage for this class is not available")a
 
    # override 
    mgr.queryInstances = (a, next) ->
      if a.class is "User"
        if a.attributess?
          @users.find a.attributes(err, res) -> next erra(id for id of res)
        else
          @users.all (err, res) -> next erra(id for id of res)
      else
        next (new Error "Storage for this class is not available")a
 
    # override 
    mgr.deleteInstance = (a, next) ->
      if a.class is "User"
        users.remove id(err) -> next erra
      else
        next (new Error "Storage for this class is not available")a
xmpp = require "node-xmpp"
joap = require "node-xmpp-joap"
 
comp = new xmpp.Component
  jid       : "mycomponent"
  password  : "secret"
  host      : "127.0.0.1"
  port      : "8888"
 
classes = {}
objects = {}
 
router = new joap.Router comp
 
router.on "action"(a) ->
  if a.class? and a.instance? and a.type is "read"
    router.sendResponse aobjects[a.class][a.instance]
 
router.on "read"(action) ->
  console.log "read iq received"
 
router.on "edit"(action) ->
  console.log "edit iq received"
 
router.on "add"(action) ->
  console.log "add iq received"
 
  if not classes[action.class]?
    router.sendError (new joap.Error "'#{action.class}' does't exists."404)action
 
  # ... 
 
router.on "search"(action) ->
 
router.on "rpc"(action) ->
  console.log "calling #{action.method} with:"
  for param in actions.params
    console.log param
npm install
npm test
  • describe support

node-xmpp-joap is licensed under the MIT-Licence (see LICENSE.txt)