Skip to content

feugy/mini-service

Repository files navigation

Mini-service

Simplistic µService library

npm package NSP Status dependencies build coverage License: MIT

Introduction

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+

Example

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}`)

Acknowledgements

This project was kindly sponsored by nearForm.

License

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.

3.x to 4.x migration

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

2.x to 3.x migration

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 apis ping & pong
  • group b with api ping

the final Mini-client will be:

client = {
  ping(),
  a: {
    ping(),
    pong()
  },
  b: {
    ping()
  }
}

1.x to 2.x migration

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: {}
  }
})

About

Micro services done simply. Choose to run them locally or remotely

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •