Skip to content

Commit

Permalink
feat(client): use mini-client
Browse files Browse the repository at this point in the history
Replace built-in client with standalone mini-client and mini-service-utils libraries.
  • Loading branch information
feugy committed Nov 6, 2016
1 parent ae54e3b commit 34f1437
Show file tree
Hide file tree
Showing 13 changed files with 192 additions and 961 deletions.
4 changes: 0 additions & 4 deletions index.js

This file was deleted.

98 changes: 0 additions & 98 deletions lib/client.js

This file was deleted.

4 changes: 4 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
startServer: require('./server'),
getClient: require('mini-client')
}
72 changes: 72 additions & 0 deletions lib/register.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
const joi = require('joi')
const boom = require('boom')
const {getParamNames, arrayToObj, validateParams, isApi, serviceschema}= require('mini-service-utils')

/**
* Register all given services to an Hapi server
* All services will be initialized first (order matters) using the given options, at server start.
*
* @param {Hapi} server - in which services are exposed as Http endpoints
* @param {Array<Object>} services - services definition including name and init() function
* @param {Object} serviceOpts - service individual options
* @param {Bunyan} logger - logger used to report init
* @returns {Promise} promise - resolve when all services have been registered as Hapi plugins.
* @returns {Array<Object>} promise.exposed - list of exposed routes:
* @returns {String} promise.exposed.name - service name
* @returns {String} promise.exposed.id - exposed api id
* @returns {Array<String>} promise.exposed.params - exposed api parameter names
* @returns {String} promise.exposed.path - http endpoint full path
*/
exports.registerAsPlugins = (server, services, serviceOpts, logger) => {
const exposed = []
const valid = serviceschema.validate(services)
if (valid.error) return Promise.reject(valid.error)
return server.register(
// all services will be considered as Hapi plugins
services.map(({name, init}) => {
const plugin = {
register: (serv, pluginOpts, next) => {
const initialized = init(Object.assign({logger}, serviceOpts[name]))
if (Promise.resolve(initialized) !== initialized) {
return next(new Error(`service ${name} init() method didn't returned a promise`))
}
return initialized.then(apis => {
if (!isApi(apis)) return
for (const id in apis) {
const api = apis[id]
const params = getParamNames(api)
const path = `/api/${name}/${id}`
const config = {validate: {}}
// adds input validation if needed
if (api.length && api.validate) {
const schema = joi.object(arrayToObj(api.validate, params)).unknown(false)
// use custom validation instead of Joi schema for a better reporting in case of extra parameters
config.validate.payload = (values, validationOpts, done) =>
done(validateParams(values, schema, id, params.length))
}
// keep the list of exposed functions
exposed.push({name, id, params, path})
// publish each API as a POST endpoint
serv.route({
method: api.length ? 'POST' : 'GET',
path,
config,
handler: (req, reply) => {
const payload = req.payload || {}
api(...params.map(prop => payload[prop]))
.then(reply)
.catch(err => reply(boom.create(599, err.message)))
}
})
logger.debug(`API ${path} exposed`)
}
})
.then(next)
.catch(next)
}
}
plugin.register.attributes = {name}
return plugin
})
).then(() => exposed)
}
19 changes: 13 additions & 6 deletions lib/server.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const {Server} = require('hapi')
const {getLogger} = require('./utils')
const {registerAsPlugins} = require('./utils/register')
const {getLogger} = require('mini-service-utils')
const {registerAsPlugins} = require('./register')
const package = require('../package.json')

/**
* Configure and start service in a standalone Hapi Http server
Expand All @@ -25,24 +26,30 @@ module.exports = (opts = {}) => {

const options = Object.assign({
port: 3000,
name: package.name,
version: package.version,
logger: getLogger(),
serviceOpts: {},
services: require('./services')
services: []
}, opts)

const {port, logger, serviceOpts, services} = options
const {port, name, version, logger, serviceOpts, services} = options
logger.debug({port}, 'Configure server')

const server = new Server()
server.connection({port})

return registerAsPlugins(server, services, serviceOpts, logger)
.then(exposed => {
.then(apis => {
// list of exposed APIs, for clients
server.route({
method: 'GET',
path: '/api/exposed',
handler: (req, reply) => reply(exposed)
handler: (req, reply) => reply({
name,
version,
apis
})
})
})
.then(() => server.start())
Expand Down
10 changes: 0 additions & 10 deletions lib/services/index.js

This file was deleted.

101 changes: 0 additions & 101 deletions lib/utils/index.js

This file was deleted.

Loading

0 comments on commit 34f1437

Please sign in to comment.