所以你有选择。这里有 2 个选择:
1。只需添加您的数据源
如果你只是初始化所有数据源,它可以在内部检查用户是否有访问权限。您可以有一个 getClient 函数在客户端上解析或抛出 UnauthorizedError,具体取决于。
2。不要只添加数据源
所以如果你真的根本不想初始化数据源,你完全可以通过自己添加“数据源”来做到这一点,就像 Apollo 一样。
const server = new ApolloServer({
// this example uses apollo-server-express
context: async ({ req, res }) => {
const accessToken = req.headers?.authorization?.split(' ')[1] || ''
const user = accessToken && buildUser(accessToken)
const context = { user }
// You can't use the name "dataSources" in your config because ApolloServer will puke, so I called them "services"
await addServices(context)
return context
}
})
const addServices = async (context) => {
const { user } = context;
const services = {
userAPI: new UserAPI(),
postAPI: new PostAPI(),
}
if (user.isAdmin) {
services.adminAPI = new AdminAPI()
}
const initializers = [];
for (const service of Object.values(services)) {
if (service.initialize) {
initializers.push(
service.initialize({
context,
cache: null, // or add your own cache
})
);
}
}
await Promise.all(initializers);
/**
* this is where you have to deviate from Apollo.
* You can't use the name "dataSources" in your config because ApolloServer will puke
* with the error 'Please use the dataSources config option instead of putting dataSources on the context yourself.'
*/
context.services = services;
}
一些注意事项:
1。你不能称它们为“数据源”
如果您在上下文对象上返回一个名为“dataSources”的属性,Apollo 将不会非常喜欢它 [meaning it throws an Error]。在我的示例中,我使用了名称“服务”,但您可以为所欲为……除了“数据源”。
使用上面的代码,在您的解析器中,只需引用 context.services.whatever。
2。这就是阿波罗所做的
此模式直接复制自 Apollo 已经为数据源所做的工作 [source]
3。我建议您仍然将它们视为数据源
我建议您坚持 DataSources 模式,并且您的“服务”都扩展 DataSource。参与的每个人都会变得更容易。
4。类型安全
如果您使用 TypeScript 或其他东西,您将失去一点类型安全性,因为 context.services 要么是一种形状,要么是另一种形状。即使你不是,如果你不小心,你最终可能会抛出“无法读取未定义的属性用户”错误而不是“未经授权”错误。您最好创建反映相同对象形状但只是抛出未经授权的“虚拟服务”。