thiagobustamante / typescript-ioc

A Lightweight annotation-based dependency injection container for typescript.
MIT License
526 stars 64 forks source link

@InRequestScope not returning the same Instance #63

Open rafaferry opened 4 years ago

rafaferry commented 4 years ago

I'm using typescript-ioc on server side with nodejs and express, and trying to create an object that holds de logged user, that I should be able to access it in any place on my application. To do so, i've created the following class:

@InRequestScope
@OnlyInstantiableByContainer
class LoggedInUserService { ... }

And i've created an express middleware that would extract the logged user from request, and fill it in LoggedInUserService. But it seems that In the same request, or even in the same function, different instances of LoggedInUserService are retrieve from Container.

function extractUser (req:express.Request, resp: express.Response, next:Function): void {
  const auth = req.headers.authorization
  if (auth != null) {
    const token = auth.replace(/bearer /ig, '')
    const jwtToken = jwt.verify(token, config.jwtSecret) as PIJWTToken
    const loggedInUserService = Container.get(LoggedInUserService)
    loggedInUserService.setup(jwtToken.email)
    const LoggedInUserService2 = Container.get(UsuarioLogadoService)

    //the next line is returning false;
    console.log('same instance?', loggedInUserService === loggedInUserService2)
  }
  next()
}

When I use Singleton scope, I do get the same Instance. Do I need to create some configuration for @InRequestScope ? What am I missing?

Thank you

rafaferry commented 4 years ago

Navigating through the types docs, i think i've misunderstood the Request Scope.

I need an HTTP Request scope, but its not clear to me how could I create such scope with the framework. Is it even possible?

I think I would have to create a Build context per HttpRequest, and that it should be in a express middleware function.

Do you have any hint for this?

pballester commented 4 years ago

Same problem here, any help?

Thanks!

rafaferry commented 4 years ago

@pballester sorry for the very late response.

I did this using the new async_hook - AsyncLocalStorage api (node 13+), but I didn't integrate it with typescript-ioc.

The code is something like this:

import { AsyncLocalStorage } from 'async_hooks';

const storage = new AsyncLocalStorage<Map<string, any | undefined>>();

//This must be the first middleware. In any code after this, storage.getStore() will return the same MAP instance.
this._express.use((req: express.Request, resp: express.Response, next: Function) => {
      storage.run(new Map(), () => next());
});
dgocoder commented 4 years ago

Would love to get this working as it just doesn't seem very straight forward. @Singleton works fine but @InRequestScope can't seem to get it to work.