I am working on a prototype with a goal to write a webservice with the express framework in TypeScript, compile it to TS and host it in a firebase functions environment. The code layers in the service is a Controller layer and for now, also a business logic layer for the business rules. Perhaps mostly the same layers seen in a .Net written webservice. With dependency injection using the inversifyJS framework I inject the logic class into the controller.
Here parts of the TypeScript code so far:
@injectable()
export class Service1Controller extends ApiController implements IService1Controller {
public constructor(
@inject(TYPES.IService1Logic)
private service1Logic: IService1Logic
) { super() }
private fastGet(request: Request, response: Response) {
const original = request.query.text;
const changed = this.service1Logic.UpdateFastGet(original);
response.status(200).send(changed);
}
}
export interface IService1Logic {
UpdateFastGet(text: string): string;
}
@injectable()
export class Service1Logic implements IService1Logic {
UpdateFastGet(text: string): string {
console.log(`[Service1Logic/UpdateFastGet]: ${text}`);
text = `${text} -> service1[fastget]`;
return text;
}
}
And this is (partly) the compile output of the Controller code
constructor(service1Logic) {
super();
this.service1Logic = service1Logic;
}
fastGet(request, response) {
const original = request.query.text;
const changed = this.service1Logic.UpdateFastGet(original);
response.status(200).send(changed);
}
When testing the code locally using the firebase functions emulator I get an error that property service1Logic cannot be read from undefined. So it seems this is undefined and I cannot figure out why.
I also tried to isolate the error and to reproduce it with the next code:
@injectable()
export class Class1 extends baseClass implements Interface1 {
constructor(
@inject(TYPES.Interface2)
private class2: Interface2
) { super() }
PrintText(text: string): void {
const mutatedText: string = this.class2.MutateText(text);
console.log(mutatedText);
}
Addition(x: number, y: number): number {
return this.Sum(x, y);
}
}
export interface Interface2 {
MutateText(text: string): string;
}
@injectable()
export class Class2 implements Interface2 {
MutateText(text: string): string {
console.log(`Received text ${text}`);
return `${text} mutated`;
}
}
The controller compiled code looks almost the same (with exception of the naming ofcourse)
let Class1 = class Class1 extends baseclass_1.baseClass {
constructor(class2) {
super();
this.class2 = class2;
}
PrintText(text) {
const mutatedText = this.class2.MutateText(text);
console.log(mutatedText);
}
Addition(x, y) {
return this.Sum(x, y);
}
};
When I run this code (not in an emulator but with node) I get no errors at all, it seems that this in PrintText does exists. I also copied the tsconfig.json content from the original project to the project where I try to isolate the error, perhaps it got to do with a setting there but that wasn't the case either as far as I can see. I am stuck on the error and I cannot figure out what is causing the error. Has anyone had this kind of issue or knows how I can solve this?
Edit: Added the calling code
For the prototype code, the methods are linked to a route.
app.get('/fastget', this.fastGet);
App is of type Express:
this.app = express();
and app is returned via a getter in the ApiController and is then added to the onRequest of firebase:
const service1Controller: IService1Controller = container.get<IService1Controller>(TYPES.IService1Controller);
export const service1 = functionsEUWest1.https.onRequest(service1Controller.App);
And these are the Types and container objects:
Types.ts
let TYPES = {
//Controllers
IService1Controller: Symbol("IService1Controller"),
//BusinessLogics
IService1Logic: Symbol("IService1Logic")
}
export default TYPES;
inversify.config.ts
class ContainerConfig {
private _container: Container = new Container;
get Container() { return this._container };
private configureControllers(container: Container) {
container.bind(TYPES.IService1Controller).to(Service1Controller);
}
private configureBusinessLogics(container: Container) {
container.bind(TYPES.IService1Logic).to(Service1Logic);
}
constructor() {
this.configureControllers(this._container);
this.configureBusinessLogics(this._container);
}
}
export default new ContainerConfig().Container;
For the code to isolate the error, this is the calling code:
const class1: Interface1 = container.get<Interface1>(TYPES.Interface1);
class1.PrintText("This text is");
const result = class1.Addition(2, 3);
console.log(`Sum of 2 and 3 is ${result}`);
This is how the TYPES and the container objects and the looks like:
Types.ts
let TYPES = {
Interface1: Symbol("Interface1"),
Interface2: Symbol("Interface2")
}
export default TYPES;
intensify.config.ts
const container = new Container();
container.bind(TYPES.Interface1).to(Class1);
container.bind(TYPES.Interface2).to(Class2);
export default container;