Reputation: 724
I am trying to use Apollo Server's Upload
scalar to send files to S3 directly. My schema:
const { gql } = require('apollo-server-express')
module.exports = gql`
extend type Mutation {
createPicture(
name: String!
picture: Upload!
): Picture!
}
type Picture {
name: String!
picture: String!
}
`
Resolver:
const { combineResolvers } = require('graphql-resolvers')
const isAuthenticated = require('./auth')
const { uploadPhoto } = require('../services/picture')
module.exports = {
Mutation: {
createPicture: combineResolvers(
isAuthenticated,
async (
parent,
{ name, picture = null },
{ models, me }
) => {
const { createReadStream, filename, mimetype, encoding } = await picture
// Does not get past this line
const stream = createReadStream()
uploadPhoto(stream, filename)
const pictureModel = models.Picture.create({
name,
picture
})
return pictureModel
}
)
}
}
But my code errors like this:
internal/util.js:55
function deprecated(...args) {
^
RangeError: Maximum call stack size exceeded
at ReadStream.deprecated [as open] (internal/util.js:55:22)
at ReadStream.open ([truncated]/node_modules/fs-capacitor/lib/index.js:90:11)
at _openReadFs (internal/fs/streams.js:123:12)
at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
at ReadStream.deprecated [as open] (internal/util.js:70:15)
at ReadStream.open ([truncated]/node_modules/fs-capacitor/lib/index.js:90:11)
at _openReadFs (internal/fs/streams.js:123:12)
at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
at ReadStream.deprecated [as open] (internal/util.js:70:15)
at ReadStream.open ([truncated]/node_modules/fs-capacitor/lib/index.js:90:11)
at _openReadFs (internal/fs/streams.js:123:12)
at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
at ReadStream.deprecated [as open] (internal/util.js:70:15)
at ReadStream.open ([truncated]/node_modules/fs-capacitor/lib/index.js:90:11)
at _openReadFs (internal/fs/streams.js:123:12)
at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
at ReadStream.deprecated [as open] (internal/util.js:70:15)
at ReadStream.open ([truncated]/node_modules/fs-capacitor/lib/index.js:90:11)
at _openReadFs (internal/fs/streams.js:123:12)
at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
at ReadStream.deprecated [as open] (internal/util.js:70:15)
at ReadStream.open ([truncated]/node_modules/fs-capacitor/lib/index.js:90:11)
Note: I am sure the image was sent correctly, as filename
is correct
Upvotes: 21
Views: 12930
Reputation: 11
TLDR: Default Apollo server file upload doesn't work in node >=13. Fix it by overwriting Apollo's server file upload with the graphql-upload
server file upload
npm install graphql-upload
Overwrite default Apollo Upload type in TypeDefs
const typeDefs = gql`
scalar Upload
...
`
Overwrite default Apollo Upload type in index.js
const { GraphQLUpload } = require('graphql-upload')
const { graphqlUploadExpress } = require('graphql-upload')
const express = require('express')
const app = express()
app.use(graphqlUploadExpress({
maxFileSize: 10000000,
maxFiles: 10
}))
const server = new ApolloServer({
typeDefs,
resolvers: {
Upload: GraphQLUpload,
...resolvers
}
uploads: false
...
})
server.applyMiddleware({
app
})
Upvotes: 1
Reputation: 1584
I've read the graphql-upload documentation but couldn't find one solid example that shows how to use graph-upload with apollo-server on NodeJS 14. Based on a sample application (that worked on the old graphql-upload version of apollo-server, failed on NodeJS 14) and answers from stack overflow I've managed to create a fully function example.
The original example: https://github.com/DNature/apollo-upload
I used apollo-server-express, instead of apollo-server.
With NodeJS 14, [email protected] and [email protected]:
index.js
import { ApolloServer } from "apollo-server-express";
import express from "express";
import { graphqlUploadExpress } from "graphql-upload";
import typeDefs from "./typeDefs";
import resolvers from "./resolvers";
// Import your database configuration
import connect from "./db";
export default (async function () {
try {
await connect.then(() => {
console.log("Connected 🚀 To MongoDB Successfully");
});
const server = new ApolloServer({
uploads: false, // Disables the bundled ApolloServer old graphql-upload that doesn't work on NodeJS 14
typeDefs,
resolvers,
});
await server.start();
const app = express();
app.use(graphqlUploadExpress({ maxFileSize: 1000000000, maxFiles: 10 }));
server.applyMiddleware({ app });
await new Promise((resolve) => app.listen({ port: 7000 }, resolve));
console.log(
`🚀 Server ready at http://localhost:7000${server.graphqlPath}`
);
} catch (err) {
console.error(err);
}
})();
In typeDefs.gql the scalar Upload needs to be defined:
import { gql } from "apollo-server-express";
export default gql`
scalar Upload
type File {
id: ID!
...
In resolvers.js the resolver for Upload needs to be defined:
...
import { GraphQLUpload } from 'graphql-upload';
...
export default {
Upload: GraphQLUpload,
Query: {
hello: () => "Hello world"
},
Mutation: {
...
Finally uploading from postman:
Upvotes: 1
Reputation: 1650
Add this to your package.json
"resolutions": {
"graphql-upload": "^11.0.0"
}
then add this inside scripts
"scripts": {
....
"preinstall": "npx npm-force-resolutions", //This one
....
}
then you need to do npm install. Done
Source: graphql-upload
Upvotes: 1
Reputation: 129
Since it is a bug with fs-capacitor, this would help as we can see in this issue
Worked for me in node 14.16.1 with the following configuration:
"resolutions": {
"fs-capacitor": "^6.2.0",
"graphql-upload": "^11.0.0"
}
I needed to add force-resolutions inside "scripts"
"scripts": {
....
"preinstall": "npx npm-force-resolutions"
}
Remove ./node_modules and install dependencies again with npm install.
Upvotes: 3
Reputation: 2015
I've been dealing with this problem multiple times
the problem is old graphql-upload more accurately version 8 uses of node open stream function which is deprecated and no longer available in 13.x and older node versions.
so the solution is you can either use nvm to set your node version to 12 or use resolutions in your package.json file. first solution(in your favorite terminal):
nvm install 12; nvm use 12
second solution(in package.json):
"resolutions": {
"**/**/fs-capacitor":"^6.2.0",
"**/graphql-upload": "^11.0.0"
}
also this is a problem I've been dealing with for months and apollo team really doesn't like updating their dependencies I think.
Upvotes: 0
Reputation: 837
Using:
"apollo-server": "^2.18.2",
"apollo-server-express": "2.18.2",
"aws-sdk": "^2.771.0",
"express-fileupload": "^1.2.0",
"graphql": "^15.3.0",
"graphql-upload": "^11.0.0",
"fs-capacitor": "^6.2.0",
I solve this by installing the latest fs-capacitor
as a dependency
yarn add fs-capacitor
Upvotes: -2
Reputation: 315
Add this to package.json:
"resolutions": {
"**/**/fs-capacitor":"^6.2.0",
"**/graphql-upload": "^11.0.0"
}
source: https://github.com/jaydenseric/graphql-upload/issues/170#issuecomment-641938198
Upvotes: 13
Reputation: 341
This error occured to me in node version 14 too! I solved it as follows:
Install latest version of graphql-upload !
use graphqlUploadExpress middleware to define the maximum file limit.
import { graphqlUploadExpress } from "graphql-upload";
const app = express()
app.use(graphqlUploadExpress({ maxFileSize: 1000000000, maxFiles: 10 }));
Set uploads to false while initializing the ApolloServer
const server = new ApolloServer({
uploads: false,
schema,
});
Upvotes: 9