Giter VIP home page Giter VIP logo

jaydenseric / apollo-upload-client Goto Github PK

View Code? Open in Web Editor NEW
1.5K 1.5K 155.0 481 KB

A terminating Apollo Link for Apollo Client that fetches a GraphQL multipart request if the GraphQL variables contain files (by default FileList, File, or Blob instances), or else fetches a regular GraphQL POST or GET request (depending on the config and GraphQL operation).

Home Page: https://npm.im/apollo-upload-client

JavaScript 100.00%
apollo apollo-client graphql maintained node npm react react-native

apollo-upload-client's People

Contributors

andreialecu avatar danielrearden avatar epitaphmike avatar fuelen avatar giautm avatar hoangvvo avatar jaydenseric avatar knaackee avatar mxstbr avatar powerkiki avatar samcoenen avatar simenb avatar srtucker22 avatar tw0517tw avatar yaacovcr avatar zackify avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

apollo-upload-client's Issues

TypeError: Object(...) is not a function

When trying to import createUploadLink, throws the error: TypeError: Object(...) is not a function in 7.0.0-alpha.3.

import { createUploadLink } from 'apollo-upload-client'

createUploadLink : TypeError: Object(...) is not a function

Hi,

With this setup:

import { createUploadLink } from "apollo-upload-client"
...

const client = new ApolloClient({
  link: createUploadLink({ uri: "http://localhost:3002/graphql" }),
  cache: new InMemoryCache(),
})

I got an error : TypeError: Object(...) is not a function coming from webpack_require

But with:

import { createHttpLink } from "apollo-link-http"
...

const client = new ApolloClient({
  link: createHttpLink({ uri: "http://localhost:3002/graphql" }),
  cache: new InMemoryCache(),
})

It works

Do I miss something?

Apollo + Ionic 3 (angular 4) we have not access to filesystem but we have DATA_URL image. How to correctly Upload it?

      // dataURI is the result of:  this.camera.getPicture(this.options)
      /**
       * this.options = {
       *       quality: 100,
       *       destinationType: this.camera.DestinationType.DATA_URL,
       *       sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
       *       encodingType: this.camera.EncodingType.JPEG,
       *       mediaType: this.camera.MediaType.PICTURE
       *     };
       **/
      let myFile = this.dataURLtoBlob('data:image/jpeg;base64,' + dataUri);

      let xhr = new XMLHttpRequest();
      xhr.responseType = 'json';
      xhr.open("POST", "/graphql");
      xhr.setRequestHeader("Content-Type", "application/json");
      xhr.setRequestHeader("Accept", "application/json");
      xhr.onload = function () {
        console.log('data returned:', xhr.response);
      };
      let query = `mutation upload ($file: Upload!) {
        singleUpload(file: $file) {
          id
        }
      }`;

      xhr.send(JSON.stringify({
        query: query,
        variables: {
          file: myFile
        }
      }));

My main question is: I don't have access to the filesystem, that's the reason why i'm asking for the content of the image. Is this the right way to call the mutation?

This is a simple script of what we are trying. We are using apollo-upload-server too.

TypeScript type declarations

Is anyone using this repo with TypeScript? I'm getting this error when I try to compile my project:
TS7016: Could not find a declaration file for module 'apollo-upload-client'.

Using in angular 5

It is possible to use it in angular?
I was able to use the previuos version of upload-client (networkInterface), but I not sure if I can with apollo-link.

Thanks in advance

TypeError: (0 , _extractFiles.extractFiles) when using with create-react-app and Typescript

Hi, I got the folowing error when I try to use apollo-upload-client with create-react-app and Typescript:

TypeError: (0 , _extractFiles.extractFiles) is not a function

My package verions:

        "apollo-cache-inmemory": "^1.1.5",
        "apollo-client": "^2.2.0",
        "apollo-link": "^1.0.7",
        "apollo-link-context": "^1.0.3",
        "apollo-link-error": "^1.0.3",
        "apollo-link-http": "^1.3.2",
        "apollo-upload-client": "^7.0.0-alpha.3",
        "react": "^16.0.0",
        "react-apollo": "^2.0.4",
        "react-dev-utils": "^4.1.0",
        "react-dom": "^16.0.0",
        "typescript": "^2.6.2",

And here is my setup:

import { createUploadLink } from 'apollo-upload-client/lib';
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { onError } from 'apollo-link-error';

const errorLink = onError(({ networkError, graphQLErrors }) => {
  if (graphQLErrors) {
    graphQLErrors.map(({ message, locations, path }) =>
      debug(
        `[GraphQL error]: Message: ${message}, Location:`,
        locations,
        `Path: ${path}`
      )
    );
  }

  if (networkError) {
    debug(`[Network error]: ${networkError}`);
  }
});

