Simplistic µService library
The goal of mini-service is to give the minimal structure to implement a µService, that can be invoked locally or remotely.
Its principles are the following:
- very easy to add new service api endpoints
- easy to use client interface, same usage both locally and remotely
- hide deployment details and provide simple-yet-working solution
- promises based (and thus, async/await compatible)
mini-service uses the latest ES6 features, so it requires node 6+
Here is a simple calculator service definition, that exposes functions to add and subtract numbers.
calc-service.js
module.exports = {
name: 'calc-service',
version: '1.0.0',
init: () => {
// each exposed APIs could also return a promise/be async
add: (a, b) => a + b,
subtract: (a, b) => a - b
}
}
If you want to use it locally in a different file: require the service definition, and create a [mini-client][mini-client-url] with it
caller-local.js
const {getClient} = require('mini-service')
const calcService = require('./calc-service')
const calc = getClient(calcService)
Then, init it (it's an async operation) and invoke any exposed API you need:
caller-local.js
await calc.init()
const sum = await calc.add(10, 5)
console.log(`Result is: ${sum}`)
Now let's imagine you need to deploy your calculator service in a standalone Http server, and invoke it from a remote server.
To turn your local service into a real server, expose your service definition with mini-service's startServer()
:
calc-service.js
const {startServer} = require('mini-service')
module.exports = {...} // same service definition as above
// starts Http server
startServer(module.exports)
A server is now listening on port 3000.
And to use it from a remote caller, creates a mini-client giving the proper url:
caller-remote.js
const getClient = require('mini-client') // or: const {getClient} = require('mini-service')
const calc = getClient({
remote: 'http://localhost:3000'
})
Please note that you don't need to require the service definition anymore.
Usage is exactly the same as previously.
caller-remote.js
await calc.init() // no-op, can be skipped
const sum = await calc.add(10, 5)
console.log(`Result is: ${sum}`)
This project was kindly sponsored by nearForm.
Copyright Damien Simonin Feugas and other contributors, licensed under MIT.
## Changelog & migration guide
All changes to this project are be documented here.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
Version 4 is using async/await, which requires node@8+.
The only breaking change is on startServer()
:
- previously it threw synrchonous errors while validating configuration.
- now all errors are thrown asynchronously
Groups are now used as sub-objects of mini-client.
Given a service exposing:
- api
ping
without group (or if group has same name as overall service) - group
a
with apisping
&pong
- group
b
with apiping
the final Mini-client will be:
client = {
ping(),
a: {
ping(),
pong()
},
b: {
ping()
}
}
Local services, as remote services, must have name
and version
options defined
When loading services, the services
property was renamed to groups
, and serviceOpts
is now groupOpts
:
const {startServer} = require('mini-service')
startServer({
groups: [ // was services previously
require('../serviceA'),
require('../serviceB'),
require('../serviceC')
],
groupOpts: { // was serviceOpts previously
serviceA: {},
serviceB: {},
serviceC: {}
}
})