I am looking for a way to load my controller classes in Inversify that are annotated with @controller()
from inversify-express-utils
without needing to manage a hand crafted/manually constructed module of imports/exports.
All of the examples I am seeing seem to indicate that in your entry file you need to import each of your controllers explicitely so that inversify-express-utils
picks up on the @controller
annotations, however this feels like it would be rather tedious for applications of a medium to large size.
In plain JavaScript I would do something like recursively require each file in a directory at runtime, however I understand that due to the way TypeScript works, this isn't exactly possible?
Using the inversify-binding-decorators
package, I am able to simply annotate a service with @provide()
and that seems to be enough to have the class added to the IOC container, however that does not seem to be enough for inversify-express-utils
to discover the @controller()
annotations on the class.
Is there a way to achieve auto discovery of these @controller()
annotated classes without manually importing them into a entry file?
/services/StarwarsNamesService.ts
import { provide } from 'inversify-binding-decorators';
import * as names from 'starwars-names';
import * as matchSorter from 'match-sorter';
@provide(StarwarsNamesService)
export default class StarwarsNamesService {
public getNames(): Array<string> {
return names.all;
}
public getRandomNames(count?: number): Array<string> {
if (!count) { count = 1; }
return names.random(count);
}
public searchNames(term?: string): Array<string> {
return matchSorter(this.getNames(), term);
}
}
/controllers/StarWarsNamesController.ts
import { inject } from 'inversify';
import { controller, httpGet } from 'inversify-express-utils';
import StarwarsNamesService from '../../starwars-names/StarwarsNamesService';
@controller('/api/starwars-names')
export default class StarWarsNamesController {
@inject(StarwarsNamesService)
private starwarsNamesService: StarwarsNamesService;
@httpGet('/')
public getAll(): any {
return this.starwarsNamesService.getNames();
}
}
boostrap.ts
import 'reflect-metadata';
import * as express from "express";
import * as path from 'path';
import { InversifyExpressServer } from 'inversify-express-utils';
import { buildProviderModule } from "inversify-binding-decorators";
import { Container } from 'inversify';
// Has to be explicitly imported otherwise is undiscovered
import './controllers/StarwarsNamesController.ts';
let container = new Container();
container.load(buildProviderModule());
let server = new InversifyExpressServer(container);
let serverInstance = server.build();
serverInstance.listen(3000, () => {
console.log('Server started on port 3000 :)');
});
Thrown Error:
E:\..\..\node_modules\inversify-express-utils\lib\utils.js:10
throw new Error(constants_1.NO_CONTROLLERS_FOUND);
^
Error: No controllers have been found! Please ensure that you have register at least one Controller.
at Object.getControllersFromContainer
...
You can do the following to expose your controllers
index.js
or index.ts
file in your controller folderexport * from "./your controller file path"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.