带有 Apollo 数据源的 NestJS

NestJS with Apollo DataSource

我一直在尝试使用 NestJS 重新创建 Apollo tutorial with NestJS. But when I try using apollo-datasource-rest,但在从外部数据源获取数据时失败并出现以下错误:

[Nest] 29974   - 07/14/2020, 9:33:20 PM   [ExceptionsHandler] Cannot read property 'fetch' of undefined +125971ms
TypeError: Cannot read property 'fetch' of undefined

似乎数据源 class 没有被正确地注入到解析器中,但我不明白为什么?

// The data source class
@Injectable()
class LaunchAPI extends RESTDataSource {
  constructor() {
    super();
    this.baseURL = 'https://api.spacexdata.com/v2/';
  }
  async getLaunchById({ launchId }) {
    return await this.get('launches', { flight_number: launchId });
  }
}

// The Nest resolver
@Resolver('launch')
@Injectable()
export class LaunchResolver {
  constructor(private readonly  launchAPI: LaunchAPI) {}

  @Query('getLaunch')
  async getLaunch(
    @Args('id') id: string
  ) {
    return await this.launchAPI.getLaunchById({ launchId: id })
  }
}

// The app module
@Module({
  imports: [
    GraphQLModule.forRoot({
      dataSources,
      context: ({ req }) => {
        if (req) {
          return { headers: req.headers };
        }
      },
      typePaths: ['./**/*.graphql'],
      definitions: {
        path: join(process.cwd(), 'src/graphql.schema.ts'),
        outputAs: 'class',
      },
      debug: true,
    })
  ],
  controllers: [AppController],
  providers: [AppService, LaunchAPI, LaunchResolver],
})
export class AppModule {}

将 Apollo 的数据源与 Nest 解析器一起使用的最佳方式是什么?

我能够通过在我的每个解析器方法上使用 @Context 装饰器来解决问题,以便获取 apollo 数据源服务(例如 dataSources),而不是注入数据解析器 class 中的源代码。所以更新后的内容如下:

// The Nest resolver
@Resolver('launch')
@Injectable()
export class LaunchResolver {
  @Query('getLaunch')
  async getLaunch(
    @Context('dataSources') { launchAPI }: DataSources,
    @Args('id') id: string
  ) {
    return await launchAPI.getLaunchById({ launchId: id })
  }
}

// app.module.ts

// set up any dataSources our resolvers need
const dataSources = () => ({
  launchAPI: new LaunchAPI(),
});

@Module({
  imports: [
    GraphQLModule.forRoot({
      dataSources,
      context: ({ req }) => {
        if (req) {
          return { headers: req.headers };
        }
      },
      typePaths: ['./**/*.graphql'],
      definitions: {
        path: join(process.cwd(), 'src/graphql.schema.ts'),
        outputAs: 'class',
      },
      debug: true,
    })
  ],
  controllers: [AppController],
  providers: [AppService, LaunchAPI, LaunchResolver],
})
export class AppModule {}