jeffijoe / awilix-express

Awilix helpers/middleware for Express
MIT License
118 stars 7 forks source link

Injecting dependencies per route instead of when creating controller #17

Closed AndreasWJ closed 5 years ago

AndreasWJ commented 5 years ago

Hi! Love the work you guys have done. Although, I'm having a problem related to registrering certain tokens through middlewares, and then injecting dependencies dependent of these tokens within my controllers. I've looked through awilix and awilix-express documentation and issues, yet I can't find any help regarding the issue I'm facing.

To give you an example, here's my controller:

const InventoryController = {
    get router() {
        const public = Router();
        const controller = makeInvoker(this.makeController);

        public.patch('/:type/route1', controller('function1'));
                public.patch('/route2', controller('function2'));

        return { public };
    },

    makeController({ addToSiteInventory, getInventory }) {
        return {
                          function1: async (req, res) => {
                ...

                try {
                    const addedItems = await addToSiteInventory.execute(...);
                    res
                        .status(Status.CREATED)
                        .json({ status: 'success', data: addedItems });
                } catch (error) {
                    console.log('Error', error);
                }
            },

            function2: async (req, res) => {
                ...

                try {
                    const inventory = await getInventory.execute(...);

                    res
                        .status(Status.OK)
                        .json({ status: 'success', data: inventory });
                } catch (error) {
                    console.log('Error', error);
                }
            },
        };
    }
};

module.exports = InventoryController;

Now, I have a couple of middlewares which uses the request's scope to register tokens. In one of my middlewares I register a token called 'type'. Which in this simplified example is a route parameter.

Okay. So the problem is that my usecases, the injected dependencies in my controller; addToSiteInventory and getInventory either rely themselves on 'type' or not. getInventory is a usecase that injects 'type'.

However, when I send a request to route2 I get something along the lines of "Can't inject getInventory, 'token' isn't registered". This is due to my middleware not registering 'token', and it's not suppose to for route2.

My question is, is there anyway to have route-specific injections? In that case I can inject each usecase for each route. Instead of injecting all usecases in my controller which leads to the aforementioned problem. I've tried public.patch('/:type/route1', inject('getInventory') controller('function1')); But with that attempt I get something along the lines of "Can't build of undefined".

jeffijoe commented 5 years ago

So to confirm, you want to depend on type without having registered it?

You can only do this with classic injection mode and default params, otherwise you can register type as null always, then have your route middleware overwrite it.

AndreasWJ commented 5 years ago

Thanks for the response! I tried implementing my usecase classes with classic injection mode. But what exactly do you mean with "default parameters"? I know Javascript puts undefined in arguments not defined, but Awilix still tries to resolve the tokens which leads to "AwilixResolutionError: Could not resolve 'type'." even when type is a standalone argument with the classic mode.

I've also tried replacing the object destructuring in the constructor to a single big object, but yet again I get AwilixResolutionError.

Replacing with nulls is another approach, but I feel it's more of a workaround IMO.

jeffijoe commented 5 years ago

Default params as in myFunc(param = defaultValue) - awilix’ parser will then know not to require that param to be registered.

It’s not a workaround, it’s a fair way to do it. 😀

AndreasWJ commented 5 years ago

Works perfectly! Thanks!