我正在使用 GraphQL 并且有一个如下所示的resolvers.js文件:
const User = require("../models/User");
const Post = require("../models/Post");
module.exports = {
Query: {
async users(){...},
async user(){...},
async posts(){...},
async post(){...},
},
User: {...},
Post: {...},
Mutation: {
createUser(){...},
login(){...},
createPost(){...},
},
}
Run Code Online (Sandbox Code Playgroud)
但是如果我有更多的模型、查询和突变,文件会很长。如何将其拆分为单独的文件?一种用于用户查询和突变,一种用于帖子等。或者那是不可能的?也许有一种方法可以将它与schema.js文件结合起来?这样我也可以拆分架构并将架构/解析器从 User 放入一个文件中。我仍然是编码的初学者。
我在前端使用带有 vue-apollo 的 Vue,在后端使用带有 mongodb 的 graphql 独立 Apollo Server 2。我有一个简单的博客应用程序,其中的帖子也有一个图像。除了上传图像外,一切正常。我希望将图像上传到我后端文件夹中的本地文件系统,并且只有保存在我的 mongodb 文档中的图像的路径。
突变:
async createPost(parent, args, context, info) {
//...
const {stream, filename} = await args.img
const img_path = await upload({stream, filename})
const post = await Post.save({
//img is a string in my mongo model
img: img_path,
author_name: args.user.username,
author_email: args.user.email
});
}
Run Code Online (Sandbox Code Playgroud)
应该返回路径并将图像保存到本地的上传方法:
const upload = ({ stream, filename }) => {
const id = shortid.generate()
const path = `${UPLOAD_DIR}/${filename}-${id}`
new Promise((resolve, reject) =>
stream
.pipe(fs.createWriteStream(filename))
.on("finish", () …Run Code Online (Sandbox Code Playgroud) 我正在寻找一种访问查询参数(对象)的子字段而不将其作为单独参数传递的方法。这是详细的案例,它解释了为什么我需要这个。我有以下架构:
type Query {
users(input: getUsersInput!):[User]
}
type User {
_id: ID!
name: String!
isAdmin(platformId: ID!)
}
type getUsersInput {
platformId: ID!
search: String
#...some other query params
}
Run Code Online (Sandbox Code Playgroud)
所以现在我想查询特定平台的用户并检查他们是否是管理员。类似的东西:
query getUsers($input: getUsersInput!) {
users(input: $input) {
_id
name
isAdmin(platformId: $input.platformId)
}
}
Run Code Online (Sandbox Code Playgroud)
但是,引用 platformId$input.platformId会出现错误。
我可以将 platformId 作为额外参数传递到查询中,但我想避免。我想解决方案可能有几个方向:
很乐意就此获得任何帮助和想法。
我正在尝试为我正在处理的项目设置 Apollo 后端,我正在尝试实现模式指令。但是,我无法将我的架构指令添加到突变中。所以我的主要问题是:如何为突变实现 auth 指令?
我已经添加@auth(requires: ADMIN)到我的用户查询的末尾,这工作正常。然后,Apollo 将需要一个具有管理员访问权限的不记名令牌来执行用户查询。
extend type Query {
user(id: ID!): User
users: [User!]! @auth(requires: ADMIN)
}
Run Code Online (Sandbox Code Playgroud)
当我尝试以相同的方式对 editMyUser 突变执行此操作时,似乎对所有突变强制执行 auth 指令,而不仅仅是我想要的突变。当我将 @auth 部分添加到 editMyUser 突变时,即使 signUp 突变也会给出“未授权”错误。尽管他们之间没有任何关系。
调用时应该传递给 auth 指令的角色字段注销为空。
extend type Mutation {
signUp(
username: String!
firstName: String
lastName: String
password: String!
isAdmin: Boolean
isActive: Boolean): User!
login(
username: String!
password: String!): User!
editMyUser(
id: ID!
firstName: String
lastName: String
password: String): User! @auth(requires: USER)
adminEditUser(
id: ID!
firstName: String
lastName: String
password: …Run Code Online (Sandbox Code Playgroud) 按照Nextjs 存储库中的这个示例,我想实现 CSRF 保护(可能使用csurf包),因为我使用带有 express-session 的会话 ID cookie。
我尝试在我的自定义服务器中设置 csurf 并将生成的令牌保存在 res.locals.csrfToken 中,可以在第一页加载时通过位于 /lib/withApollo.js 中的静态方法“getInitialProps”获取我的示例链接。一旦我尝试更改页面(带有链接)或尝试使用 apollo 发出发布请求(例如登录),服务器就会更改 csrf 令牌,因此 Apollo 使用的令牌不再有用,所以我得到了“csrf 无效”错误。
带有 csurf 配置的自定义服务器
const csrf = require('csurf');
const csrfProtection = csrf();
////express-session configuration code////
app.use(csrfProtection);
app.use((req, res, next) => {
res.locals.csrfToken = req.csrfToken();
next();
})
Run Code Online (Sandbox Code Playgroud)
/lib/initApollo.js
function create(initialState, { getToken, cookies, csrfToken }) {
const httpLink = createHttpLink({
uri: "http://localhost:3000/graphql",
credentials: "include"
});
const authLink = setContext((_, { headers }) => {
const token …Run Code Online (Sandbox Code Playgroud) const {
DEVELOPMENT_SERVER,
PRODUCTION_BUILD
} = require("next/constants");
require('dotenv').config()
const path = require('path')
const Dotenv = require('dotenv-webpack')
const nextConfig = {
webpack: config => ({ ...config, node: { fs: "empty" } })
};
module.exports = phase => {
if (phase === DEVELOPMENT_SERVER || phase === PRODUCTION_BUILD) {
const withCSS = require("@zeit/next-css");
return withCSS(nextConfig);
}
return nextConfig;
};
*module.exports = {
webpack: (config) => {
config.plugins = config.plugins || []
config.plugins = [
...config.plugins,
// Read the .env file
new Dotenv({
path: …Run Code Online (Sandbox Code Playgroud)Apollo 查询在我的 React 应用程序中缓存了错误的数据。
如果我将查询的 fetchPolicy 设置为“仅网络”,则一切正常。
所以我认为这是一个缓存问题。
一直在努力解决问题,看到了关于apollo cache的文章,还是解决不了问题。
以下是我查询后的结果:
参数 memberId 为空(结果正确)
[
{
"id": 87,
"totalQuantity": 12,
"Orders": [
{
"id": 1,
"quantity": 11,
"Member": {
"id": 1,
"name": "A"
}
},
{
"id": 28,
"quantity": 1,
"Member": {
"id": 9,
"name": "B"
}
}
]
},
{
"id": 88,
"totalQuantity": 1,
"Orders": [
{
"id": 2,
"quantity": 1,
"Member": {
"id": 1,
"name": "A"
}
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
参数 memberId 为 9(结果正确)
[
{
"id": …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 React 在 Apollo Client 中进行查询而不返回 JSX 组件,只是一个对象(data向 Apollo Server 进行常见查询时收到的对象)。
我尝试使用<Query />组件,但它返回一个 React 节点,我只需要一个对象。该文档仅解释了在某些时候返回 JSX 组件的方法,当我要做的只是发送请求并在回调中处理响应时。
实际上我正在尝试这种方式(我在 React 中使用 TypeScript):
import React from 'react';
import { withApollo } from 'react-apollo';
import gql from 'graphql-tag';
const MY_QUERY = gql`
query MY_QUERY {
myQuery {
attr1
attr2
}
}
`;
const res = ({ client }: { client: any }) =>
client
.query(MY_QUERY)
.then((data: { data: any }) => data);
withApollo(res);
console.log(res);
Run Code Online (Sandbox Code Playgroud)
有了这个,我正在寻找一个像
{
"data": {
"myQuery": …Run Code Online (Sandbox Code Playgroud) 我想用 Apollo Client 读取响应头,但我不能。
我正在使用 Apollo 服务器和 Apollo 客户端进行 GraphQL API 通信,并且我想来回发送标头。我已经设置了客户端,以便它发送一个 x-client-version 标头,并且我已经将服务器设置为有时也使用相同的标头进行回复。
问题是,当我尝试使用 Apollo 客户端读取 x-client-version 标头(或任何真正的标头)时,我得到未定义。我根据我在网上找到的示例甚至 YouTube 演练在下面设置了一些 Afterware:
const clientVersionAfterware = new ApolloLink((operation, forward) =>
forward(operation).map(response => {
const {
response: { headers },
} = operation.getContext();
console.log(headers);
if (headers) {
const token = headers.get("x-client-version");
console.log(token);
if (token) {
localStorage.setItem("clientVersion", token);
}
}
return response;
}),
);
Run Code Online (Sandbox Code Playgroud)
将其附加到链接链:
const httpLink = handleErrors.concat(
clientVersionAfterware.concat(new HttpLink(linkOptions)),
);
const batchHttpLink = handleErrors.concat(
clientVersionAfterware.concat(
new BatchHttpLink({ ...linkOptions, batchInterval: 10 }), …Run Code Online (Sandbox Code Playgroud) 我正在使用 Apollo 与用 React 编写的 Web 应用程序中的 GraphQL 服务器进行交互。我正在尝试在应用程序中实现错误处理并为此依赖apollo-link-error。
现在,我需要处理两类错误:
显然,一旦错误被本地处理我需要它不会在全球范围内处理,因为它并没有多大意义,显示错误消息旁边的一个表单字段和通过举杯消息一般错误。
我在尝试实现这个时遇到的第一个绊脚石是全局错误处理逻辑在本地错误处理逻辑之前触发,这使我无法在本地拦截错误,然后找到防止全局逻辑踢进来的方法.
我创建了 Codesandbox 示例,它ApolloClient以最简单的方式设置一个,使用 http 和错误链接,并使用该react-apollo Query组件对不存在的资源进行查询,从而产生错误。
我onError在Query组件的回调(因此是本地错误处理)和apollo-link-error处理程序(因此是全局错误处理)中处理错误,并将错误打印到控制台。
它表明全局错误处理逻辑在局部错误处理之前启动。我需要它是相反的。