const link = createUploadLink({
  uri: '/graphql',
  credentials:
    process.env.NODE_ENV === 'development' ? 'include' : 'same-origin',
  headers: {
    authorization: localStorage.getItem(TOKEN)
      ? `Bearer ${localStorage.getItem(TOKEN)}`
      : null
  }
});

const client = new ApolloClient({
  cache: new InMemoryCache(),
  link: errorLink.concat(link)
});

Files created with the window.File constructor upload empty in Safari

This is a fun issue! Mostly because I can't seem to pinpoint where the issue exactly lies! πŸ˜„

Scenario

I use the apollo-upload-client together with the apollo-upload-server in my React project to upload images to my server. I use some simple client-side image compression to reduce the size of the file to upload to speed up the upload process (greatly outweighs the time required to compress the image + lowers data usage).

In Chrome and Firefox the upload works like a charm with compressed images. πŸ‘

Problem

In Safari my client doesn't correctly upload the compressed image: the Upload promise on the server resolves to a FileStream with a length of 0. πŸ‘Ž My Request Headers Content-Length is way to small to include the image, so it's simply not being sent, though no errors are being thrown. I do get the metadata of the image (filename, mime type etc.) on the server so the request is correctly being sent, it just doesn't contain the image data.

Expected behaviour

The image would correctly be sent OR an error would be thrown telling me if something's wrong.

Root of problem

The obvious issue is that I'm breaking my image during compression. However, when I console.log(URL.createObjectURL(myImage)) and copy/paste that string in an <img> tag on the page, it renders correctly and when logging the file itself to the console, I see nothing out of the ordinary either. I can even download and base64 the File and open it in an external service without any issues.

It seems to me that the File is, in fact, a valid File. Apollo-upload-client doesn't agree with me on this one though.

Code

The file compression can be seen here at CodeSandbox. It doesn't work for some reason inside CodeSandbox, but can be copy/pasted to local and runs without issues there.

It seems a bit overkill to re-create the rest of the project structure inside CodeSandbox because it's so big and unrelated (as proven by the small request content-length). The code is hosted on a private repo which I'm not allowed to share. FWIW, the server follows https://github.com/jaydenseric/apollo-upload-examples/tree/master/api (only difference is that I use express). After compressing the image, it's sent directly using the mutate prop passed by the GraphQL HoC, no further adjustments are made to it.

Question

I'm not very familiar with the apollo-upload-client, but if someone could give me some pointers in how I can further debug this myself, I'd be glad to do so! Maybe the File needs to meet certain conditions I'm unaware of? It currently has a name, content, type and lastModified. IMO an error should at least be thrown when a File should, but couldn't, be uploaded.

How to use this package in combination with `createBatchingNetworkInterface`?

Right now, my setup looks like this:

const networkInterface = createBatchingNetworkInterface({ uri: `${environment.api}graphql/batch` });

networkInterface.use([{
  applyBatchMiddleware(req, next) {
    if (!req.options.headers) {
      req.options.headers = {};  // Create the header object if needed.
    }
    // some header processing
    ...
    next();
  }
}]);

const client = new ApolloClient({
  networkInterface,
});

I do not yet understand where to use createUploadLink given my setup.
Please help me understand what to do to get this package to work. :)

Persisted queries?

I just tried to use the apollo-link-persisted-queries together with apollo-upload-client, but I'm still seeing the full query body being sent over the wire for all queries.

Is there anything apollo-upload-client does that could prevent it from working with persisted queries?

Accessing the uploaded files

This is more of a question.

I can successfully upload files to a directory in the server but I do not know how to retrieve it. What is the proper way to do it? Is there an implementation for accessing files through graphql queries or do I have to create another endpoint for accessing files or images?

I have tried running Filereader on the client code after accessing the static files but no luck.. the file is not in a jpg format.

Network Error while uploading image using react-native-image-picker

I am trying to upload image to my backend using apollo-upload-client

The format is this

let image = { uri: 'content://media/external/images/media/127077',
name: 'IMG_20180120_094407.jpg',
type: 'image/jpeg' }

I pass this to ReactNativeFile

like this
let file = new ReactNativeFile(image)

When submit, it hits the server but I am not able to get response as it is always throwing error
[Network error]: TypeError: Network request failed

Without the image upload part, I don't get the error.

What should I do to resolve this?

cropping image before uploading

