Skip to content

Confusing issue with resolving class if module is called from separate module  #262

Closed
@tenowg

Description

@tenowg

Maybe you can help me resolve this issue. This is likely behavior that I didn't account for in my code.

var k: i.Kernel = new Kernel();
export var pInject = makePropertyInjectDecorator(k);

k.bind<DefaultOptions>(DefaultOptions).toConstantValue(new DefaultOptions());
k.bind<RouteBuilder>(RouteBuilder).to(RouteBuilder).inSingletonScope().onActivation((context, router) => {
    router.kernelInstance = k;
    return router;
});
k.bind<ExpressMvc>(ExpressMvc).to(ExpressMvc).onActivation((context, expressify) => {
    expressify.kernel = k;
    return expressify;
});

/**
 * The main function called to create a ExpressMvc object, initialized the DI and returns a useable ExpressMvc object
 *
 * @param {...mvcController} ...controllers The list of controllers to add to DI, all controllers used are required.
 * @return {ExpressMvc}
 */
export function expressMvc(...controllers: any[]): ExpressMvc {
    debug("Starting ExpressMVC");
    // Handle registering Controllers
    controllers.forEach(controller => {
        debug(`Binding controller (${controller.name})`);
        k.bind<mvcController>(controller).to(controller);
        debug(`Bound controller (${controller.name})`);
    });
    debug('Finished binding controllers...');
    return k.get<ExpressMvc>(ExpressMvc);
}

export function getRouter(): RouteBuilder {
    return k.get<RouteBuilder>(RouteBuilder);
}

When this code is called from identical code from within the module, it works without an issue, when I seperate the test code (just a simple module that is supposed to run the server) the getRouter() function will error with `Missing required @Injectable annotation in: RouteBuilder.

The getRouter() is used in functions as such:

/**
 * route is optional, if not supplied will use a slug-case case of the function name as route
 */
export function HttpGet(options?: {
        route?: string,
        parameters?: string
    }) {
    return (target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) => {
        if (!options || !options.route) {
            options = options || {};
            options.route = "/" + require('to-slug-case')(propertyKey);
        }

        getRouter().registerHandler(AllowedMethods.GET, options.route, target, propertyKey, options.parameters || "");     
    }
}

which are annotations on methods in controller classes.

The main code that is run to start the application is:

import {expressMvc} from "@demgel/mvc";
import {TestController} from "./controllers/testController";
import {TestService} from "./services/testService";

let server = expressMvc(TestController);
server.addTransient<TestService>(TestService, TestService);
server.setViewEngine("../../views", 'pug');
// server.setFavicon('');
server.listen(3000);

If this is in the @demgel/mvc module it will work When I separate this code to a new module, I get the error.

additionaly, if I remove any controllers from the startup, RouteBuilder is injected into ExpressMvc when it is resolved at the end of the expressMvc function.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions