Comparing version 3.2.0 to 4.0.0
85
boot.js
@@ -43,7 +43,6 @@ 'use strict' | ||
server[readyKey] = function (func) { | ||
if (typeof func !== 'function') { | ||
if (func && typeof func !== 'function') { | ||
throw new Error('not a function') | ||
} | ||
instance.ready(encapsulateThreeParam(func, this)) | ||
return this | ||
return instance.ready(func ? encapsulateThreeParam(func, this) : undefined) | ||
} | ||
@@ -92,2 +91,6 @@ | ||
if (opts.autostart !== false) { | ||
opts.autostart = true | ||
} | ||
server = server || this | ||
@@ -103,2 +106,3 @@ | ||
this.started = false | ||
this.booted = false | ||
@@ -120,4 +124,21 @@ | ||
// 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() | ||
} | ||
}) | ||
} | ||
@@ -127,24 +148,7 @@ | ||
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) | ||
} | ||
@@ -184,4 +188,5 @@ | ||
// we reinit, if use is called after emitting start once | ||
this._init() | ||
if (this.booted) { | ||
throw new Error('root plugin has already booted') | ||
} | ||
@@ -238,4 +243,24 @@ // we always add plugins to load at the current element | ||
Boot.prototype.ready = function (func) { | ||
this._readyQ.push(func) | ||
return this | ||
if (func) { | ||
if (typeof func !== 'function') { | ||
throw new Error('not a function') | ||
} | ||
this._readyQ.push(func) | ||
this.start() | ||
return | ||
} | ||
return new Promise((resolve, reject) => { | ||
this._readyQ.push(readyPromiseCB) | ||
this.start() | ||
function readyPromiseCB (err, context, done) { | ||
if (err) { | ||
reject(err) | ||
} else { | ||
resolve(context) | ||
} | ||
process.nextTick(done) | ||
} | ||
}) | ||
} | ||
@@ -242,0 +267,0 @@ |
{ | ||
"name": "avvio", | ||
"version": "3.2.0", | ||
"version": "4.0.0", | ||
"description": "Asynchronous bootstrapping of Node applications", | ||
@@ -5,0 +5,0 @@ "main": "boot.js", |
@@ -76,2 +76,3 @@ # avvio | ||
* <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> | ||
@@ -85,3 +86,3 @@ * <a href="#onClose"><code>instance.<b>onClose()</b></code></a> | ||
### avvio([instance], [started]) | ||
### avvio([instance], [options], [started]) | ||
@@ -112,3 +113,6 @@ Starts the avvio sequence. | ||
* `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: | ||
@@ -230,3 +234,3 @@ | ||
### app.ready(func(error, [context], [done])) | ||
### app.ready([func(error, [context], [done])]) | ||
@@ -241,5 +245,7 @@ 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. | ||
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('avvioo')(server) | ||
const app = require('avvio')(server) | ||
... | ||
@@ -263,2 +269,21 @@ // ready with one parameter | ||
}) | ||
// 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) | ||
} | ||
} | ||
``` | ||
@@ -268,5 +293,15 @@ | ||
Returns the instance on which `ready` is called, to support a chainable API. | ||
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. | ||
------------------------------------------------------- | ||
<a name="express"></a> | ||
@@ -273,0 +308,0 @@ |
@@ -8,4 +8,4 @@ 'use strict' | ||
test('one level', (t) => { | ||
t.plan(13) | ||
test('one level', async (t) => { | ||
t.plan(14) | ||
@@ -42,11 +42,12 @@ const app = boot() | ||
app.on('start', () => { | ||
t.ok(firstLoaded, 'first is loaded') | ||
t.ok(secondLoaded, 'second is loaded') | ||
t.ok(thirdLoaded, 'third is loaded') | ||
t.pass('booted') | ||
}) | ||
const readyContext = await app.ready() | ||
t.equal(app, readyContext) | ||
t.ok(firstLoaded, 'first is loaded') | ||
t.ok(secondLoaded, 'second is loaded') | ||
t.ok(thirdLoaded, 'third is loaded') | ||
t.pass('booted') | ||
}) | ||
test('multiple reentrant plugin loading', (t) => { | ||
test('multiple reentrant plugin loading', async (t) => { | ||
t.plan(31) | ||
@@ -113,10 +114,27 @@ | ||
app.on('start', () => { | ||
t.ok(firstLoaded, 'first is loaded') | ||
t.ok(secondLoaded, 'second is loaded') | ||
t.ok(thirdLoaded, 'third is loaded') | ||
t.ok(fourthLoaded, 'fourth is loaded') | ||
t.ok(fifthLoaded, 'fifth is loaded') | ||
t.pass('booted') | ||
await app.ready() | ||
t.ok(firstLoaded, 'first is loaded') | ||
t.ok(secondLoaded, 'second is loaded') | ||
t.ok(thirdLoaded, 'third is loaded') | ||
t.ok(fourthLoaded, 'fourth is loaded') | ||
t.ok(fifthLoaded, 'fifth is loaded') | ||
t.pass('booted') | ||
}) | ||
test('async ready plugin registration (errored)', async (t) => { | ||
t.plan(1) | ||
const app = boot() | ||
app.use(async (server, opts) => { | ||
await sleep(10) | ||
throw new Error('kaboom') | ||
}) | ||
try { | ||
await app.ready() | ||
t.fail('we should not be here') | ||
} catch (err) { | ||
t.is(err.message, 'kaboom') | ||
} | ||
}) |
@@ -208,1 +208,51 @@ 'use strict' | ||
}) | ||
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) | ||
}) |
@@ -9,3 +9,3 @@ 'use strict' | ||
boot() | ||
let readyResult = boot() | ||
.use(function (ctx, opts, done) { | ||
@@ -20,6 +20,4 @@ t.pass('1st plugin') | ||
t.pass('we are ready') | ||
}).use(function (ctx, opts, done) { | ||
t.pass('3rd plugin') | ||
done() | ||
}) | ||
t.equal(readyResult, undefined) | ||
}) | ||
@@ -33,3 +31,3 @@ | ||
app | ||
let readyResult = app | ||
.use(function (ctx, opts, done) { | ||
@@ -44,6 +42,4 @@ t.pass('1st plugin') | ||
t.pass('we are ready') | ||
}).use(function (ctx, opts, done) { | ||
t.pass('3rd plugin') | ||
done() | ||
}) | ||
t.equal(readyResult, undefined) | ||
}) | ||
@@ -50,0 +46,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
62015
1946
436