警告,下面的代码是不正确的,需要为每个请求创建DATASOURCES。
不使用下面的代码
我试图在apollo-rest-datasource
中使用NestJS。我看到的缺点是DataSources不参与NestJS的DI系统。
通过让NestJS实例化单个数据源,然后使用GraphQLModule.forRootAsync
将这些实例注入到阿波罗服务器的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和阿波罗GraphQL上下文?
发布于 2019-02-04 14:23:31
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模块的提供程序中,如果它们也需要从其他模块中使用,则可以选择导出它们。
更新:,因为dataSources也需要传递到ApolloServer中,所以您可以通过引入自己的装饰器来应用于每个DataSource,然后使用反射来“发现”应用程序中存在的所有源,从而以一种更适合的方式实现这一点。这一点目前还没有很好的文档化,但是您可以从Nest源代码中查看如何实现这一目标的示例。 decorated classes for the GraphQL module。
它基本上可以归结为使用ModulesContainer
和MetadataScanner
来查找应用程序中存在的所有提供程序,然后筛选哪些提供者已经应用了自定义装饰器。(例如,@DataSource()
)。
我不认为您现在拥有的东西一定是一个大问题,但是如果您要以这种方式实现它,您就不必担心每次都要添加新的dataSources。
发布于 2020-07-21 17:35:12
我能够通过在我的每个解析器方法上使用@Context
装饰器来解决这个问题,以便获取数据源。给出一个例子here的完整答案。
https://stackoverflow.com/questions/54517872
复制相似问题