Type-graphql: How to work with InversifyJS Container?

Created on 30 Jul 2019  路  9Comments  路  Source: MichalLytek/type-graphql

Hello. Thank you for your awesome library.

There is my problem. I'm trying to use InversifyJS library (https://github.com/inversify/InversifyJS) for implementation DI principle. There is my code:

User Resolver file

import { Resolver, Query, Arg } from 'type-graphql';
import { inject } from 'inversify';

import { User } from '../type-defs';
import { IUserService } from '../interfaces';
import { TYPES } from '../services';

@Resolver(_of => User)
class UserResolver {
  private userService: IUserService;

  public constructor(@inject(TYPES.User) userService: IUserService) {
    this.userService = userService;
  }

  @Query(_returns => User, {
    nullable: true,
    description: 'Search and GET a single User by ID',
  })
  public async user(@Arg('id') id: string): Promise<User> {
    const user = await this.userService.getUser();
    if (user === undefined) {
      throw new Error(id);
    }
    return user;
  }
}

export default UserResolver;

inversify.config.ts file

import { Container } from 'inversify';

import TYPES from './types';
import { IUserService } from './interfaces';
import UserService from '../user';

const serviceContainer = new Container();

serviceContainer.bind<IUserService>(TYPES.User).to(UserService);

export default serviceContainer;

Build schema

const schema = await buildSchema({
      resolvers: [UserResolver],
      container: serviceContainer,
      emitSchemaFile: path.resolve(__dirname, 'schema.gql'),
});

If I try to get user in GraphQL Playground, I get error: "Error: No matching bindings found for serviceIdentifier: UserResolver".

I understand that it is problem with Inversify, but maybe you know, why Inversify doesn't work because of resolver. I want inject only service in resolver and bind this service in Inversify Container, but why must I binding resolver too? Thank you for your attention.

Question Solved

Most helpful comment

I'll apologize first since this discussion has been marked as solved, but I feel that this might contribute to others asking.

I don't know if I'm breaking the rules by commenting here, but the way to do this using inversify would be:

serviceContainer.bind<IUserResolver>(TYPES.UserResolver).toSelf()

Like @19majkel94 said, TypeGraphQL doesn't know about types, but if you bind the class to itself, the engine can use the container.get method.

All 9 comments

why must I binding resolver too? Thank you for your attention.

Because you need to create an instance of the resolver class to be able to use this inside the method. So TypeGraphQL calls container.getInstance(UserResolver), not new UserResolver(), so your container can resolve dependencies.

Thank you for your answer.

But I don't understand, how can I create an instance on the resolver class? It has a "userService: IUserService" argument in constructor, so, if I want to create an instance using "new" operator, I must provide to constructor an instance of UserService, but UserService should be injected using Container. What wrong in my understanding?

Note: In this example, I don't see any instances of the resolvers - the resolvers provides in "buildSchema" method as classes, not as instances.

Sorry, wrong tense/grammar - TypeGraphQL needs an instance of the resolver class to be able to use this inside the methods. That's why you need to bind the resolver class too.

Ok, I've understood this moment.

So, if I want to binding my resolver class, I should write the next code in "inversify.config.js":

serviceContainer.bind<IUserResolver>(TYPES.UserResolver).to(UserResolver);

Is it right?

No, TypeGraphQL calls container.get(UserResolver), it doesn't know anything about TYPES.

container.bind<UserResolver>(UserResolver).toSelf();

Ok, there is new Error: "Error: NULL argument". So, I think that I should read all documentation of InversifyJS, because I don't know what this error mean. Or maybe you know about this problem too? I'm sorry, that I ask a questions about Inversify, not about TypeGraphQL.

Sorry, I don't use Inversify so I can't help you. Please ask on stack overflow or somewhere.

I'll apologize first since this discussion has been marked as solved, but I feel that this might contribute to others asking.

I don't know if I'm breaking the rules by commenting here, but the way to do this using inversify would be:

serviceContainer.bind<IUserResolver>(TYPES.UserResolver).toSelf()

Like @19majkel94 said, TypeGraphQL doesn't know about types, but if you bind the class to itself, the engine can use the container.get method.

@dzfranco I totally agree, it works well. Thanks.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

memark picture memark  路  3Comments

robertchung97 picture robertchung97  路  3Comments

MichalLytek picture MichalLytek  路  3Comments

Asim13se picture Asim13se  路  3Comments

MichalLytek picture MichalLytek  路  4Comments