|  |  | # avvio
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | [](https://www.npmjs.com/package/avvio)
 | 
						
						
						
							|  |  | [](https://snyk.io/test/github/fastify/avvio)
 | 
						
						
						
							|  |  | [](https://standardjs.com/)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Asynchronous bootstrapping is hard, different things can go wrong, *error handling* and *load order* just to name a few. The aim of this module is to make it simple.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | `avvio` is fully *reentrant* and *graph-based*. You can load
 | 
						
						
						
							|  |  | components/plugins *within* plugins, and be still sure that things will
 | 
						
						
						
							|  |  | happen in the right order. At the end of the loading, your application will start.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | * [Install](#install)
 | 
						
						
						
							|  |  | * [Example](#example)
 | 
						
						
						
							|  |  | * [API](#api)
 | 
						
						
						
							|  |  | * [Acknowledgements](#acknowledgements)
 | 
						
						
						
							|  |  | * [License](#license)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | <a name="install"></a>
 | 
						
						
						
							|  |  | ## Install
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | To install `avvio`, simply use npm:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | npm install avvio --save
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | <a name="example"></a>
 | 
						
						
						
							|  |  | ## Example
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The example below can be found [here][example] and run using `node example.js`.
 | 
						
						
						
							|  |  | It demonstrates how to use `avvio` to load functions / plugins in order.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | 'use strict'
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | const app = require('avvio')()
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | app
 | 
						
						
						
							|  |  |   .use(first, { hello: 'world' })
 | 
						
						
						
							|  |  |   .after((err, cb) => {
 | 
						
						
						
							|  |  |     console.log('after first and second')
 | 
						
						
						
							|  |  |     cb()
 | 
						
						
						
							|  |  |   })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | app.use(third)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | app.ready(function (err) {
 | 
						
						
						
							|  |  |   // the error must be handled somehow
 | 
						
						
						
							|  |  |   if (err) {
 | 
						
						
						
							|  |  |     throw err
 | 
						
						
						
							|  |  |   }
 | 
						
						
						
							|  |  |   console.log('application booted!')
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | function first (instance, opts, cb) {
 | 
						
						
						
							|  |  |   console.log('first loaded', opts)
 | 
						
						
						
							|  |  |   instance.use(second)
 | 
						
						
						
							|  |  |   cb()
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | function second (instance, opts, cb) {
 | 
						
						
						
							|  |  |   console.log('second loaded')
 | 
						
						
						
							|  |  |   process.nextTick(cb)
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // async/await or Promise support
 | 
						
						
						
							|  |  | async function third (instance, opts) {
 | 
						
						
						
							|  |  |   console.log('third loaded')
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | <a name="api"></a>
 | 
						
						
						
							|  |  | ## API
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   * <a href="#constructor"><code><b>avvio()</b></code></a>
 | 
						
						
						
							|  |  |   * <a href="#use"><code>instance.<b>use()</b></code></a>
 | 
						
						
						
							|  |  |   * <a href="#after"><code>instance.<b>after()</b></code></a>
 | 
						
						
						
							|  |  |   * <a href="#await-after"><code>await instance.<b>after()</b></code></a>
 | 
						
						
						
							|  |  |   * <a href="#ready"><code>instance.<b>ready()</b></code></a>
 | 
						
						
						
							|  |  |   * <a href="#start"><code>instance.<b>start()</b></code></a>
 | 
						
						
						
							|  |  |   * <a href="#override"><code>instance.<b>override()</b></code></a>
 | 
						
						
						
							|  |  |   * <a href="#onClose"><code>instance.<b>onClose()</b></code></a>
 | 
						
						
						
							|  |  |   * <a href="#close"><code>instance.<b>close()</b></code></a>
 | 
						
						
						
							|  |  |   * <a href="#express"><code>avvio.<b>express()</b></code></a>
 | 
						
						
						
							|  |  |   * <a href="#toJSON"><code>avvio.<b>toJSON()</b></code></a>
 | 
						
						
						
							|  |  |   * <a href="#prettyPrint"><code>avvio.<b>prettyPrint()</b></code></a>
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | <a name="constructor"></a>
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### avvio([instance], [options], [started])
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Starts the avvio sequence.
 | 
						
						
						
							|  |  | As the name suggests, `instance` is the object representing your application.
 | 
						
						
						
							|  |  | Avvio will add the functions `use`, `after` and `ready` to the instance.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const server = {}
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | require('avvio')(server)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | server.use(function first (s, opts, cb) {
 | 
						
						
						
							|  |  |   // s is the same of server
 | 
						
						
						
							|  |  |   s.use(function second (s, opts, cb) {
 | 
						
						
						
							|  |  |     cb()
 | 
						
						
						
							|  |  |   })
 | 
						
						
						
							|  |  |   cb()
 | 
						
						
						
							|  |  | }).after(function (err, cb) {
 | 
						
						
						
							|  |  |   // after first and second are finished
 | 
						
						
						
							|  |  |   cb()
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Options:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | * `expose`: a key/value property to change how `use`, `after` and `ready` are exposed.
 | 
						
						
						
							|  |  | * `autostart`: do not start loading plugins automatically, but wait for
 | 
						
						
						
							|  |  |   a call to [`.start()`](#start)  or [`.ready()`](#ready).
 | 
						
						
						
							|  |  | * `timeout`: the number of millis to wait for a plugin to load after which
 | 
						
						
						
							|  |  |   it will error with code `ERR_AVVIO_PLUGIN_TIMEOUT`. Default
 | 
						
						
						
							|  |  |   `0` (disabled).
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Events:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | * `'start'`  when the application starts
 | 
						
						
						
							|  |  | * `'preReady'` fired before the ready queue is run
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The `avvio` function can also be used as a
 | 
						
						
						
							|  |  | constructor to inherit from.
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | function Server () {}
 | 
						
						
						
							|  |  | const app = require('avvio')(new Server())
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | app.use(function (s, opts, done) {
 | 
						
						
						
							|  |  |   // your code
 | 
						
						
						
							|  |  |   done()
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | app.on('start', () => {
 | 
						
						
						
							|  |  |   // you app can start
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | <a name="use"></a>
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### app.use(func, [optsOrFunc]) => Thenable
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Loads one or more functions asynchronously.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The function **must** have the signature: `instance, options, done`
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | However, if the function returns a `Promise` (i.e. `async`), the above function signature is not required.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Plugin example:
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | function plugin (server, opts, done) {
 | 
						
						
						
							|  |  |   done()
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | app.use(plugin)
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | `done` should be called only once, when your plugin is ready to go.  Additional
 | 
						
						
						
							|  |  | calls to `done` are ignored.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | `use` returns a thenable wrapped instance on which `use` is called, to support a chainable API that can also be awaited.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | This way, async/await is also supported and `use` can be awaited instead of using `after`.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Example using `after`:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | async function main () {
 | 
						
						
						
							|  |  |   console.log('begin')
 | 
						
						
						
							|  |  |   app.use(async function (server, opts) {
 | 
						
						
						
							|  |  |     await sleep(10)
 | 
						
						
						
							|  |  |     console.log('this first')
 | 
						
						
						
							|  |  |   })
 | 
						
						
						
							|  |  |   app.after(async (err) => {
 | 
						
						
						
							|  |  |     if (err) throw err
 | 
						
						
						
							|  |  |     console.log('then this')
 | 
						
						
						
							|  |  |   })
 | 
						
						
						
							|  |  |   await app.ready()
 | 
						
						
						
							|  |  |   console.log('ready')
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | main().catch((err) => console.error(err))
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Example using `await after`:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | async function main () {
 | 
						
						
						
							|  |  |   console.log('begin')
 | 
						
						
						
							|  |  |   app.use(async function (server, opts) {
 | 
						
						
						
							|  |  |     await sleep(10)
 | 
						
						
						
							|  |  |     console.log('this first')
 | 
						
						
						
							|  |  |   })
 | 
						
						
						
							|  |  |   await app.after()
 | 
						
						
						
							|  |  |   console.log('then this')
 | 
						
						
						
							|  |  |   await app.ready()
 | 
						
						
						
							|  |  |   console.log('ready')
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | main().catch((err) => console.error(err))
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Example using `await use`:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | async function main () {
 | 
						
						
						
							|  |  |   console.log('begin')
 | 
						
						
						
							|  |  |   await app.use(async function (server, opts) {
 | 
						
						
						
							|  |  |     await sleep(10)
 | 
						
						
						
							|  |  |     console.log('this first')
 | 
						
						
						
							|  |  |   })
 | 
						
						
						
							|  |  |   console.log('then this')
 | 
						
						
						
							|  |  |   await app.ready()
 | 
						
						
						
							|  |  |   console.log('ready')
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | main().catch((err) => console.error(err))
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | A function that returns the options argument instead of an object is supported as well:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | function first (server, opts, done) {
 | 
						
						
						
							|  |  |   server.foo = 'bar'
 | 
						
						
						
							|  |  |   done()
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | function second (server, opts, done) {
 | 
						
						
						
							|  |  |   console.log(opts.foo === 'bar') // Evaluates to true
 | 
						
						
						
							|  |  |   done()
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | /**
 | 
						
						
						
							|  |  |  * If the options argument is a function, it has access to the parent
 | 
						
						
						
							|  |  |  * instance via the first positional variable
 | 
						
						
						
							|  |  |  */
 | 
						
						
						
							|  |  | const func = parent => {
 | 
						
						
						
							|  |  |   return {
 | 
						
						
						
							|  |  |     foo: parent.foo
 | 
						
						
						
							|  |  |   }
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | app.use(first)
 | 
						
						
						
							|  |  | app.use(second, func)
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | This is useful in cases where an injected variable from a plugin needs to be made available to another.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | It is also possible to use [esm](https://nodejs.org/api/esm.html) with `import('./file.mjs')`:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | import boot from 'avvio'
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | const app = boot()
 | 
						
						
						
							|  |  | app.use(import('./fixtures/esm.mjs'))
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | <a name="error-handling"></a>
 | 
						
						
						
							|  |  | #### Error handling
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | In order to handle errors in the loading plugins, you must use the
 | 
						
						
						
							|  |  | `.ready()` method, like so:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | app.use(function (instance, opts, done) {
 | 
						
						
						
							|  |  |   done(new Error('error'))
 | 
						
						
						
							|  |  | }, opts)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | app.ready(function (err) {
 | 
						
						
						
							|  |  |   if (err) throw err
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | When an error happens, the loading of plugins will stop until there is
 | 
						
						
						
							|  |  | an [`after`](#after) callback specified. Otherwise, it will be handled
 | 
						
						
						
							|  |  | in [`ready`](#ready).
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | <a name="after"></a>
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### app.after(func(error, [context], [done]))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Calls a function after all the previously defined plugins are loaded, including
 | 
						
						
						
							|  |  | all their dependencies. The `'start'` event is not emitted yet.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Note: `await after` can be used as an awaitable alternative to `after(func)`, or `await use` can be also as a shorthand for `use(plugin); await after()`.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The callback changes based on the parameters you give:
 | 
						
						
						
							|  |  | 1. If no parameter is given to the callback and there is an error, that error will be passed to the next error handler.
 | 
						
						
						
							|  |  | 2. If one parameter is given to the callback, that parameter will be the `error` object.
 | 
						
						
						
							|  |  | 3. If two parameters are given to the callback, the first will be the `error` object, the second will be the `done` callback.
 | 
						
						
						
							|  |  | 4. If three parameters are given to the callback, the first will be the `error` object, the second will be the top level `context` and the third the `done` callback.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | In the "no parameter" and "one parameter" variants, the callback can return a `Promise`.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const server = {}
 | 
						
						
						
							|  |  | const app = require('avvio')(server)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ...
 | 
						
						
						
							|  |  | // after with one parameter
 | 
						
						
						
							|  |  | app.after(function (err) {
 | 
						
						
						
							|  |  |   if (err) throw err
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // after with two parameter
 | 
						
						
						
							|  |  | app.after(function (err, done) {
 | 
						
						
						
							|  |  |   if (err) throw err
 | 
						
						
						
							|  |  |   done()
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // after with three parameters
 | 
						
						
						
							|  |  | app.after(function (err, context, done) {
 | 
						
						
						
							|  |  |   if (err) throw err
 | 
						
						
						
							|  |  |   assert.equal(context, server)
 | 
						
						
						
							|  |  |   done()
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // async after with one parameter
 | 
						
						
						
							|  |  | app.after(async function (err) {
 | 
						
						
						
							|  |  |   await sleep(10)
 | 
						
						
						
							|  |  |   if (err) {
 | 
						
						
						
							|  |  |     throw err
 | 
						
						
						
							|  |  |   }
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // async after with no parameter
 | 
						
						
						
							|  |  | app.after(async function () {
 | 
						
						
						
							|  |  |   await sleep(10)
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | `done` must be called only once.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | If called with a function, it returns the instance on which `after` is called, to support a chainable API.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | <a name="await-after"></a>
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### await app.after() | app.after() => Promise
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Calling after with no function argument loads any plugins previously registered via `use` and returns a promise, which resolves when all plugins registered so far have loaded.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | async function main () {
 | 
						
						
						
							|  |  |   app.use(async function (server, opts) {
 | 
						
						
						
							|  |  |     await sleep(10)
 | 
						
						
						
							|  |  |     console.log('this first')
 | 
						
						
						
							|  |  |   })
 | 
						
						
						
							|  |  |   app.use(async function (server, opts) {
 | 
						
						
						
							|  |  |     await sleep(10)
 | 
						
						
						
							|  |  |     console.log('this second')
 | 
						
						
						
							|  |  |   })
 | 
						
						
						
							|  |  |   console.log('before after')
 | 
						
						
						
							|  |  |   await app.after()
 | 
						
						
						
							|  |  |   console.log('after after')
 | 
						
						
						
							|  |  |   app.use(async function (server, opts) {
 | 
						
						
						
							|  |  |     await sleep(10)
 | 
						
						
						
							|  |  |     console.log('this third')
 | 
						
						
						
							|  |  |   })
 | 
						
						
						
							|  |  |   await app.ready()
 | 
						
						
						
							|  |  |   console.log('ready')
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | main().catch((err) => console.error(err))
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Unlike `after` and `use`, `await after` is *not* chainable.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | <a name="ready"></a>
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### app.ready([func(error, [context], [done])])
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Calls a function after all the plugins and `after` call are completed, but before `'start'` is emitted. `ready` callbacks are executed one at a time.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The callback changes based on the parameters you give:
 | 
						
						
						
							|  |  | 1. If no parameter is given to the callback and there is an error, that error will be passed to the next error handler.
 | 
						
						
						
							|  |  | 2. If one parameter is given to the callback, that parameter will be the `error` object.
 | 
						
						
						
							|  |  | 3. If two parameters are given to the callback, the first will be the `error` object, the second will be the `done` callback.
 | 
						
						
						
							|  |  | 4. If three parameters are given to the callback, the first will be the `error` object, the second will be the top level `context` unless you have specified both server and override, in that case the `context` will be what the override returns, and the third the `done` callback.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | If no callback is provided `ready` will return a Promise that is resolved or rejected once plugins and `after` calls are completed.  On success `context` is provided to the `.then` callback, if an error occurs it is provided to the `.catch` callback.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const server = {}
 | 
						
						
						
							|  |  | const app = require('avvio')(server)
 | 
						
						
						
							|  |  | ...
 | 
						
						
						
							|  |  | // ready with one parameter
 | 
						
						
						
							|  |  | app.ready(function (err) {
 | 
						
						
						
							|  |  |   if (err) throw err
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // ready with two parameter
 | 
						
						
						
							|  |  | app.ready(function (err, done) {
 | 
						
						
						
							|  |  |   if (err) throw err
 | 
						
						
						
							|  |  |   done()
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // ready with three parameters
 | 
						
						
						
							|  |  | app.ready(function (err, context, done) {
 | 
						
						
						
							|  |  |   if (err) throw err
 | 
						
						
						
							|  |  |   assert.equal(context, server)
 | 
						
						
						
							|  |  |   done()
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // ready with Promise
 | 
						
						
						
							|  |  | app.ready()
 | 
						
						
						
							|  |  |   .then(() => console.log('Ready'))
 | 
						
						
						
							|  |  |   .catch(err => {
 | 
						
						
						
							|  |  |     console.error(err)
 | 
						
						
						
							|  |  |     process.exit(1)
 | 
						
						
						
							|  |  |   })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // await ready from an async function.
 | 
						
						
						
							|  |  | async function main () [
 | 
						
						
						
							|  |  |   try {
 | 
						
						
						
							|  |  |     await app.ready()
 | 
						
						
						
							|  |  |     console.log('Ready')
 | 
						
						
						
							|  |  |   } catch(err) {
 | 
						
						
						
							|  |  |     console.error(err)
 | 
						
						
						
							|  |  |     process.exit(1)
 | 
						
						
						
							|  |  |   }
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | `done` must be called only once.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The callback form of this function has no return value.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | If `autostart: false` is passed as an option, calling `.ready()`  will
 | 
						
						
						
							|  |  | also start the boot sequence.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | <a name="start"></a>
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### app.start()
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Start the boot sequence, if it was not started yet.
 | 
						
						
						
							|  |  | Returns the `app` instance.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | <a name="express"></a>
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### avvio.express(app)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Same as:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const app = express()
 | 
						
						
						
							|  |  | const avvio = require('avvio')
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | avvio(app, {
 | 
						
						
						
							|  |  |   expose: {
 | 
						
						
						
							|  |  |     use: 'load'
 | 
						
						
						
							|  |  |   }
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | <a name="override"></a>
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### app.override(server, plugin, options)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Allows overriding the instance of the server for each loading plugin.
 | 
						
						
						
							|  |  | It allows the creation of an inheritance chain for the server instances.
 | 
						
						
						
							|  |  | The first parameter is the server instance and the second is the plugin function while the third is the options object that you give to use.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const assert = require('assert')
 | 
						
						
						
							|  |  | const server = { count: 0 }
 | 
						
						
						
							|  |  | const app = require('avvio')(server)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | console.log(app !== server, 'override must be set on the Avvio instance')
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | app.override = function (s, fn, opts) {
 | 
						
						
						
							|  |  |   // create a new instance with the
 | 
						
						
						
							|  |  |   // server as the prototype
 | 
						
						
						
							|  |  |   const res = Object.create(s)
 | 
						
						
						
							|  |  |   res.count = res.count + 1
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   return res
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | app.use(function first (s1, opts, cb) {
 | 
						
						
						
							|  |  |   assert(s1 !== server)
 | 
						
						
						
							|  |  |   assert(server.isPrototypeOf(s1))
 | 
						
						
						
							|  |  |   assert(s1.count === 1)
 | 
						
						
						
							|  |  |   s1.use(second)
 | 
						
						
						
							|  |  |   cb()
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |   function second (s2, opts, cb) {
 | 
						
						
						
							|  |  |     assert(s2 !== s1)
 | 
						
						
						
							|  |  |     assert(s1.isPrototypeOf(s2))
 | 
						
						
						
							|  |  |     assert(s2.count === 2)
 | 
						
						
						
							|  |  |     cb()
 | 
						
						
						
							|  |  |   }
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | <a name="onClose"></a>
 | 
						
						
						
							|  |  | ### app.onClose(func([context], [done]))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Registers a new callback that will be fired once then `close` api is called.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The callback changes basing on the parameters you give:
 | 
						
						
						
							|  |  | 1. If one parameter is given to the callback, that parameter will be the `context`.
 | 
						
						
						
							|  |  | 2. If zero or one parameter is given, the callback may return a promise
 | 
						
						
						
							|  |  | 3. If two parameters are given to the callback, the first will be the top level `context` unless you have specified both server and override, in that case the `context` will be what the override returns, the second will be the `done` callback.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const server = {}
 | 
						
						
						
							|  |  | const app = require('avvio')(server)
 | 
						
						
						
							|  |  | ...
 | 
						
						
						
							|  |  | // onClose with one parameter
 | 
						
						
						
							|  |  | app.onClose(function (context) {
 | 
						
						
						
							|  |  |   // ...
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // onClose with one parameter, returning a promise
 | 
						
						
						
							|  |  | app.onClose(function (context) {
 | 
						
						
						
							|  |  |   return new Promise((resolve, reject) => {
 | 
						
						
						
							|  |  |     // ...
 | 
						
						
						
							|  |  |   })
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // async onClose with one parameter
 | 
						
						
						
							|  |  | app.onClose(async function (context) {
 | 
						
						
						
							|  |  |   // ...
 | 
						
						
						
							|  |  |   await ...
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // onClose with two parameter
 | 
						
						
						
							|  |  | app.onClose(function (context, done) {
 | 
						
						
						
							|  |  |   // ...
 | 
						
						
						
							|  |  |   done()
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | If the callback returns a promise, the next onClose callback and the close callback will not run until the promise is either resolved or rejected.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | `done` must be called only once.
 | 
						
						
						
							|  |  | Returns the instance on which `onClose` is called, to support a chainable API.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | <a name="close"></a>
 | 
						
						
						
							|  |  | ### app.close(func(error, [context], [done]))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Starts the shutdown procedure, the callback is called once all the registered callbacks with `onClose` has been executed.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The callback changes based on the parameters you give:
 | 
						
						
						
							|  |  | 1. If one parameter is given to the callback, that parameter will be the `error` object.
 | 
						
						
						
							|  |  | 2. If two parameters are given to the callback, the first will be the `error` object, the second will be the `done` callback.
 | 
						
						
						
							|  |  | 3. If three parameters are given to the callback, the first will be the `error` object, the second will be the top level `context` unless you have specified both server and override, in that case the `context` will be what the override returns, and the third the `done` callback.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | If no callback is provided `close` will return a Promise.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const server = {}
 | 
						
						
						
							|  |  | const app = require('avvio')(server)
 | 
						
						
						
							|  |  | ...
 | 
						
						
						
							|  |  | // close with one parameter
 | 
						
						
						
							|  |  | app.close(function (err) {
 | 
						
						
						
							|  |  |   if (err) throw err
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // close with two parameter
 | 
						
						
						
							|  |  | app.close(function (err, done) {
 | 
						
						
						
							|  |  |   if (err) throw err
 | 
						
						
						
							|  |  |   done()
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // close with three parameters
 | 
						
						
						
							|  |  | app.close(function (err, context, done) {
 | 
						
						
						
							|  |  |   if (err) throw err
 | 
						
						
						
							|  |  |   assert.equal(context, server)
 | 
						
						
						
							|  |  |   done()
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | // close with Promise
 | 
						
						
						
							|  |  | app.close()
 | 
						
						
						
							|  |  |   .then(() => console.log('Closed'))
 | 
						
						
						
							|  |  |   .catch(err => {
 | 
						
						
						
							|  |  |     console.error(err)
 | 
						
						
						
							|  |  |     process.exit(1)
 | 
						
						
						
							|  |  |   })
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | `done` must be called only once.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | <a name="toJSON"></a>
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### avvio.toJSON()
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Return a JSON tree representing the state of the plugins and the loading time.
 | 
						
						
						
							|  |  | Call it on `preReady` to get the complete tree.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const avvio = require('avvio')()
 | 
						
						
						
							|  |  | avvio.on('preReady', () => {
 | 
						
						
						
							|  |  |   avvio.toJSON()
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The output is like this:
 | 
						
						
						
							|  |  | ```json
 | 
						
						
						
							|  |  | {
 | 
						
						
						
							|  |  |   "label": "bound root",
 | 
						
						
						
							|  |  |   "start": 1550245184665,
 | 
						
						
						
							|  |  |   "nodes": [
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |       "parent": "bound root",
 | 
						
						
						
							|  |  |       "start": 1550245184665,
 | 
						
						
						
							|  |  |       "label": "first",
 | 
						
						
						
							|  |  |       "nodes": [
 | 
						
						
						
							|  |  |         {
 | 
						
						
						
							|  |  |           "parent": "first",
 | 
						
						
						
							|  |  |           "start": 1550245184708,
 | 
						
						
						
							|  |  |           "label": "second",
 | 
						
						
						
							|  |  |           "nodes": [],
 | 
						
						
						
							|  |  |           "stop": 1550245184709,
 | 
						
						
						
							|  |  |           "diff": 1
 | 
						
						
						
							|  |  |         }
 | 
						
						
						
							|  |  |       ],
 | 
						
						
						
							|  |  |       "stop": 1550245184709,
 | 
						
						
						
							|  |  |       "diff": 44
 | 
						
						
						
							|  |  |     },
 | 
						
						
						
							|  |  |     {
 | 
						
						
						
							|  |  |       "parent": "bound root",
 | 
						
						
						
							|  |  |       "start": 1550245184709,
 | 
						
						
						
							|  |  |       "label": "third",
 | 
						
						
						
							|  |  |       "nodes": [],
 | 
						
						
						
							|  |  |       "stop": 1550245184709,
 | 
						
						
						
							|  |  |       "diff": 0
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  |   ],
 | 
						
						
						
							|  |  |   "stop": 1550245184709,
 | 
						
						
						
							|  |  |   "diff": 44
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | <a name="prettyPrint"></a>
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### avvio.prettyPrint()
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | This method will return a printable string with the tree returned by the `toJSON()` method.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const avvio = require('avvio')()
 | 
						
						
						
							|  |  | avvio.on('preReady', () => {
 | 
						
						
						
							|  |  |   console.log(avvio.prettyPrint())
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The output will be like:
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | avvio 56 ms
 | 
						
						
						
							|  |  | ├── first 52 ms
 | 
						
						
						
							|  |  | ├── second 1 ms
 | 
						
						
						
							|  |  | └── third 2 ms
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | -------------------------------------------------------
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ## Acknowledgements
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | This project was kindly sponsored by [nearForm](https://nearform.com).
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ## License
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Copyright Matteo Collina 2016-2020, Licensed under [MIT][].
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | [MIT]: ./LICENSE
 | 
						
						
						
							|  |  | [example]: ./example.js
 |