xjrpc

XJRPC is JSON based RPC with observers and remote promises

Usage no npm install needed!

<script type="module">
  import xjrpc from 'https://cdn.skypack.dev/xjrpc';
</script>

README

Extended Json RPC - JavaScript implementation with promises

Calling remote objects

  var remoteCounterServer=session.createRemoteElement('server','counterServer','CounterServer')
  var counter1=remoteCounterServer.getOrCreateCounter('counter1')
  counter1.increment()
  counter1.incrementAndReturn().then(function(res) {
    if(res!=2) throw new Error('wrong counter value')
  },function() {
    throw new Error('Rpc error')
  })

  var counter2=remoteCounterServer.getCounter('counter2')
  counter2.increment()
  counter2.incrementAndReturn().then(function(res) {
    throw new Error('result in place when we expect error')
  },function() {
    counter2.__promise.then(function() {
      throw new Error('result in place when we expect error')
    },function() {
      cb(true)
    })
  })

Object definitions

We need to define what object methods return in order to use them remotely in easy way.

  var serverDefinitions={}

  var Counter=function() {
    this.value=0
  }
  Counter.prototype.$increment={ noReturn:true }
  Counter.prototype.increment=function() {
    this.value++
    console.log("INCREMENT",this.value)
  }
  Counter.prototype.incrementAndReturn = function() {
    this.value++
    console.log("INCREMENT",this.value)
    return this.value
  }

  serverDefinitions['Counter']=interfaces.createDefinition(Counter.prototype)

  var CounterServer=function() {
    this.counters={}
  }
  CounterServer.prototype.$getCounter={ returnRemote:'Counter', realms:['client'] }
  CounterServer.prototype.getCounter=function(name) {
    console.log("GET COUNTER",name)
    if(this.counters[name]) {
      return this.counters[name]
    } else throw new Error('counter not found!')
  }
  CounterServer.prototype.$getOrCreateCounter={ returnRemote:'Counter', realms:['client'] }
  CounterServer.prototype.getOrCreateCounter=function(name) {
    this.counters[name]=this.counters[name] || new Counter()
    return this.getCounter(name)
  }

  serverDefinitions['CounterServer']=interfaces.createDefinition(CounterServer.prototype,'client')

How to use with sockJS

Write in Server:

  /// Include modules:
  var http = require('http')
  var sockjs = require('sockjs')
  var xjrpc = require('xjrpc')

  /// initialize sockjs and xjrpc servers
  var rpcSock = sockjs.createServer()
  var rpcServer = xjrpc.createServer(rpcSock)

  /// Gather class definitions:
  var clientDefinitions ={
    'MyServiceClass':xjrpc.createDefinition(MyServiceClass.prototype,'client')
  }

  /// Create session initializer
  rpcServer.addSessionInitializer('initializerName',function(rpc,welcomeMessage) {
    var myServiceObject=new MyServiceClass(...)
    rpc.share('MyServiceName',myServiceObject)
  })

  /// Share service definitions with client somehow:
  var definitionsJSON=JSON.stringify(clientDefinitions,null,'  ')
  xms.node.fs.writeFile('../client/rpcDefinitions.json',definitionsJSON)
  xms.node.fs.writeFile('../client/rpcDefinitions.jsonp','loadDefinitions('+definitionsJSON+')')
  xms.node.fs.writeFile('../client/rpcDefinitions.js','window.rpcDefinitions='+definitionsJSON)
  
  var server = http.createServer()
  rpcSock.installHandlers(server, {prefix:'/xjrpc'})
  server.listen(9999, '0.0.0.0')

Write in Client:

 <script src="xjrpc.js"></script>
 <script src="rpcDefinitions.js"></script>
 <script>
   var rpcSocket=new XJRPC.sockJsClient.RpcSockJsClient(
     document.location.protocol+'//'+document.location.host+'/xjrpc', true
   )
   var rpcClient=rpcSocket.getRpcClient()
   var rpcSession=rpcClient.createSession(window.rpcDefinitions)
   rpcSession.connect('server',{ /* Welcome messsage for server */ })
   var myRemoteService = rpcSession.createRemoteElement('server','MyServiceName','MyServiceClass')

   /* call your service */
 </script>