Skip to content

lightweight json-rpc node middleware with promises - because not EVERY api has to be RESTful

Notifications You must be signed in to change notification settings

victor-stone/json-rpc-promise

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

json-rpc-promise server middleware

Because not every remote API has to be RESTful.

N.B. this is not a full implementation of the 2.0 spec. As of this writing it is missing notifications and batching.

The methods in your API need to all return promises.

Example - Server

...
class Calc {
  sum(x,y) {
    return Promise.resolve(x + y);
  }
  multiply(x,y) {
    return Promise.resolve(x * y);
  }
}

const modules = { calc: new Calc() };

app.use( '/api', rpc( { modules } );

Example Client

  rpc.calc.sum( 3, 4 ).then( answer => console.log('Answer: ', answer) );

Example full - Server

const express    = require('express');
const bodyParser = require('body-parser');
const cors       = require('cors');

var app = exppress();

app.use( cors({ preflightContinue:true }) );
app.use( '/api', bodyParser.json() );

class Calc {
  sum(x,y) {
    return Promise.resolve(x + y);
  }
  multiply(x,y) {
    return Promise.resolve(x * y);
  }
}

class Users {
  constructor(mongodbClient) {
    this.db = mongodbClient; // for examples
  }
  find(id) {
    return this.db.collections('users').find( { id } ).toArray();
  }
}

const api = {
  calc: new Calc(),
  users: new Users(someMongoClientThingy)
};

app.use( '/api', rpc({ modules:api }) ); // <<== REGISTER API HERE

const DEFAULT_PORT = 3000;

const port = process.env.PORT || DEFAULT_PORT;

app.listen( port, () => console.log('Server listening on port ' + port) );

Example - full Client

import axios from 'axios';

// OR in the browser CDN: 
// <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

const reducer = api => function(obj,m) { 
  obj[m] = (...args) => this._rpc(api + '.' + m, args);
  return obj;
};

class RPC {
  constructor(opts) {
    this._opts = { ...opts };
    this.currId = 1;
    axios.defaults.baseURL = opts.host;
    axios.defaults.headers.post['Content-Type'] = 'application/json';
  }

  _rpc = (method, params = null) =>
    axios.post('/', {
      jsonrpc: '2.0',
      id: ++this.currId,
      method,
      params: typeof params === 'string' ? [params] : params
    }).then(({ data: { /* id, */ result} }) => result);

  getMethods = () =>
    this._rpc('rpc.listMethods').then(apis => {
      for (var api in apis) {
        this[api] = apis[api].reduce( reducer(api).bind(this), {} );
      }
      return apis;
    });
}

const rpc = new RPC({ host: 'http://localhost:3000/api' });

rpc.getMethods().then( () => {

  rpc.calc.sum( 3, 4 ).then( answer => console.log('Answer: ', answer) );

  rpc.users.find( 'gloria' ).then( record => console.log( 'Gloria: ', gloria ));
})

About

lightweight json-rpc node middleware with promises - because not EVERY api has to be RESTful

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published