Hi,
Thanks for this great library. I have a question. Is there a way to crop the image before uploading the image or should the image be cropped server side? I noticed that the library deals with File or FileList objects but if I crop the image client side, I am not sure how to change back to File object. Please share any library to crop images server side.
Thanks

Error: Network error: Network request failed in my React-Native project

Why do I get this error?
Error: Network error: Network request failed

My store

export const client = new ApolloClient({
  link: createUploadLink({ uri: 'http://localhost:3030/graphql' }),
  cache: new InMemoryCache()
})
const middlewares = [client.middleware(), thunk]
export const store = createStore(
  reducers(client),
  undefined,
  composeWithDevTools(applyMiddleware(...middlewares)),
)

My backend here

My mutation:

export default gql`
  mutation($file: Upload!) {
    uploadFile(file: $file)
  }
`

My action:

  _onShowSignupPress = async () => {
    const { profilePhotoUri } = this.state
    const file = new ReactNativeFile({
      uri: profilePhotoUri,
      type: 'image/jpeg',
      name: 'photo.jpg'
    })
    const response = await this.props.mutate({ variables: { file } })
    console.log(response)
  }

after APOLLO_MUTATION_INIT - APOLLO_MUTATION_ERROR

{
  type: 'APOLLO_MUTATION_INIT',
  mutationString: 'mutation ($file: Upload!) {\n  uploadFile(file: $file)\n}\n',
  mutation: {
    kind: 'Document',
    definitions: [
      {
        kind: 'OperationDefinition',
        operation: 'mutation',
        variableDefinitions: [
          {
            kind: 'VariableDefinition',
            variable: {
              kind: 'Variable',
              name: {
                kind: 'Name',
                value: 'file'
              }
            },
            type: {
              kind: 'NonNullType',
              type: {
                kind: 'NamedType',
                name: {
                  kind: 'Name',
                  value: 'Upload'
                }
              }
            },
            defaultValue: null
          }
        ],
        directives: [],
        selectionSet: {
          kind: 'SelectionSet',
          selections: [
            {
              kind: 'Field',
              alias: null,
              name: {
                kind: 'Name',
                value: 'uploadFile'
              },
              arguments: [
                {
                  kind: 'Argument',
                  name: {
                    kind: 'Name',
                    value: 'file'
                  },
                  value: {
                    kind: 'Variable',
                    name: {
                      kind: 'Name',
                      value: 'file'
                    }
                  }
                }
              ],
              directives: [],
              selectionSet: null
            }
          ]
        }
      }
    ],
    loc: {
      start: 0,
      end: 62,
      source: {
        body: '\n  mutation($file: Upload!) {\n    uploadFile(file: $file)\n  }\n',
        name: 'GraphQL request',
        locationOffset: {
          line: 1,
          column: 1
        }
      }
    }
  },
  variables: {
    file: {
      uri: 'file:///Users/xyz/Library/Developer/CoreSimulator/Devices/BF0FFACC-B049-403D-A27C-048B9BC54636/data/Containers/Data/Application/BCB8B96B-DC71-4ECC-8537-6E4174F78420/Documents/images/F2FDA5B9-B427-476F-BFA7-7FA8E2F8FF10.jpg',
      type: 'image/jpeg',
      name: 'photo.jpg'
    }
  },
  operationName: null,
  mutationId: '1',
  extraReducers: [],
  updateQueries: {}
}

But my server is working
2017-12-01 20 28 17

Network error: 413 (Request Entity Too Large) for files > 1MB

I get this error whenever I try to upload a file larger than around 1 MB. The current setup is using the latest Apollo Client v2, Express, Apollo Server and Node.js

It feels like I'm missing something, maybe the binary data is getting sent in the literal query string and not the multipart of the request?

Here's my client side Apollo instance
import clientConfig from '../../clientConfig';
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory'
import { split } from 'apollo-link';
import { onError } from "apollo-link-error";
import { HttpLink } from 'apollo-link-http';
import { createUploadLink } from 'apollo-upload-client';
import { WebSocketLink } from "apollo-link-ws";
import { getMainDefinition } from 'apollo-utilities';
import { SubscriptionClient } from 'subscriptions-transport-ws';

// Create WebSocket client
const wsClient = new SubscriptionClient(clientConfig.endpoints.websocketEndpoint, {
  reconnect: true,
  connectionParams: {},
});

