Skip to content

Commit

Permalink
refactor: refactor bootstrap to take the 'config' and 'providers' as …
Browse files Browse the repository at this point in the history
…arguments

Pass the 'config' object and 'providers' array as arguments to the application bootstrap
(src/bootstrap/index.js file) and have the boostrap inject the config into each provider's
constructor
  • Loading branch information
simplymichael committed Jun 14, 2024
1 parent 7166b3e commit 64a2db9
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 5 deletions.
3 changes: 2 additions & 1 deletion src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const express = require("express");
const cookieParser = require("cookie-parser");
const createError = require("http-errors");
const bootstrap = require("./bootstrap");
const providers = require("./bootstrap/providers");
const config = require("./config");
const container = require("./framework/component/container");
const { StatusCodes, StatusTexts } = require("./framework/component/http");
Expand Down Expand Up @@ -40,7 +41,7 @@ module.exports = function createApp({ webRouter, apiRouter }) {
* This way, any registered services are available to route handlers
* (via req.app.resolve(serviceName)) and other files.
*/
bootstrap();
bootstrap(config, providers);

if(typeof webRouter !== "function" && typeof apiRouter !== "function") {
throw new Error(
Expand Down
22 changes: 18 additions & 4 deletions src/bootstrap/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
const providers = require("./providers");

module.exports = function setupServices() {
module.exports = function setupServices(config, providers) {
for(let i = 0; i < providers.length; i++) {
const Provider = providers[i];
const provider = new Provider();

if(typeof Provider !== "function") {
throw new TypeError(
"A Service Provider must be a class or constructor function. " +
`Service Provider ${Provider} is a ${typeof Provider}.`
);
}

const provider = new Provider(config);
const className = Object.getPrototypeOf(provider)?.name ?? Provider.name;

if(typeof provider.register !== "function") {
throw new TypeError(
"Service providers must define a 'register()' method. " +
`Service Provider '${className}' has no 'register()' method defined.`
);
}

/*
* Bind the dependencies of the service(s) that the provider provides
Expand Down
68 changes: 68 additions & 0 deletions src/bootstrap/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* eslint-env node, mocha */

const { chai } = require("../lib/test-helper");
const bootstrap = require(".");

let expect;


module.exports = {
bootstrap() {
describe("bootstrap(config, providers)", function() {
before(async function() {
expect = (await chai()).expect;
});

it("should throw if a provider is neither a constructor nor a class", function() {
const providers = [ { register() {} } ];

expect(() => bootstrap({}, providers)).to.throw(/A Service Provider must be a class or constructor function/);
});

it("should throw if a provider has no register method defined", function() {
const providers = [ function TestServiceProvider() {} ];

expect(() => bootstrap({}, providers)).to.throw(
"Service providers must define a 'register()' method. " +
"Service Provider 'TestServiceProvider' has no 'register()' method defined."
);
});

it("should invoke the 'register()' method of every passed provider", function() {
let className;
let funcName;
let protoFuncName;

class ClassServiceProvider {
register() { className = "ClassServiceProvider"; }
}

function FunctionServiceProvider() {
this.register = function register() {
funcName = "FunctionServiceProvider";
};
}

function ProtoFunctionServiceProvider() {}

ProtoFunctionServiceProvider.prototype.register = function register() {
protoFuncName = "PrototypeInheritedRegisterMethod";
};

expect(className).to.be.undefined;
expect(funcName).to.be.undefined;
expect(protoFuncName).to.be.undefined;

bootstrap({}, [
ClassServiceProvider,
FunctionServiceProvider,
ProtoFunctionServiceProvider
]);

expect(className).to.equal("ClassServiceProvider");
expect(funcName).to.equal("FunctionServiceProvider");
expect(protoFuncName).to.equal("PrototypeInheritedRegisterMethod");
});
});
}
};

0 comments on commit 64a2db9

Please sign in to comment.