Контекст не передается во вложенный распознаватель Apollo GraphQL - PullRequest
0 голосов
/ 24 июня 2019

Я использую Apollo Server v2 для своего проекта

Я добавил аутентификацию, как указано здесь https://www.apollographql.com/docs/apollo-server/features/authentication/

Я хотел включить вложенный преобразователь в мои Query и Mutation, поэтомуЯ сделал согласно https://stackoverflow.com/a/40916089/7584077

Дело в том, что мой распознаватель немного сложнее, чем показанный выше

// typeDefs/typeDefs.js
import { gql } from "apollo-server-express";
import issueTracker from "./issueTracker";

const base = gql`
  scalar Timestamp

  type Query {
    ping: String!
  }

  type Mutation {
    ping: String!
  }
`;

export default [base, issueTracker];
// typeDefs/issuetracker.js
import { gql } from "apollo-server-express";

export default gql`
  type Comment {
    id: ID
    message: String
    commentBy: User
    createdAt: Timestamp
    updatedAt: Timestamp
    version: Int
  }

  type Issue {
    id: ID
    requestId: ID
    title: String
    issueNumber: Int
    status: Int
    tags: [String]
    assignees: [User]
    createdBy: User
    comments: [Comment]
    createdAt: Timestamp
    updatedAt: Timestamp
    version: Int
  }

  input CreateIssueRequest {
    requestId: ID!
    title: String!
    createdBy: ID!
    message: String!
    assignees: [ID]!
  }

  type IssueTrackerQuery {
    ping: String!
  }

  type IssueTrackerMutation {
    createIssue(request: CreateIssueRequest!): Issue
  }

  extend type Query {
    IssueTracker: IssueTrackerQuery
  }

  extend type Mutation {
    IssueTracker: IssueTrackerMutation
  }
`;

И модифицированная версия ответа на стеквыше.Вот мой комбинированный преобразователь.

// resolvers/resolvers.js
import IssueTracker from "./issueTracker";

export default {
  Query: {
    ping: () => "ping!",
    IssueTracker: () => ({
      ping: IssueTracker.ping,
    }),
  },
  Mutation: {
    ping: () => "ping!",
    IssueTracker: () => ({
      createIssue: IssueTracker.createIssue,
    }),
  },
};

Это потому, что я хотел, чтобы Query & Mutation был полностью отделен.

Вот мой IssueTrackerresolver

// resolvers/issueTracker.js
export default {
  ping: () => "ping",
  createIssue: async (parent, args, context) => {
    console.log(parent);
    console.log(args);
    console.log(context);
    // create issue as per request and return
  }

Дело в том, что parent на самом деле является args полем!И мне нужен userId из контекста, чтобы сделать разумные данные.

1 Ответ

0 голосов
/ 25 июня 2019

Хм, первый подход SDL может быть немного хитрым.Не легко объяснить, что здесь не так, но я сделаю все возможное.Сначала позвольте мне рассказать вам, что нужно сделать, чтобы сделать эту работу, а затем я объясню, что идет не так.

Создайте поле IssueTrackerMutation на карте распознавателя:

export default {
  Query: {
    ping: () => "ping!",
    IssueTracker: () => ({ // same here but I will just do the mutation for you
      ping: IssueTracker.ping,
    }),
  },
  Mutation: {
    ping: () => "ping!",
    IssueTracker: () => null, // or whatever you want as a root here
  },
  IssueTrackerMutation: {
    createIssue: IssueTracker.createIssue
  }
};

Примечаниеразница между созданием «чистого» резольвера для IssueTracker и возвратом объекта для IssueTracker с методом createIssue.

Теперь функция должна вызываться с ожидаемыми параметрами.Причина, по которой родительский аргумент отсутствует, заключается в особой реализации распознавателя по умолчанию.Средство распознавания предназначено для работы с объектно-ориентированным стилем, где поля могут быть полями или методами.Вы можете представить себе, что распознаватель будет работать так:

defaultResolver(fieldName, parent, args, context, info) {
  if (typeof parent !== 'object') {
    throw "Need object to default resolve";
  }
  if (typeof parent[fieldName] === 'function') {
    return parent[fieldName](args, context, info);
  }
  return parent[fieldName];
}

Это позволит вам записывать объекты доступа к данным следующим образом:

class IssueTracker {
  issues = []
  async createIssue(args, ctx, info) {
    const issue = await createIssue(args.request);
    this.issues.push(issue);
    return issue;
  }
}

const issueTracker = new IssueTracker();

export default {
  // ...
  Mutation: {
    // ...
    IssueTracker: () => issueTracker,
  },
  IssueTrackerMutation: {
    createIssue: IssueTracker.createIssue
  }
};

Об этом не так уж много говорится.но, вероятно, относительно близко, как работает GraphQL в Facebook.Сообщество, кажется, продвигает больше логики в решатели.

...