Загрузка Graphql Apollo в Nest js возвращает неверное значение {} - PullRequest
1 голос
/ 04 февраля 2020

Я попытался добавить аргумент загрузки в конечную точку GraphQL, используя graphql-upload s GraphQLUpload scalar:

import { FileUpload, GraphQLUpload } from 'graphql-upload'

@Mutation(() => Image, { nullable: true })
async addImage(@Args({name: 'image', type: () => GraphQLUpload}) image: FileUpload): Promise<Image | undefined> {
// do stuff...
}

И это сработало изначально. Однако через несколько запусков он начал возвращать следующую ошибку:

"Variable \"$image\" got invalid value {}; Expected type Upload. Upload value invalid."

Пробное тестирование с клиентом Insomnia и curl:

curl localhost:8000/graphql \
  -F operations='{ "query": "mutation ($image: Upload!) { addImage(image: $image) { id } }", "variables": { "image": null } }'
  -F map='{ "0": ["variables.image"] }'
  -F 0=@/path/to/image

Ответы [ 3 ]

6 голосов
/ 11 февраля 2020

Основываясь на ответе @ willsquire, я понял, что по какой-то причине декоратор Scalar у меня не работает, поэтому я в итоге заменил GraphQl-Upload на следующий фрагмент

import * as FileType from 'file-type'
import { GraphQLError, GraphQLScalarType } from 'graphql'
import { Readable } from 'stream'

export interface FileUpload {
  filename: string
  mimetype: string
  encoding: string
  createReadStream: () => Readable
}

export const GraphQLUpload = new GraphQLScalarType({
  name: 'Upload',
  description: 'The `Upload` scalar type represents a file upload.',
  async parseValue(value: Promise<FileUpload>): Promise<FileUpload> {
    const upload = await value
    const stream = upload.createReadStream()
    const fileType = await FileType.fromStream(stream)

    if (fileType?.mime !== upload.mimetype)
      throw new GraphQLError('Mime type does not match file content.')

    return upload
  },
  parseLiteral(ast): void {
    throw new GraphQLError('Upload literal unsupported.', ast)
  },
  serialize(): void {
    throw new GraphQLError('Upload serialization unsupported.')
  },
})
1 голос
/ 05 февраля 2020

После небольшого копания выясняется, что apollo-server-core автоматически анализирует загрузку файлов в промежуточном программном обеспечении с graphql-upload на основе запроса, состоящего из нескольких частей, вместо определения по имени скалярного типа. Так что graphql-upload необязательно, поскольку он уже интегрирован, но это полезно для получения проанализированного типа:

import { Scalar } from '@nestjs/graphql'
import FileType from 'file-type'
import { GraphQLError } from 'graphql'
import { FileUpload } from 'graphql-upload'
import { isUndefined } from 'lodash'

@Scalar('Upload')
export class Upload {
  description = 'File upload scalar type'

  async parseValue(value: Promise<FileUpload>) {
    const upload = await value
    const stream = upload.createReadStream()
    const fileType = await FileType.fromStream(stream)

    if (isUndefined(fileType)) throw new GraphQLError('Mime type is unknown.')

    if (fileType?.mime !== upload.mimetype)
      throw new GraphQLError('Mime type does not match file content.')

    return upload
  }
}
0 голосов
/ 05 мая 2020

Для меня решения, предложенные здесь @Yhozen и @Willsquire, являются своего рода обходным путем, но не верным ответом на проблему.

В моем случае реальная проблема исходила от graphql-upload У меня это было в моих зависимостях, и это создавало ошибку, описанную в этом стеке.

Удаляя зависимость это решило проблему. Как заметил @willsquire, graphql-upload уже находится в пакете apollo-server, нет необходимости импортировать его в пакете.

...