NestJS GraphQL数据源

时间:2019-02-04 14:05:02

标签: typescript graphql apollo-server nestjs

警告以下代码是需要根据请求创建的错误数据源。

请勿使用下面的代码

我正在尝试对NestJS使用apollo-rest-datasource。我看到的缺点是数据源不参与NestJS的DI系统。

通过NestJS实例化单例数据源,然后使用GraphQLModule.forRootAsync将这些实例注入到Apollo Server的dataSources属性中,我可以解决此问题。

 GraphQLModule.forRootAsync({
      imports: [
        DataSourcesModule
      ],
      useFactory: (...args: DataSource[]) => {
        return {
          typePaths: ['./**/*.graphql'],
          context: ({req}: {req: Request}) => ({ token: req.headers.authorization }),
          playground: true,
          dataSources: () => {
            let dataInstances = {} as any;
            args.forEach(arg => {
              const dataSource = arg as any;
              dataInstances[dataSource.constructor.name] = arg;
            });
            return dataInstances;
          },
        };
      },
      inject: [...dataSources]

我现在可以在我的DataSource中使用DI,并且可以在解析器中使用DI来包含我的DataSource实例(而不是从GraphQL上下文进行访问)。虽然这样做有效,但感觉很不对劲。

NestJS的DI和Apollo GraphQL上下文是否有更好的方法?

2 个答案:

答案 0 :(得分:1)

RESTDataSource看起来只是一个普通的类。您应该能够简单地应用@Injectable()装饰器并将其视为常规的Nest服务。这样一来,您就可以将依赖项注入到它们之中,也可以将DataSources注入到您的解析器中,而不必像已经显示的那样在GraphQLModule中自举。

const { RESTDataSource } = require('apollo-datasource-rest');
import { Injectable } from '@nestjs/common';

@Injectable()
class MoviesAPI extends RESTDataSource {
  // Inject whatever Nest dependencies you want
  constructor(private readonly someDependency: SomeDependency) {
    super();
    this.baseURL = 'https://movies-api.example.com/';
  }

  async getMovie(id) {
    return this.get(`movies/${id}`);
  }

  async getMostViewedMovies(limit = 10) {
    const data = await this.get('movies', {
      per_page: limit,
      order_by: 'most_viewed',
    });
    return data.results;
  }
}

@Injectable()
class ResolverClass {
   // Inject your datasources
   constructor(private readonly moviesApi: MoviesAPI) { }
}

您只需要确保将DataSource类放入适当的Nest模块的提供程序中,并在需要从其他模块中使用它们时也可以选择导出它们。

更新: 由于还需要将数据源传递到ApolloServer中,因此您可以通过引入自己的装饰器以应用于每个数据源,然后使用反射来“发现”应用程序中存在的所有源,从而以更嵌套的方式进行此操作。目前尚无很好的文档记录,但是您可以查看一些Nest源代码中的示例以了解如何完成此操作。 For reference here's the code that discovers all of the @Resolver decorated classes for the GraphQL module

它基本上可以归结为使用ModulesContainerMetadataScanner查找应用程序中存在的所有提供程序,然后进行过滤以查找哪些应用了您的自定义装饰器的提供程序。 (例如@DataSource())。

我认为您现在所拥有的并不一定是一个大问题,但是如果您以这种方式实现它,则不必担心每次都记得添加新的dataSources。

答案 1 :(得分:-1)

我能够通过在每个解析器方法上使用@Context装饰器来解决此问题,以获取数据源。带有示例here的完整答案。