Javascript GraphQL:field.resolve()结果在指令中未定义

Javascript GraphQL:field.resolve()结果在指令中未定义,javascript,node.js,graphql,apollo-server,express-graphql,Javascript,Node.js,Graphql,Apollo Server,Express Graphql,我一直在关注我在谷歌上找到的关于如何生成AuthDirective的所有结果,但我无法让它工作 我将保留所有文件,以查看我是否在实现中出错,但我想不会,因为即使在字段中没有任何条件,我也进行了测试。resolve 我发现的一件特别的事情是field.resolve附带了4个参数,其中第一个参数总是未定义的,不确定是否可能是它,但只是作为一个附加提示 下面是代码: 这是我的typedefs的一部分 directive @isAuthenticated on FIELD_DEFINITION sc

我一直在关注我在谷歌上找到的关于如何生成AuthDirective的所有结果,但我无法让它工作

我将保留所有文件,以查看我是否在实现中出错,但我想不会,因为即使在字段中没有任何条件,我也进行了测试。resolve

我发现的一件特别的事情是field.resolve附带了4个参数,其中第一个参数总是未定义的,不确定是否可能是它,但只是作为一个附加提示

下面是代码:

这是我的typedefs的一部分

directive @isAuthenticated on FIELD_DEFINITION

scalar Date

type User {
    id: ID,
    name: String
    email: String
    password: String
    createdAt: Date
}

type Token {
    token: String
}

# IF I REMOVE @isAuthenticated this works!
type Query {
    user(name: String): User! @isAuthenticated 
    users: [User!]! @isAuthenticated
}

type Mutation {
    createUser(name: String, email: String, password: String): Boolean!
    login(email: String!, password: String!): Token!
}
这是我的模式:

import path from 'path';
import { makeExecutableSchema } from 'graphql-tools';
import { fileLoader, mergeResolvers, mergeTypes } from 'merge-graphql-schemas';
import schemaDirectives from './Directives';

const typedefsArray = fileLoader(path.join(__dirname, './**/*.graphql'));
const resolversArray = fileLoader(path.join(__dirname, './**/*.resolvers.ts'));

const typeDefs = mergeTypes(typedefsArray);
const resolvers = mergeResolvers(resolversArray);
const schema = makeExecutableSchema({ typeDefs, resolvers, schemaDirectives });

export default schema;
这是我的授权指令

import { defaultFieldResolver } from 'graphql';
import { AuthenticationError, SchemaDirectiveVisitor } from 'apollo-server-express';

class AuthDirective extends SchemaDirectiveVisitor {
  visitFieldDefinition(field: any) {
    const { resolver = defaultFieldResolver } = field;

    field.resolve = async function (...args: any) {
      const [_, __, context] = args;
      const { req } = context;
      const accessToken = req.headers.authorization
        ? req.headers.authorization.replace('Bearer ', '')
        : null;

      if (accessToken) {
        // here I was doing jwt.verify(accessToken) but I removed it for now to simplify
        const result = await resolver.apply(this, args);
        return result; // <--- THIS IS ALWAYS UNDEFINED
      } else {
        throw new AuthenticationError('Unauthorized field');
      }
    };
  }
}

export default AuthDirective;
最后是我的用户解析器。如前所述,如果我从用户graphql查询中删除该指令,它将正常工作:

import jwt from 'jsonwebtoken';
import { AuthenticationError, UserInputError } from 'apollo-server-express';
import { IUser } from './IUser';
import UserModel from './user.schema';
import { Config } from '../../config';

const { APP_SECRET } = Config;

const createToken = async (user: IUser, secret: string, expiresIn: string) => {
  const { id, email, name } = user;
  return jwt.sign({ id, email, name }, secret, { expiresIn });
};

const userResolvers = {
  Query: {
    user: (_: any, { name }: { name: string }) => UserModel.findOne({ name }).exec(),
    users: () => UserModel.find({}).exec()
  },
  Mutation: {
    createUser: async (_: any, args: IUser) => {
      await new UserModel(args).save();
      return true;
    },
    login: async (_: any, { email, password }: IUser) => {
      const user = await UserModel.findOne({ email }).exec();

      if (!user) {
        throw new UserInputError('No user found with this login credentials.');
      }

      const isValid = await user.validatePassword(password);

      if (!isValid) {
        throw new AuthenticationError('Invalid password.');
      }

      return { token: createToken(user, APP_SECRET, '30m') };
    }
  }
};

export default userResolvers;
和我的服务器:

import morgan from 'morgan';
import express from 'express';
import bodyParser from 'body-parser';
import compression from 'compression';
import depthLimit from 'graphql-depth-limit';
import { ApolloServer } from 'apollo-server-express';

import { Config, DBConfig } from './config';
import schema from './domain';
const { PORT } = Config;

const app = express();

const apolloServer = new ApolloServer({
  schema,
  validationRules: [depthLimit(7)],
  context: ({ req, res }: any) => ({ req, res })
});

app.use(express.json());
app.use(compression());
app.use(morgan('combined'));
app.use(bodyParser.urlencoded({ extended: true }));
apolloServer.applyMiddleware({ app });

DBConfig.init();

app.listen(PORT, () => console.log(`Server running on port ${PORT}`));


字段
上没有
解析器
属性,因此

const { resolver = defaultFieldResolver } = field;
将始终导致
resolver
的值为
defaultFieldResolver
。如果您在某个具有自定义冲突解决程序的字段上使用该指令,则不会调用该自定义冲突解决程序——只使用默认行为,这可能会返回
undefined

您需要确保使用了正确的属性:

const { resolve = defaultFieldResolver } = field;
或者,您可以在分解
字段时重命名结果变量:

const { resolve: resolver = defaultFieldResolver } = field;

天哪,我觉得自己太蠢了,除了那个,我什么都试过了!谢谢你的快速回复
const { resolve: resolver = defaultFieldResolver } = field;