question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using upload as argument (graphql type) for mutation

See original GitHub issue

I have already successfully implemented uploading files successfully in nexus framework - but with schema I ran out of ideas.

According to the docs (https://nexusjs.org/docs/api/scalar-type) this was my approach:

import { arg, extendType }  from '@nexus/schema'

import { GraphQLUpload } from 'apollo-server-express'

export const Upload = GraphQLUpload

extendType({
  type: 'Mutation',
  definition(t) {
    t.crud.deleteOneDocument(),      
    t.field('uploadSingleDocument', {
      type: 'Document',
      args: {
        file: arg({ type: "Upload", required: true })  //here gives me "Type '"Upload"' is not assignable to type 'NexusArgConfigType"
      },
      async resolve (_root, args, ctx) {
           // ....
      },
    })
  },
})

I`ve also tried some of the solutions from issue #441 but seems like they are not working for my environment.

This is my package.json:

{ "name": "test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "ts-node-dev --transpile-only --no-notify api/app.ts", "build": "tsc" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "@nexus/schema": "^0.16.0", "@prisma/client": "^2.9.0", "apollo-server": "^2.18.2", "apollo-server-express": "^2.18.2", "express": "^4.17.1", "graphql": "^15.3.0", "graphql-scalars": "^1.4.0", "nexus-plugin-prisma": "^0.21.0" }, "devDependencies": { "@prisma/cli": "^2.9.0", "ts-node-dev": "^1.0.0-pre.65", "typescript": "^4.0.3" } }

I am running npm run dev while in the code window. Server is running on apollo-express.

This was my working solution with nexus framework (mutation had same code) for binary/multipart upload:

import { GraphQLUpload } from 'apollo-server-core';
import type { FileUpload } from 'graphql-upload';

export type UploadRoot = Promise<FileUpload>;

schema.scalarType({
  // Why we need the bang: https://github.com/apollographql/apollo-server/blob/570f548b88750a06fbf5f67a4abe78fb0f870ccd/packages/apollo-server-core/src/index.ts#L49-L56
  ...GraphQLUpload!,
  rootTyping: 'UploadRoot',
})

Please help!

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:1
  • Comments:6

github_iconTop GitHub Comments

3reactions
hajnalbencommented, Feb 11, 2021

Thanks for the awesome help @bkiac!

However we will need to register the Upload scalar alongside the resolvers to the makeSchema -> type field.

export const schema = makeSchema({
  types: [...resolvers, Upload], // from: scalars.ts
  // ...
 }

In case anyone wants to centralize your Upload handling you could use the scalarType insteadof asNexusMethod:

// scalars.ts
import { GraphQLUpload } from "apollo-server-express"
import { scalarType } from "nexus"
import { FileUpload } from "graphql-upload"
import { createWriteStream } from "fs"
import { promisify } from "util"
import stream from "stream"
import { join } from "path"

type UploadResult = String

export type Upload = Promise<UploadResult>

export const Upload = scalarType({
  name: 'Upload',
  asNexusMethod: 'upload',
  description: GraphQLUpload.description,
  serialize: GraphQLUpload.serialize,
  parseValue: uploadProcessor,
  parseLiteral: GraphQLUpload.parseLiteral
})

const pipeline = promisify(stream.pipeline);

async function uploadProcessor(value: Promise<any>): Promise<UploadResult> {
  // We want to support URLs as well
  if (typeof value === 'string') {
    return value
  }

  const file: FileUpload = await GraphQLUpload.parseValue(value)

  const path = __dirname + '/' + file.filename

  await pipeline(
    file.createReadStream(),
    createWriteStream(join(__dirname, file.filename))
  )

  return path
}
3reactions
bkiaccommented, Dec 15, 2020

This works for me with nexus@^1.0.0, apollo-server-express@^2.19.0

// scalars.ts
import { GraphQLUpload } from "apollo-server-express"
import { FileUpload } from "graphql-upload"
import { asNexusMethod } from "nexus"

export type Upload = Promise<FileUpload>
// Bang is required due to https://github.com/apollographql/apollo-server/blob/570f548b88750a06fbf5f67a4abe78fb0f870ccd/packages/apollo-server-core/src/index.ts#L49-L56
export const Upload = asNexusMethod(GraphQLUpload!, "upload")
// schema.ts
import { makeSchema } from "nexus"
import * as path from "path"

export const schema = makeSchema({
	// ...
	sourceTypes: {
		modules: [
			{
				module: path.join(__dirname, "path/to/scalars.ts"),
				alias: "BackingScalars",
			},
		],
	},
})
// upload.ts
import { arg, mutationField, nonNull } from "nexus"

export const upload = mutationField("upload", {
	type: "String",
	args: {
		data: nonNull(arg({ type: "Upload" })),
	},
	resolve: async (_, args) => {
		const { createReadStream } = await args.data
		const stream = createReadStream()
		// ...
		return "success"
	},
})
Read more comments on GitHub >

github_iconTop Results From Across the Web

Mutations - Apollo GraphQL Docs
GraphQL mutations represent two things in one operation: The mutation field name with arguments, which represents the actual operation to be done on...
Read more >
How to manage file uploads in GraphQL mutations using ...
Enter the Multipart Request Spec (The New Way) ... As you can see, adding in a file is as simple as adding in...
Read more >
Postman - Upload file and other argument with GraphQL
I know how I can upload a file, however, in my mutation I have to pass a String! together with the Upload! ....
Read more >
How to Add File Upload to Your GraphQL API - Level Up Coding
We define the types of data for our queries and mutations. Note that we also defined a new scalar type called Upload in...
Read more >
Mutations and Input Types - GraphQL
This is as simple as making the API endpoint part of the top-level Mutation type instead of the top-level Query type.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found