Tsed: [FEAT] GraphQL - Add dataSources population similar to resolvers so that they can use DI

Created on 22 Jun 2019  路  9Comments  路  Source: tsedio/tsed

add a @ApolloDataSource() attribute similar to the @ResolverService() attribute that can register all dataSources with the DI. Then in GraphQLService can merge them in using a similar method as resolvers.

please and thank you :)

enhancement released

Most helpful comment

Hi, once you have the datasource in the context you could use it like this:

@ResolverService(User)
export class UserResolver {
    @Authorized()
    @Query(() => User)
    public async user(
        @Arg('userId') userId: string,
        @Ctx('dataSources') dataSources,
    ): Promise<User> {
        const userDataSource = dataSources.userDataSource as UserDataSource;
        return userDataSource.getUserById(userId);
    }
}

assuming you have a datasource class like

import { RESTDataSource } from 'apollo-datasource-rest';

@DataSourceService()
export class UserDataSource extends RESTDataSource {
  constructor() {
    super();
    this.baseURL = 'https://myapi.com/api/users';
  }

  getUserById(id: string): Promise<User> {
    return this.get(`/${id}`);
  }
}

All 9 comments

Hello @bsparks
Can you give me more details to implement @ApolloDataSource() (I prefere @DataSource()) (a link to the official documentation would be great).

Question: DataSource are always a class ?

Here some links of decorators and services:

Decorator:
https://github.com/TypedProject/ts-express-decorators/blob/master/packages/graphql/src/decorators/resolverService.ts

Registry:
https://github.com/TypedProject/ts-express-decorators/blob/master/packages/graphql/src/registries/ResolverServiceRegistry.ts

And the resolvers registration to Apollo:
https://github.com/TypedProject/ts-express-decorators/blob/master/packages/graphql/src/services/GraphQLService.ts#L51

If you want to contribute to this PR the steps are:

  • Copy decorator resolverService and rename it by dataSource.ts => @DataSource
  • Create a new registry by copying ResolverServiceRegistry and rename it by DataSourceRegistry
  • Create in GraphQLService a new method getDataSource (is the same as getResolvers) and use it GraphQLService.createServer to register dataSource according to the official Apollo documentation :)

I can help you to implement unit test :)

See you,
Romain

Hi,
So the dataSources documentation is here: https://www.apollographql.com/docs/apollo-server/features/data-sources/#accessing-data-sources-from-resolvers

They are subclasses from the abstract class of Apollo: https://github.com/apollographql/apollo-server/blob/master/packages/apollo-datasource/src/index.ts

During the apollo request pipeline it goes through each in the dataSources server config and calls the initialize method and adds them to the context: https://github.com/apollographql/apollo-server/blob/5d4b7906d9371d323281cbfde8ba22a19173df54/packages/apollo-server-core/src/requestPipeline.ts#L574

They have to be added at the beginning during configuration.
I have currently got around this by setting up my own "GraphQlModule" (custom) and in $onInit calling graphQlService.createServer myself so that I can inject my DataSource services into that service and add them to the configuration.

The steps that you laid out are basically what I thought should happen. I'll see what I can do to create the PR myself. Thanks :)

Hello @bsparks
Any update ? If I can help you, tell me :)

sorry, there was a holiday week here in US and got distracted at work after... :)

so I'm not super familiar with how to do the monorepo stuff.
or how to actually test it (npm link?) so it's all just theory sort of... hehe
I did run yarn test and made sure those worked again
gflow also just hung (never used that before) so I just created a branch manually

I guess I would need some help with those things.

Hello @bsparks
The project and subpackages are automatically installed with npm install. You just have to run npm test :)

Gflow isn't required to manage or create a branch. In fact, Gflow run npm test and git rebase origin/production before pushing the branch on github. You can doing that manually :)

I'll change the contributing.md to explain that :)

See you
Romain

@bsparks The contributing guide is up to date :). I'll fix coverage on your PR

See you
Romain

@bsparks Can you give more detail about how to use datasource with Ts.ED. it try to write documentation ;)

How I can use the declared dataSource in a resolver or from a context ?

See you,
Romain

Hi, once you have the datasource in the context you could use it like this:

@ResolverService(User)
export class UserResolver {
    @Authorized()
    @Query(() => User)
    public async user(
        @Arg('userId') userId: string,
        @Ctx('dataSources') dataSources,
    ): Promise<User> {
        const userDataSource = dataSources.userDataSource as UserDataSource;
        return userDataSource.getUserById(userId);
    }
}

assuming you have a datasource class like

import { RESTDataSource } from 'apollo-datasource-rest';

@DataSourceService()
export class UserDataSource extends RESTDataSource {
  constructor() {
    super();
    this.baseURL = 'https://myapi.com/api/users';
  }

  getUserById(id: string): Promise<User> {
    return this.get(`/${id}`);
  }
}

Hooo nice, I'll complete the documentation ;)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

haroon407 picture haroon407  路  4Comments

royibernthal picture royibernthal  路  3Comments

royibernthal picture royibernthal  路  4Comments

OskarLebuda picture OskarLebuda  路  4Comments

thanhchuongitc picture thanhchuongitc  路  6Comments