Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
How to use ES6 generators with Hapi.js <3
import co from 'co'
// Generator controller,
// this.models refers to Sequelize models added with server.bind()
function* loginController(request) {
let user = yield this.models.User.find({
where: {
email: request.payload.email
}
});
if (!user)
yield Promise.reject(Boom.notFound('USER_NOT_FOUND'));
return user.toJSON();
}
// Wraps generator so it can be used in Hapi responses
function wrapGen(generator) {
let handler = co.wrap(generator);
return function(request, reply) {
handler.bind(this)(request, reply)
.then(reply)
.catch(reply);
};
}
// Here's the most typical Hapi.js route
server.route({
method: 'POST',
path: '/auth/login',
handler: wrapGen(loginController)
});

If you wanted to turn wrapGen into a module, I suggest generoute or generoutify. Prefixed with hapi- perhaps.

This is cool btw, thanks for putting it out there.

lib/util/generoute.js

import co from 'co';

// Wraps generator so it can be used in Hapi responses
function generoute(generator) {
  let handler = co.wrap(generator);
  return function(request, reply) {
    handler.bind(this)(request)
      .then(reply)
      .catch(reply);
  };
}

export default generoute;

server.js

require('babel/register');

import {Server} from 'hapi';
import {version} from '../package.json';
import generoute from './lib/util/generoute';

let server = new Server();

let versionHandler = function* () {
  // really no point to using a promise here, I just wanted to prove it works.
  return yield Promise.resolve({version: this.version});
};

server.connection({ port: 9000 });
server.bind({version: version});
server.route({
  method: 'GET',
  path: '/version',
  handler: generoute(versionHandler)
});

server.start(function () {
  console.log('Server running at:', server.info.uri);
});

@nackjicholson This is very nice, is it working as expected?

ebertmi commented Mar 20, 2016

With newer co versions the wrapping is even easier.

Just use

import co from 'co';

// Wraps generator so it can be used in Hapi Route Handlers
function generoute(generator) {
  return co.wrap(generator);
}

export default generoute;

This allows to use a generator handler with request and reply.

function* myHandler (request, reply) {
  try {
    let user =  yield DB.getUser(request.params.id);
    ...
    reply(user);
  } catch (e) {
    reply({
       customErrorMessage: 'All your base are belong to us!'
    }).code(400);
  }
}

This allows to set the HTTP response codes, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment