From 7e4ff4d0d4b618e35ec364aa518576592ae307d9 Mon Sep 17 00:00:00 2001 From: Oscar Funes <571775+osukaa@users.noreply.github.com> Date: Wed, 23 Oct 2024 22:55:22 -0700 Subject: [PATCH 1/2] Add usage of hapi/topo to sort through the plugin list. --- API.md | 13 +++++++++++++ lib/index.js | 10 +++++++++- package.json | 1 + test/index.js | 31 +++++++++++++++++++++++++++++++ test/plugins/after.js | 13 +++++++++++++ test/plugins/before.js | 10 ++++++++++ 6 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 test/plugins/after.js create mode 100644 test/plugins/before.js diff --git a/API.md b/API.md index 376ebc3..281e6b8 100644 --- a/API.md +++ b/API.md @@ -86,6 +86,19 @@ Composes a hapi server object where: If you are developing a plugin, ensure your plugin dependencies are properly managed to guarantee that all dependencies are loaded before your plugin registration completes. See [hapi's](https://hapi.dev/api) `server.dependency(dependencies, [after])` for more information. +If you need to sort the plugins before registration, you can do so by adding `before` and `after` to the plugin object. The `before` and `after` properties are a plugin name or arrays of plugin names that the plugin should be placed before or after. + +```js +{ + register: { + plugins: [ + { plugin: 'myplugin', before: ['anotherplugin'] }, + { plugin: 'anotherplugin', after: ['myplugin'] } + ] + } +} +``` + ## Usage ```javascript diff --git a/lib/index.js b/lib/index.js index 8cfb3a0..f2678e1 100755 --- a/lib/index.js +++ b/lib/index.js @@ -6,6 +6,8 @@ const Hapi = require('@hapi/hapi'); const Hoek = require('@hapi/hoek'); const Validate = require('@hapi/validate'); const MoWalk = require('mo-walk'); +const Topo = require('@hapi/topo'); + const internals = {}; @@ -43,7 +45,13 @@ exports.compose = async function (manifest, options = {}) { return internals.parsePlugin(plugin, options.relativeTo); })); - await server.register(plugins, manifest.register.options ?? {}); + const sorted = new Topo.Sorter(); + + for (const plugin of plugins) { + sorted.add([plugin], { after: plugin.after, before: plugin.before, group: plugin.name ?? plugin.plugin.name }); + } + + await server.register(sorted.nodes, manifest.register.options ?? {}); } return server; diff --git a/package.json b/package.json index 208888f..a4697a7 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ }, "dependencies": { "@hapi/hoek": "^11.0.2", + "@hapi/topo": "^6.0.2", "@hapi/validate": "^2.0.1", "mo-walk": "^1.2.0" }, diff --git a/test/index.js b/test/index.js index 9709d4c..e2f1369 100755 --- a/test/index.js +++ b/test/index.js @@ -404,6 +404,37 @@ describe('compose()', () => { expect(secondResponse.statusCode).to.equal(200); expect(secondResponse.payload).to.equal('second'); }); + + it('has a registration with before and after options', async () => { + + const manifest = { + register: { + plugins: [ + { + plugin: '../test/plugins/after.js', + after: ['before'] + }, + { + plugin: require('./plugins/route'), + routes: { prefix: '/test/' } + }, + { + plugin: '../test/plugins/before.js', + before: ['after'] + } + ], + options: { + routes: { prefix: '/override/me/' } + } + } + }; + + const server = await Glue.compose(manifest); + expect(server.plugins.before.exists).to.equal(true); + expect(server.plugins.after.exists).to.equal(true); + const response = await server.inject('/test/plugin'); + expect(response.statusCode).to.equal(200); + }); }); it('resolves ES modules from a path', async () => { diff --git a/test/plugins/after.js b/test/plugins/after.js new file mode 100644 index 0000000..f6c393e --- /dev/null +++ b/test/plugins/after.js @@ -0,0 +1,13 @@ +'use strict'; + +const Assert = require('assert'); + +exports.register = function (server, options) { + + Assert(server.plugins.before.exists, 'before plugin should be registered before this plugin'); + server.expose('exists', true); +}; + +exports.name = 'after'; + +exports.multiple = false; diff --git a/test/plugins/before.js b/test/plugins/before.js new file mode 100644 index 0000000..447b144 --- /dev/null +++ b/test/plugins/before.js @@ -0,0 +1,10 @@ +'use strict'; + +exports.register = function (server, options) { + + server.expose('exists', true); +}; + +exports.name = 'before'; + +exports.multiple = false; From ae6fd22542a4add21f317d82be8a7773d4ee73e1 Mon Sep 17 00:00:00 2001 From: Oscar Funes <571775+osukaa@users.noreply.github.com> Date: Wed, 23 Oct 2024 23:10:22 -0700 Subject: [PATCH 2/2] Fix assertion, instead of exact match use includes due to different behavior across node versions. --- API.md | 2 +- test/esm.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/API.md b/API.md index 281e6b8..518c20c 100644 --- a/API.md +++ b/API.md @@ -188,7 +188,7 @@ const startServer = async function () { await server.start(); console.log('hapi days!'); } - catch (err) + catch (err) { console.error(err); process.exit(1); } diff --git a/test/esm.js b/test/esm.js index 9e43876..5326717 100644 --- a/test/esm.js +++ b/test/esm.js @@ -19,7 +19,7 @@ describe('import()', () => { it('exposes all methods and classes as named imports', () => { - expect(Object.keys(Glue)).to.equal([ + expect(Object.keys(Glue)).to.include([ 'compose', 'default' ]);