const link = split(
  // split based on operation type
  ({ query }) => {
    const { kind, operation } = getMainDefinition(query);
    return kind === 'OperationDefinition' && operation === 'subscription';
  },
  new WebSocketLink(wsClient),
  createUploadLink({
    uri: '/graphql',
    credentials: 'same-origin'
  }),
  new HttpLink({
    uri: '/graphql',
    credentials: 'same-origin'
  }),
  onError(({ graphQLErrors, networkError }) => {
    if (graphQLErrors)
      graphQLErrors.map(({ message, locations, path }) =>
        console.log(
          `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
        )
      );
    if (networkError) console.log(`[Network error]: ${networkError}`);
  })
);

const cache = new InMemoryCache();

export default function createApolloClient() {
  return new ApolloClient({
    link,
    cache: cache.restore(window.__APOLLO_CLIENT__),
    ssrMode: true,
    queryDeduplication: true,
    connectToDevTools: true,
  });
}

export {wsClient};
Request Payload
------WebKitFormBoundaryfP8PAj7i7fx1pQoy 
Content-Disposition:form-data; name="operations"{  
   "query":"mutation testCreateCategory($name: String!, $image: Upload) {\n  testCreateCategory(name: $name, image: $image) {\n    id\n    name\n    products {\n      id\n      name\n      manufacturer\n      productCode\n      attributesTemplate\n      __typename\n    }\n    updatedAt\n    __typename\n  }\n}\n",
   "operationName":"testCreateCategory",
   "variables":{  
      "name":"test 234csd345"
   }
}------WebKitFormBoundaryfP8PAj7i7fx1pQoy 
Content-Disposition:form-data; name="map"{  
   "0":[  
      "variables.image"
   ]
}------WebKitFormBoundaryfP8PAj7i7fx1pQoy 
Content-Disposition:form-data; name="0"; filename="03.jpg" 
Content-Type:image/jpeg 


------WebKitFormBoundaryfP8PAj7i7fx1pQoy--

Cookie gets not sent

Hi!

Using this config the cookie gets not sent to the server. (as documented here)

    const networkInterface = createBatchNetworkInterface({
        uri: '/graphql',
        batchInterval: 10,
        opts: {
            credentials: 'same-origin'
        }
    });

You have to use this to get it working

    const networkInterface = createBatchNetworkInterface({
        uri: '/graphql',
        batchInterval: 10,
        credentials: 'same-origin'
    });

I think this is not intuitive.

Support creating a custom FormData object.

Is it possible to provide additional prop to the link config options, to support custom FormData handling, e.g.

customFormData: (query, fetchOptions, files) => {
const body = new FormData();
...balblalbalb...

return body;
}

This will allow more versatility, because not always back-end refactoring to support a certain request convention is an option.

Thank you!

Upload progress?

@jaydenseric I've been wondering how to track progress for uploads. Would love to implement it here. No idea where to start though

uri must be a string

After upgrading to version 5.0 I got an runtime error: "uri must be a string".
I can see in debugger that apollo client got object with uri, opts and batchInterval (instead of just uri string). There was no such error in version 4.0.3.
What I did wrong?
Thank you!

"Uncaught Error: Must contain a query definition" when apollo-client v2 + compose + client option

localhost

environments

{
  "dependencies": {
    "@types/react": "^16.0.28",
    "@types/react-dom": "^16.0.3",
    "apollo-client-preset": "^1.0.5",
    "apollo-upload-client": "^7.0.0-alpha.1",
    "babel-plugin-add-module-exports": "^0.2.1",
    "babel-preset-env": "^1.6.1",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-1": "^6.24.1",
    "graphql": "^0.12.3",
    "graphql-tag": "^2.6.1",
    "parcel-bundler": "1.2.1",
    "react": "^16.2.0",
    "react-apollo": "^2.0.4",
    "react-dom": "^16.2.0",
    "typescript": "^2.6.2"
  }
}

When I was trying to have a query and a mutation on a component, I encountered this error.
Very simplified reproductive code is below.

class YourComponent extends React.Component<ChildProps<{}, QueryResponse & MutationResponse>, {}> {
  render() {
    console.log(this.props)
    return <div>from YourComponent</div>
  }
}

export default compose(
  graphql<QueryResponse>(QUERY),
  graphql<MutationResponse>(MUTATION, {
    options: props => ({
      client: uploadClient
    })
  })
)(YourComponent)
  1. you have compose to build your graphql
  2. you have a query + a mutation
  3. you set a client through the options variable on the mutation

If I remove options and use the client in ApolloProvider <ApolloProvider client={uploadClient}>, then it will remove the error.

export default compose(
  graphql<QueryResponse>(QUERY),
  graphql<MutationResponse>(MUTATION)
)(QueryAndMutation)

Is it maybe how I build graphql is irregular?

Error: Network error: Network request failed

This is similar to #45

What are you doing

I am trying to use apollo-upload-client to enable me upload files from my mobile app

const httpLink = createUploadLink({ uri: httpUri });
const authLink = setContext(async (req, { headers }) => {
  const token = await getUserJWT()
  return {
    headers: {
      ...headers,
      authorization: token
    }
  }
})
const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors)
    graphQLErrors.map(({ message, locations, path }) =>
      console.log(
        `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
      )
    );
  if (networkError) console.log(`[Network error]: ${networkError}`);
});

const link = ApolloLink.split(
  operation => {
    const operationAST = getOperationAST(operation.query, operation.operationName);
    return !!operationAST && operationAST.operation === 'subscription';
  },
  new WebSocketLink({
    uri: wsUri,
    options: {
      reconnect: true, //auto-reconnect
      connectionParams: {
        authorization: getUserJWT
      }
    }
  }),
  errorLink.concat(authLink.concat(httpLink))
);



const cache = new InMemoryCache();

persistCache({
  cache,
  storage: AsyncStorage,
});


const client = new ApolloClient({
  link,
  cache
});

and my mutation is this

validateCard: async ({ senderFirstName, senderLastName, senderPhoneNumber, senderFacebook, senderTwitter, senderWhatsapp, senderInstagram, senderImage, recipientFirstName, recipientLastName, recipientPhoneNumber, recipientFacebook, recipientTwitter, recipientWhatsapp, recipientInstagram, recipientImage, artistId }) => {
            senderImage = new ReactNativeFile(senderImage)
            recipientImage = new ReactNativeFile(recipientImage)
            console.log(senderImage)
            
            try {
                const { data: { validateCard: { ok, errors, senderFirstNameAvailable, senderLastNameAvailable, recipientFirstNameAvailable, recipientLastNameAvailable, suggestedArtists }}} = await validateCardMutation({ variables: {
                    input: { 
                        senderFirstName, 
                        senderLastName, 
                        senderPhoneNumber, 
                        senderFacebook, 
                        senderTwitter, 
                        senderWhatsapp, 
                        senderInstagram, 
                        senderImage, 
                        recipientFirstName, 
                        recipientLastName, 
                        recipientPhoneNumber, 
                        recipientFacebook, 
                        recipientTwitter, 
                        recipientWhatsapp, 
                        recipientInstagram, 
                        recipientImage,
                        artistId
                     }
                }})
                return {
                    ok,
                    error: formatErrors(errors),
                    senderFirstNameAvailable, 
                    senderLastNameAvailable, 
                    recipientFirstNameAvailable, 
                    recipientLastNameAvailable, 
                    suggestedArtists
                }                

            } catch (error) {
                console.log("We encountered the following error: ", error)
            }
        }
    })

