Code Monkey home page Code Monkey logo

node-martini's Introduction

Martini

Client and Server RPC

Martini can generate both the client, and server from a single protocol.

Usage

Define a protocol

Create a user type, and define a single route that returns a JSON-encoded user.

var protocol = {
  types: {
    user: {type: 'struct', props: {
      name  : 'string',
      phone : 'string,'
      age   : 'number',
    }, require: ['name']}
  },
  routes: {
    getUser: {
      proto: {
        method : 'GET',
        route  : '/user/:uid'
      },
      output: 'user'
    }
  }
}

Create the server

Create a server class, and implement all methods in the protocol. Each route must return a Promise object.

function Server() {}

Server.prototype.getUser = function (_, params) {
  return new Promise(function (done) {
    done({user: 'bob', phone: '123-432-2131', age :30})
  })
}

Create a router out of the server object.

var http   = require('http')
var RPC    = require('martini')

var rpc    = RPC.New(protocol)
var router = rpc.getRouter(new Server())

var server = http.createServer(router)

server.listen(process.env.PORT)

Create the client

var RPC    = require('martini')
var rpc    = RPC.New(protocol)
var client = rpc.getClient(process.env.PORT, process.env.HOST)

client.getUser(null, {uid: 1234})
  .then(console.log)
  .catch(console.error)

Advanced

Streaming JSON

Newline delimited JSON is a powerful, yet simple protocol. Define a typed stream using emitter/TYPE where TYPE is a marshalable format, e.g.

var protocol = {
  types: {
    user: {type: 'struct', props: { name: 'string' }
  },
  routes: {
    getUsers: {
      proto: {
        method : 'GET',
        route  : '/users'
      },
      output: 'emitter/user'
    }
  }
}

Create a server route that returns an event emitter

Server.prototype.getUsers = function () {
  var ee = new EventEmitter()
  setImmediate(function(){ // this must be on another tick
    ee.emit('data', {name: 'bob'})
    ee.emit('data', {name: 'kim'})
    ee.emit('end')
  })
  return ee
}

Create a client that consumes the event emitter

client.getUsers(null, {})
.then(function (users) {
  users.on('data', function(user){
    console.log('Got User:', user.name)
  })
  users.on('end', function(){
    console.log('DONE')
  })
})

This will print the following

Got User: bob
Got User: kim
DONE

See Also

node-martini's People

Contributors

groundwater avatar

Stargazers

Jesús Leganés-Combarro avatar

Watchers

Wraithan avatar James Cloos avatar

node-martini's Issues

Streaming Protocol Support

I want to support streaming protocols, such as newline delimited JSON.

You should be able to return Stream objects, and EventEmitters. The protocol will still be type-checked. In the case of a stream, it will be newline buffered and each line validated. In the case of an event emitter, each data event must be a whole object.

Server.prototype.getStream = function(){
  var ee = new EventEmitter()

  setImmediate(function(){
    ee.emit('data', {/* valid data type */})
    ee.emit('data', {/* valid data type */})
    ee.emit('end') // ends stream
  })

  return ee
}

or

Server.prototype.getStream = function(){
  return fs.createReadStream('./newline-json.ndj', 'utf-8')
}

The data type for the stream should be stream/TYPE where TYPE is a type defined in the schema.

Version 2 Changes

  1. Allow combination of protocols. Given proto1 and proto2 I want to serve them both up from different prefixes e.g., /records -> recordProtocol and /views -> viewProtocol
  2. In protocol, the output should be optional. Perhaps rename it to validate or something. Martini is supposed to aid in rapid development, and a validation is an optimization. It should be opt-in at a later stage.
  3. Flatten the protocol JSON somehow.
  4. Include whole types instead of references in input/output validation. I had some reason for this...
  5. Chaining protocols, where one protocol hands-off to another on the server. An authentication class could first get the user, and then another class handles the request with the user in scope. I'll have to figure out how to structure this.
  6. Generators for streaming? (this would work better with async/await)
  7. Fix exports. I want to write import {createClient} from 'martini' for example.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.