Включить связь при запросе узла с использованием оболочки, созданной Prisma - PullRequest
0 голосов
/ 09 октября 2018

Я следую примеру GraphQL Prisma Typescript , предоставленному Prisma, и создал простую модель данных, сгенерировал код для клиента и распознавателей Prisma и т. Д.

Моя модель данных включает в себяследующие узлы:

type User {
  id: ID! @unique
  displayName: String!
}

type SystemUserLogin {
  id: ID! @unique
  username: String! @unique
  passwordEnvironmentVariable: String!
  user: User!
}

Я засеял системного пользователя и пользователя.

mutation {
  systemUserLogin: createSystemUserLogin({
    data: {
      username: "SYSTEM",
      passwordEnvironmentVariable: "SYSTEM_PASSWORD",
      user: {
        create: {
          displayName: "System User"
        }
      }
    }
  })
}

Я создал образец мутации login:

login: async (_parent, { username, password }, ctx) => {
    let user
    const systemUser = await ctx.db.systemUserLogin({ username })
    const valid = systemUser && systemUser.passwordEnvironmentVariable && process.env[systemUser.passwordEnvironmentVariable] &&(process.env[systemUser.passwordEnvironmentVariable] === password)

    if (valid) {
      user = systemUser.user // this is always undefined!
    }

    if (!valid || !user) {
      throw new Error('Invalid Credentials')
    }

    const token = jwt.sign({ userId: user.id }, process.env.APP_SECRET)

    return {
      token,
      user: ctx.db.user({ id: user.id }),
    }
  },

Но независимо от того, что я делаю, systemUser.user ВСЕГДА не определен!

Это имеет смысл - как клиентская оболочка узнает, как "глубоко" проникнуть в график, не сказав мне об этом?

Но как я могу сказать, что я хочу включить отношение User?

Редактировать: я попробовал приведенное ниже предложение использовать prisma-client.

Но ни один из моих распознавателей никогдакажется, что его называют ...

export const SystemUserLogin: SystemUserLoginResolvers.Type<TypeMap> = {
  id: parent => parent.id,
  user: (parent, args, ctx: any) => {
    console.log('resolving')
    return ctx.db.systemUserLogin({id: parent.id}).user()
  },
  environmentVariable: parent => parent.environmentVariable,
  systemUsername: parent => parent.systemUsername,
  createdAt: parent => parent.createdAt,
  updatedAt: parent => parent.updatedAt
};

И ...

  let identity: UserParent;

  const systemUserLogins = await context.db.systemUserLogins({
    where: {
      systemUsername: user,
    }
  });
  const systemUserLogin = (systemUserLogins) ? systemUserLogins[0] : null ;

  if (systemUserLogin && systemUserLogin.environmentVariable && process.env[systemUserLogin.environmentVariable] && process.env[systemUserLogin.environmentVariable] === password) {
    console.log('should login!')

    identity = systemUserLogin.user; // still null
  }

Редактировать 2: Вот хранилище

https://github.com/jshin47/annotorious/tree/master/server

Ответы [ 2 ]

0 голосов
/ 09 октября 2018

В настоящее время существует два способа решения этой проблемы:

  • Использование Prisma client в качестве OP на данный момент
  • Использование Prismabindings , как было предложено @ User97 в принятом ответе

Подробнее о разнице между привязками Prisma client и Prisma можно узнать в этом сообщении на форуме.

Поскольку OP в настоящее время использует клиент Prisma, я буду использовать его и для этого ответа!

Давайте посмотрим на оператор OP, сделанный в вопросе:

Это имеет смысл - как клиентская оболочка узнает, как "глубоко" войти в график, не сказав мне об этом?

ОП правильно заявил, что клиент Prisma не может знать, как глубоко войти вграфик и какие отношения выбрать.Фактически, если явно не сообщит иначе (например, с помощью $fragment API ), клиент никогда не получит никаких отношений и всегда будет только выбирать скалярные значения.Из документов Prisma :

Всякий раз, когда модель запрашивается с помощью клиента Prisma, выбираются все скалярные поля этой модели.Это верно независимо от того, запрашивается ли отдельный объект или список объектов.

Итак, как правильно разрешить эту ситуацию?На самом деле, решение состоит в том, чтобы не внести изменения в способ использования клиента Prisma, а реализовать дополнительную функцию распознавателя GraphQL!

Смысл в средствах распознавания состоит в том, что онивыборка данных для определенных полей в вашей схеме.В случае OP в настоящее время нет средства распознавания, которое "разрешало бы" отношение user, определенное для типа SystemUserLogin:

type SystemUserLogin {
  id: ID! @unique
  username: String! @unique
  passwordEnvironmentVariable: String!
  user: User! # GraphQL doesn't know how to resolve this
}

Чтобы разрешить эту ситуацию, вам необходимо реализовать выделенный "тип"resolver "для этого так:

const resolvers = {
  SystemUserLogin: {
    user(parent, args, ctx) {
      return ctx.db.systemUserLogin({id: parent.id}).user()
    }
  } 
}

Полное раскрытие: я работаю в Prisma, и мы работаем над добавлением более качественной документации и ресурсов для этого варианта использования.Также посмотрите этот пример, где явные средства разрешения для полей отношений author и posts требуются по той же причине.

Надеюсь, это поможет!

РЕДАКТИРОВАТЬ : Мы также добавили немного более подробное объяснение в учебнике Prisma по поводу Стандартных шаблонов распознавателя .

0 голосов
/ 09 октября 2018

Второй параметр функций привязки призмы принимает строку запроса GraphQL.Изменение следующей строки с

const systemUser = await ctx.db.query.systemUserLogin({ username })

на

const systemUser = await ctx.db.query.systemUserLogin({ username }, `{id username user {id displayName}}`)

даст вам данные пользователя.

Привязка Prisma вернет только прямые свойства модели в случае, если второй параметрне передается ему.

...