diff --git a/README.md b/README.md
index e82c448..51060df 100644
--- a/README.md
+++ b/README.md
@@ -73,6 +73,7 @@ async function third (instance, opts) {
* instance.use()
* instance.after()
* instance.ready()
+ * instance.start()
* instance.override()
* instance.onClose()
* instance.close()
@@ -81,7 +82,7 @@ async function third (instance, opts) {
-------------------------------------------------------
-### avvio([instance], [started])
+### avvio([instance], [options], [started])
Starts the avvio sequence.
As the name suggest, `instance` is the object representing your application.
@@ -107,6 +108,9 @@ server.use(function first (s, opts, 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).
+
Events:
@@ -261,6 +265,16 @@ app.ready(function (err, context, done) {
Returns the instance on which `ready` is called, to support a chainable API.
+If `autostart: false` is passed as an option, calling `.ready()` will
+also start the boot sequence.
+
+-------------------------------------------------------
+
+
+### app.start()
+
+Start the boot sequence, if it was not started yet.
+
-------------------------------------------------------
diff --git a/boot.js b/boot.js
index 4a3dee1..c0bd4cb 100644
--- a/boot.js
+++ b/boot.js
@@ -88,6 +88,10 @@ function Boot (server, opts, done) {
return instance
}
+ if (opts.autostart !== false) {
+ opts.autostart = true
+ }
+
server = server || this
this._server = server
@@ -98,6 +102,7 @@ function Boot (server, opts, done) {
this.once('start', done)
}
+ this.started = false
this.booted = false
this._readyQ = fastq(this, callWithCbOrNextTick, 1)
@@ -114,34 +119,34 @@ function Boot (server, opts, done) {
}
this._thereIsCloseCb = false
- // we init, because we need to emit "start" if no use is called
- this._init()
+ this._doStart = null
+ const main = new Plugin(this, (s, opts, done) => {
+ this._doStart = done
+ if (opts.autostart) {
+ this.start()
+ }
+ }, opts, noop)
+
+ Plugin.loadPlugin.call(this, main, (err) => {
+ debug('root plugin ready')
+ if (err) {
+ this._error = err
+ if (this._readyQ.length() === 0) {
+ throw err
+ }
+ } else {
+ this._readyQ.resume()
+ }
+ })
}
inherits(Boot, EE)
-Boot.prototype._init = function () {
- if (this.booted) {
- throw new Error('root plugin has already booted')
- }
+Boot.prototype.start = function () {
+ this.started = true
- if (this._current.length === 0) {
- const main = new Plugin(this, function root (s, opts, done) {
- // we need to wait any call to use() to happen
- process.nextTick(done)
- }, {}, noop)
- Plugin.loadPlugin.call(this, main, (err) => {
- debug('root plugin ready')
- if (err) {
- this._error = err
- if (this._readyQ.length() === 0) {
- throw err
- }
- } else {
- this._readyQ.resume()
- }
- })
- }
+ // we need to wait any call to use() to happen
+ process.nextTick(this._doStart)
}
// allows to override the instance of a server, given a plugin
@@ -176,8 +181,9 @@ Boot.prototype._addPlugin = function (plugin, opts, callback) {
opts = opts || {}
callback = callback || null
- // we reinit, if use is called after emitting start once
- this._init()
+ if (this.booted) {
+ throw new Error('root plugin has already booted')
+ }
// we always add plugins to load at the current element
const current = this._current[0]
@@ -230,6 +236,7 @@ Boot.prototype.close = function (func) {
Boot.prototype.ready = function (func) {
this._readyQ.push(func)
+ this.start()
return this
}
diff --git a/test/basic.test.js b/test/basic.test.js
index ddd197b..3004626 100644
--- a/test/basic.test.js
+++ b/test/basic.test.js
@@ -205,3 +205,53 @@ test('promise long resolve', (t) => {
t.notOk(err)
})
})
+
+test('do not autostart', (t) => {
+ const app = boot(null, {
+ autostart: false
+ })
+ app.on('start', () => {
+ t.fail()
+ })
+ t.end()
+})
+
+test('start with ready', (t) => {
+ t.plan(2)
+
+ const app = boot(null, {
+ autostart: false
+ })
+
+ app.on('start', () => {
+ t.pass()
+ })
+
+ app.ready(function (err) {
+ t.error(err)
+ })
+})
+
+test('load a plugin after start()', (t) => {
+ t.plan(1)
+
+ var startCalled = false
+ const app = boot(null, {
+ autostart: false
+ })
+
+ app.use((s, opts, done) => {
+ t.ok(startCalled)
+ done()
+ })
+
+ // we use a timer because
+ // it is more reliable than
+ // nextTick and setImmediate
+ // this almost always will come
+ // after those are completed
+ setTimeout(() => {
+ app.start()
+ startCalled = true
+ }, 2)
+})