in my server, I have this for my graphql server

const schema = makeExecutableSchema({ 
    typeDefs,
    resolvers,
})

export default function (host, port, database) {
    
    const graphQLServer = express();

    graphQLServer.use(cors({ origin: '*'}))
    graphQLServer.use(bodyParser.urlencoded({ extended: true }), bodyParser.json())
    graphQLServer.use(authMiddleware)
    graphQLServer.use('/graphql', uploadMiddleware)
    graphQLServer.use('/graphiql', graphiqlExpress({
        endpointURL: '/graphql',
        subscriptionsEndpoint: `ws://${config.ws.HOST}:${config.ws.PORT}/${config.ws.PATH}`,
    }));
    graphQLServer.use('/graphql', apolloUploadExpress(), graphqlExpress(req => {
        console.log(req.body)
        return {
            schema,
            context: {
                db: database,
                user: req.user,
                JWT_SECRET: config.secrets.JWT
            }
        }
    }))

    return graphQLServer.listen(port, () => {
        console.log(`GraphQL Server is now running on http://${host}:${port}`)
        new SubscriptionServer(
            {
                schema,
                execute,
                subscribe,
            },
            {
                server: graphQLServer,
                path: '/subscriptions',
            }
        )
    })
    
}

my scalar is this

scalar FileUploadObject

and resolver is this

//import the GraphQLUpload function
import { GraphQLUpload } from 'apollo-upload-server'

//added to other functions in the resolvers object
FileUploadObject: GraphQLUpload

and my graqhql definition

input CardValidationInput {
        senderFirstName: String
        senderLastName: String
        senderPhoneNumber: String
        senderFacebook: String
        senderWhatsapp: String
        senderTwitter: String
        senderInstagram: String
        senderImage: FileUploadObject
        recipientFirstName: String
        recipientLastName: String
        recipientPhoneNumber: String
        recipientFacebook: String
        recipientWhatsapp: String
        recipientTwitter: String
        recipientInstagram: String
        recipientImage: FileUploadObject #This is the part that should contain the uploaded file
        artistId: Int                        
    }

