typescript - NestJS GraphQL 数据源

标签 typescript graphql apollo-server nestjs

警告以下代码是不正确的数据源,需要根据请求创建。

请勿使用以下代码

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

我能够通过让 NestJS 实例化单例数据源然后使用 GraphQLModule.forRootAsync 将这些实例注入(inject) 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]

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

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

最佳答案

RESTDataSource 看起来只是一个普通的类。您应该能够简单地应用 @Injectable() 装饰器并将它们视为常规 Nest 服务。这将允许您将依赖项注入(inject)到它们中,并将数据源注入(inject)到您的解析器中,而无需像您所展示的那样在 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-y 的方式实现这一点。这不是目前记录良好的内容,但您可以查看一些 Nest 源代码中的示例,了解如何完成此操作。 For reference here's the code that discovers all of the @Resolver decorated classes for the GraphQL module .

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

我认为您现在拥有的不一定是大问题,但如果您以这种方式实现它,您就不必担心每次都要记住添加新的数据源。

关于typescript - NestJS GraphQL 数据源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54517872/

相关文章:

graphql - GitHub API 是否为架构查询返回无效结果?

node.js - graphql + apollo-server-express,如何处理 express authMiddleware 中的身份验证错误?

graphql - 自动重新加载网关以在联合服务 apollo GraphQL 中更改架构

javascript - 循环遍历html元素中的子元素

javascript - 来自另一个组件的 Angular2 调用函数

asp.net-mvc - NullInjectorError : No provider for HttpClient! Angular 5

typescript - 使用 webpack 和 babel-loader 进行转译时,TypeGraphQL @Arg 装饰器失败并出现解析器错误

javascript - Angular OnPush 更改检测传播到 ngFor 循环中的子组件

react-native - 调用一次后重置 useLazyQuery

javascript - GraphQL+ react + Apollo :Unable to fetch data from server to client