Comparing version 7.0.0-alpha.0 to 7.0.0-alpha.1
34
boot.js
@@ -9,2 +9,3 @@ 'use strict' | ||
const debug = require('debug')('avvio') | ||
const kAvvio = Symbol('kAvvio') | ||
@@ -37,2 +38,3 @@ function wrap (server, opts, instance) { | ||
Object.defineProperty(server, 'then', { get: thenify.bind(instance) }) | ||
server[kAvvio] = true | ||
@@ -193,2 +195,4 @@ server[afterKey] = function (func) { | ||
Boot.prototype[kAvvio] = true | ||
// load a plugin | ||
@@ -200,7 +204,13 @@ Boot.prototype.use = function (plugin, opts) { | ||
Boot.prototype._loadRegistered = function (plugin) { | ||
plugin = plugin || this._lastUsed | ||
return new Promise((resolve) => { | ||
Boot.prototype._loadRegistered = function () { | ||
const plugin = this._current[0] | ||
return new Promise((resolve, reject) => { | ||
var weNeedToStart = !this.started && !this.booted | ||
if (plugin && !plugin.loaded) { | ||
plugin.asyncQ.push(() => { | ||
debug('_loadRegistered deferring promise', plugin.name) | ||
plugin.pushToAsyncQ((err) => { | ||
if (err) { | ||
reject(err) | ||
return | ||
} | ||
resolve() | ||
@@ -214,3 +224,3 @@ }) | ||
// so one can use after() befor calling ready | ||
if (!this.started && !this.booted) { | ||
if (weNeedToStart) { | ||
this._root.q.resume() | ||
@@ -257,2 +267,6 @@ } | ||
Boot.prototype.after = function (func) { | ||
if (!func) { | ||
return this._loadRegistered() | ||
} | ||
this._addPlugin(_after.bind(this), {}, true) | ||
@@ -353,3 +367,7 @@ | ||
// because of automatic promise chaining. | ||
if (this.booted) return | ||
if (this.booted) { | ||
debug('thenify returning null because we are already booted') | ||
return | ||
} | ||
debug('thenify') | ||
const p = this._loadRegistered() | ||
@@ -369,3 +387,3 @@ return p.then.bind(p) | ||
res = func() | ||
if (res && typeof res.then === 'function') { | ||
if (res && !res[kAvvio] && typeof res.then === 'function') { | ||
res.then(() => process.nextTick(cb), (e) => process.nextTick(cb, e)) | ||
@@ -377,3 +395,3 @@ } else { | ||
res = func(err) | ||
if (res && typeof res.then === 'function') { | ||
if (res && !res[kAvvio] && typeof res.then === 'function') { | ||
res.then(() => process.nextTick(cb), (e) => process.nextTick(cb, e)) | ||
@@ -380,0 +398,0 @@ } else { |
{ | ||
"name": "avvio", | ||
"version": "7.0.0-alpha.0", | ||
"version": "7.0.0-alpha.1", | ||
"description": "Asynchronous bootstrapping of Node applications", | ||
@@ -5,0 +5,0 @@ "main": "boot.js", |
@@ -31,5 +31,5 @@ 'use strict' | ||
function Plugin (parent, func, optsOrFunc, isAfter, timeout) { | ||
this.started = false | ||
this.func = func | ||
this.opts = optsOrFunc | ||
this.deferred = false | ||
this.onFinish = null | ||
@@ -42,4 +42,5 @@ this.parent = parent | ||
this.q.pause() | ||
this.asyncQ = fastq(parent, (resolve, cb) => { | ||
resolve(this.server) | ||
this._error = null | ||
this.asyncQ = fastq(parent, (done, cb) => { | ||
done(this._error || this.parent._error) | ||
cb() | ||
@@ -88,8 +89,6 @@ }, 1) | ||
this._error = err | ||
if (err) { | ||
debug('exec errored', name) | ||
// In case of errors, we need to kickstart | ||
// the asyncQ as it won't get started otherwise | ||
this.asyncQ.resume() | ||
} else { | ||
@@ -120,2 +119,3 @@ debug('exec completed', name) | ||
this.started = true | ||
this.emit('start', this.server ? this.server.name : null, this.name, Date.now()) | ||
@@ -126,10 +126,2 @@ var promise = func(this.server, this.opts, done) | ||
debug('resolving promise', name) | ||
queueMicrotask(() => { | ||
if (this.asyncQ.length() > 0) { | ||
this.server.after(() => { | ||
this.asyncQ.resume() | ||
}) | ||
} | ||
this.q.resume() | ||
}) | ||
@@ -148,4 +140,27 @@ promise.then( | ||
Plugin.prototype.pushToAsyncQ = function (fn) { | ||
if (!this.server) { | ||
this.on('start', () => this._pushToAsyncQ(fn)) | ||
return | ||
} | ||
this._pushToAsyncQ(fn) | ||
} | ||
Plugin.prototype._pushToAsyncQ = function (fn) { | ||
debug('_pushToAsyncQ', this.name) | ||
if (this.asyncQ.length() === 0) { | ||
this.server.after((err, cb) => { | ||
this.q.pause() | ||
debug('resuming asyncQ', this.name) | ||
this.asyncQ.resume() | ||
process.nextTick(cb, err) | ||
}) | ||
} | ||
this.asyncQ.push(fn) | ||
this.q.resume() | ||
} | ||
Plugin.prototype.finish = function (err, cb) { | ||
debug('finish', this.name) | ||
debug('finish', this.name, err) | ||
const done = () => { | ||
@@ -164,2 +179,3 @@ if (this.loaded) { | ||
if (err) { | ||
this.asyncQ.resume() | ||
done() | ||
@@ -170,3 +186,3 @@ return | ||
const check = () => { | ||
debug('check', this.name, this.q.length(), this.q.running()) | ||
debug('check', this.name, this.q.length(), this.q.running(), this.asyncQ.length()) | ||
if (this.q.length() === 0 && this.q.running() === 0) { | ||
@@ -177,3 +193,3 @@ if (this.asyncQ.length() > 0) { | ||
this.asyncQ.pause() | ||
check() | ||
queueMicrotask(check) | ||
} | ||
@@ -193,3 +209,3 @@ this.asyncQ.resume() | ||
// that might be scheduled in the loading callback | ||
process.nextTick(check) | ||
queueMicrotask(check) | ||
} | ||
@@ -199,3 +215,3 @@ } | ||
process.nextTick(check) | ||
queueMicrotask(check) | ||
@@ -202,0 +218,0 @@ // we start loading the dependents plugins only once |
@@ -756,1 +756,35 @@ 'use strict' | ||
}) | ||
test('after return self', (t) => { | ||
t.plan(6) | ||
const app = boot() | ||
let pluginLoaded = false | ||
let afterCalled = false | ||
let second = false | ||
app.use(function (s, opts, done) { | ||
t.notOk(afterCalled, 'after not called') | ||
pluginLoaded = true | ||
done() | ||
}) | ||
app.after(function () { | ||
t.ok(pluginLoaded, 'afterred!') | ||
afterCalled = true | ||
// happens with after(() => app.use(..)) | ||
return app | ||
}) | ||
app.use(function (s, opts, done) { | ||
t.ok(afterCalled, 'after called') | ||
second = true | ||
done() | ||
}) | ||
app.on('start', () => { | ||
t.ok(afterCalled, 'after called') | ||
t.ok(pluginLoaded, 'plugin loaded') | ||
t.ok(second, 'second plugin loaded') | ||
}) | ||
}) |
@@ -30,2 +30,23 @@ 'use strict' | ||
test('await after without server', async (t) => { | ||
const app = boot() | ||
let secondLoaded = false | ||
app.use(async (app) => { | ||
t.pass('plugin init') | ||
app.use(async () => { | ||
t.pass('plugin2 init') | ||
await sleep(1) | ||
secondLoaded = true | ||
}) | ||
}) | ||
await app.after() | ||
t.pass('reachable') | ||
t.is(secondLoaded, true) | ||
await app.ready() | ||
t.pass('reachable') | ||
}) | ||
test('await after - nested plugins with future tick callbacks', async (t) => { | ||
@@ -313,1 +334,14 @@ const app = {} | ||
}) | ||
test('stop processing after errors', async (t) => { | ||
const app = boot() | ||
try { | ||
await app.use(async function first (app) { | ||
t.pass('first should be loaded') | ||
throw new Error('kaboom') | ||
}) | ||
} catch (e) { | ||
t.is(e.message, 'kaboom') | ||
} | ||
}) |
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
122883
4160