What do you expect

When I tap the button, my input should be posted to the server

What are you experiencing

It keeps throwing this error

Error: Network error: Network request failed

How to use client in node js test suite

I'd like to use this library from my node js test suite to test file uploading against my apollo server. I tried using fs.createReadStream(...) but extract-files expects File or ReactNativeFile. Is there something I can use in node js that is equivalent to File or ReactNativeFile?

Cannot compose createUploadLink

This was mentioned in #35 already, but I'm still experiencing the same issue when trying to compose any other link with createUploadLink.

My code:

function omitTypename(key, value) {
    return key === '__typename' ? undefined : value
}

const cleanTypenameFieldLink = new ApolloLink((operation, forward) => {
    if (operation.variables) {
        operation.variables = JSON.parse(JSON.stringify(operation.variables), omitTypename)
    }

    return forward(operation)
});

const uri = 'http://localhost:8080';
const uploadLink = createUploadLink({ uri });
const appLink = cleanTypenameFieldLink.concat(uploadLink);

// Apollo client
const client = new ApolloClient({
    link: appLink,
    cache: new InMemoryCache(),
    credentials: 'same-origin'
});

I've tried a combination of:

1)
concat(uploadLink, cleanTypenameFieldLink)
uploadLink.concat(cleanTypenameFieldLink)

my custom cleanTypenameFieldLink doesn't run, but the file will upload

The order above throws an apollo-link warning:
You are calling concat on a terminating link, which will have no effect

2)
concat(cleanTypenameFieldLink, uploadLink),
cleanTypenameFieldLink.concat(uploadLink);
While this seems to work, but the upload promise is undefined when it hits the server. Which I'm assuming means the clientUploadLink never was ran when last.

3)
I've also tried the fix mentioned in the bottom of the issue of referencing the build index.js directly, to no avail.

4)
Assumed my custom link wasn't working and tried something simple like HttpLink, I had the same results as 1 and 2 from above.

In that issue it was mentioned this might be a .mjs and CRA issue, but I've ejected my CRA and confirmed I have the merged code from the mentioned CRA PR in #35. Which just seemed to be CRA support for .mjs extensions.

If I've missed anything please let me know! Everything has worked great otherwise, so thank you.

Request doesn't add multipart/form-data

I tried to follow the example given in the readme.

The apollo mutation arrives at the server with the correct output, but the apolloUploadExpress method just passe on the request to the next middleware without processing it as the follwoing is always true:

!request.is('multipart/form-data')

I believe the client middleware createNetworkInterface, imported from

import { createNetworkInterface } from 'apollo-upload-client

Doesn't seem to add the required multipart/form-data to the request.

Anything I might have missed?

Here is my code, I add a custom header for authentication. Might that be the issue?

const networkInterface = createNetworkInterface({
  uri: '/graphql',
});
networkInterface.use([{
  applyMiddleware(req, next) {
    if (!req.options.headers) {
      req.options.headers = {};  // Create the header object if needed.
    }
    // get the authentication token from local storage if it exists
    const token = localStorage.getItem('token');
    req.options.headers.authorization = Auth.getToken() ? `Bearer ${token}` : null;
    next();
  }
}]);




const client = new ApolloClient({
  networkInterface,
  dataIdFromObject: (o: any) => {
      return o.id
  }
});

Error: Network error: window is not defined

Hi Jay,

I'm pretty sure this is an error on my end, but if you have any advice I would love to hear it. I'm using next.js with apollo-client and getting 'window is not defined' when I switch to the new createNetworkInterface.

{ Error: Network error: window is not defined at new ApolloError (/Users/michaelmerrill/code/src/github.com/michaelmerrill/snapflix-client/node_modules/apollo-client/src/errors/ApolloError.js:32:28) at /Users/michaelmerrill/code/src/github.com/michaelmerrill/snapflix-client/node_modules/apollo-client/src/core/QueryManager.js:260:41 at /Users/michaelmerrill/code/src/github.com/michaelmerrill/snapflix-client/node_modules/apollo-client/src/core/QueryManager.js:683:25 at Array.forEach (native) at /Users/michaelmerrill/code/src/github.com/michaelmerrill/snapflix-client/node_modules/apollo-client/src/core/QueryManager.js:680:27 at Array.forEach (native) at QueryManager.broadcastQueries (/Users/michaelmerrill/code/src/github.com/michaelmerrill/snapflix-client/node_modules/apollo-client/src/core/QueryManager.js:677:42) at Array.<anonymous> (/Users/michaelmerrill/code/src/github.com/michaelmerrill/snapflix-client/node_modules/apollo-client/src/core/QueryManager.js:63:23) at dispatch (/Users/michaelmerrill/code/src/github.com/michaelmerrill/snapflix-client/node_modules/redux/lib/createStore.js:186:19) at /Users/michaelmerrill/code/src/github.com/michaelmerrill/snapflix-client/node_modules/apollo-client/src/ApolloClient.js:174:30 graphQLErrors: [], networkError: ReferenceError: window is not defined at HTTPUploadNetworkInterface.fetchFromRemoteEndpoint (/Users/michaelmerrill/code/src/github.com/michaelmerrill/snapflix-client/node_modules/apollo-upload-client/src/network-interface.js:6:26) at /Users/michaelmerrill/code/src/github.com/michaelmerrill/snapflix-client/node_modules/apollo-client/src/transport/networkInterface.js:108:71, message: 'Network error: window is not defined', extraInfo: undefined, queryErrors: [ [Circular] ] }

Network error: Cannot read property 'headers' of undefined

On upgrading from 3.0.3 to 4.0.0 I get the following error:

Network error: Cannot read property 'headers' of undefined
  at new ApolloError ([...]/node_modules/apollo-client/apollo.umd.js:1851:28)

I think it should be passing options through to window.fetch as well as opts?

Mutation error

I am trying to get this working without errors. So far I have managed to get a file uploaded using the middleware, but it returns and error and the store is not updated.

The documentation is great and pretty straight forward. I have set everything up. I keep getting the error:

Uncaught (in promise) Error: Network error: A state mutation was detected between dispatches, in the path `apollo.mutations.5.variables.uploadInput`. This may cause incorrect behavior.(http://redux.js.org/docs/Troubleshooting.html#never-mutate-reducer-arguments)

My container component is below

import React from 'react'
import { graphql, gql, compose } from 'react-apollo'
import UploadBankStatement from '../../components/EftFileUploads/UploadBankStatement.jsx';

const createEftFileUpload = gql`mutation createEftFileUpload(
          $bankAccountCode: String!,
          $uploadInput: UploadInput!,
          $uploadedByPersonCode: String!) {
        createEftFileUpload(
          bankAccountCode: $bankAccountCode,
          uploadInput: $uploadInput,
          uploadedByPersonCode: $uploadedByPersonCode) {
        id
      }
  }`;

const mutationConfig = {
  props: ({ mutate }) => ({
    createEftFileUpload: (bankAccountCode, uploadInput, uploadedByPersonCode) => {

      let variables = {
        bankAccountCode,
        uploadInput,
        uploadedByPersonCode
      };

      return mutate({ variables });
    }
  })
};

export default compose(
  graphql(createEftFileUpload, mutationConfig)
)(UploadBankStatement);

Below is the component that executes the mutation

import React, { Component, PropTypes } from 'react';
import gql from 'graphql-tag';
import { graphql, compose } from 'react-apollo';
import { Container, Row, Col, Card, CardBlock } from 'reactstrap';
import BankAccountsSelect from '../../containers/BankAccountsSelectContainer.jsx';

class UploadBankStatement extends Component {
  constructor(props) {
    super(props);

    // this.state = {
    //   bankAccountCode: null
    // };

    this.readFile = this.readFile.bind(this);
  }
  proceed = bankAccountCode => {
    this.bankStatementFile.click();
    // this.setState({ bankAccountCode });
  }

  readFile = e => {
    const files = e.target.files;
    console.log(e.target, e.target.validity);

    if (files && files[0]) {
      const file = files[0];
      this.props.createEftFileUpload(
        "1",
        file,
        "1");
    }
  }

  render() {
    console.log(this.props);
    return (
      <div>
        <input
          type="file"
          className="hidden-xl-down"
          ref={input => { this.bankStatementFile = input; }}
          onChange={this.readFile}
          onClick={e => { e.target.value = null }}
        />
        <BankAccountsSelect proceed={this.proceed} />
      </div>
    );
  }
}

UploadBankStatement.propTypes = {
  mutate: PropTypes.func.isRequired
}

export default UploadBankStatement;

Here are the redux events being fired ...

APOLLO_QUERY_INIT
APOLLO_QUERY_INIT
APOLLO_QUERY_RESULT
APOLLO_QUERY_RESULT
APOLLO_MUTATION_INIT
APOLLO_MUTATION_ERROR

The details of the error

type(pin): "APOLLO_MUTATION_ERROR"
β–Άerror(pin)
name(pin): "Invariant Violation"
framesToPop(pin): 1
mutationId(pin): "5"

Please can anyone point to how I can solve this.

Support batching again

Support for batching has been temporarily dropped in the rush to support the final Apollo Client v2 API (see #33 (comment)).

I am waiting on apollo-link-batch-http to be updated (it is still using apollo-fetch) so I can refer to it when writing our new batching terminating link.

Implement a progress bar ?

I know this is not the correct place to post it. But ... how would be the starting path to implement a progress Bar ?. XMLHttpRequest.upload seems not to capture any package.

Thanks πŸ‘

Transform error

When importing this component, my app complains about stage-0 and the transform runtime babel plugin not being installed. This is due to the babel config being in the package.json, can we get this fixed?

In field "uri": Unknown field

How to fix this error in my react-native project?
I'm uses library import ImagePicker from 'react-native-image-picker'

GraphQLError: Variable "$file" got invalid value {"uri":"file:///Users/xyz/Library/Developer/CoreSimulator/Devices/BF0FFACC-B049-403D-A27C-048B9BC54636/data/Containers/Data/Application/2AA8E51D-8BE7-4061-B187-82BF1953D9F8/Documents/images/FB720B3C-30A1-4BDF-875C-AAB16AFA35C8.jpg","type":"image/jpeg","name":"photo.jpg"}.
In field "uri": Unknown field.
In field "size": Expected "Int!", found null.
In field "path": Expected "String!", found null.
    at getVariableValues (/Users/xyz/graphql-upload-files-server/node_modules/graphql/execution/values.js:93:15)
    at buildExecutionContext (/Users/xyz/graphql-upload-files-server/node_modules/graphql/execution/execute.js:207:54)
    at executeImpl (/Users/xyz/graphql-upload-files-server/node_modules/graphql/execution/execute.js:121:15)
    at Object.execute (/Users/xyz/graphql-upload-files-server/node_modules/graphql/execution/execute.js:110:229)
    at doRunQuery (/Users/xyz/graphql-upload-files-server/node_modules/apollo-server-core/src/runQuery.ts:149:16)
    at /Users/xyz/graphql-upload-files-server/node_modules/apollo-server-core/src/runQuery.ts:70:39
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:228:7)

code

_onShowSignupPress = async () => {
    const { profilePhotoUri } = this.state
    const uploadUri = Platform.OS === 'ios' ? profilePhotoUri.replace('file://', '') : profilePhotoUri 
    const file = new ReactNativeFile({
      uri: uploadUri,
      type: 'image/jpeg',
      name: 'photo.jpg'
    })
    const response = await this.props.mutate({ variables: { file } })
    console.log(response)
  }

Typescript support

I tried to use the package in a typescript project but received the following errors:

node_modules/@types/graphql/subscription/subscribe.d.ts(17,4): error TS2314: Generic type 'AsyncIterator<T, E>' requires 2 type argument(s).
node_modules/@types/graphql/subscription/subscribe.d.ts(29,4): error TS2304: Cannot find name 'AsyncIterable'.

Is Typescript support planned?

Filesize

Considering we have the file's size in the browser, it would be pretty convenient to have size on the server as well.

Uploading to say s3 requires the filesize, so this would be quite nice.

Blob image

I implemented both apollo-upload-client and apollo-upload-server step by step, but the log in resolver is empty.
My blob file:
image
Server:
image
Client:
image

connection resets in chrome

there's a strange issue i can't really find the cause. i've implemented it very similiar to your example and it works quite well on edge and firefox. but in chrome i get POST http://localhost:8080/graphql net::ERR_CONNECTION_RESET. usually i would say this is a server side issue. but even in wireshark i can see that the response is coming back to chrome and in firefox and edge it's working.

currently i'm trying with 7.0.0-alpha.3. any ideas?

Parallel upload?

I'm wondering if this project could transparently support parallel uploads? If you provide a FileList, it could perhaps send 3 at a time?

Or would that break a single-form-post assumption on the server?

Also not sure if it's worth it, if the parallel uploading takes just as long as serial uploading.

Client is sending null in the query

My query payload which contains the file portion of the mutation is now sending null when i send the payload to my backend.

      file: acceptedFiles[0],
      type: 'OTHER',
    };
    const documents = [file];

 uploadOrderDocument({
      orderId,
      documents: [documents],
    }).then(res => console.log(res))
      .catch(err => console.log(err));

React Native & `babel-preset-env`

Trying this out with RN and got the error:

Couldn't find preset "env" relative to directory

Installing babel-preset-env fixes it but it seems like this should have been installed as a dependency and shouldn't be necessary for RN anyway?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.