Open MichalLytek opened 6 years ago
Hi,
Any news about this feature ?
I tried using https://github.com/jaydenseric/apollo-upload-server, i configured a upload resolver like this :
import {GraphQLUpload} from "apollo-upload-server";
...
@Mutation(returns => Media)
async upload(@Arg('file') file: GraphQLUpload): Promise<Media> {
// process upload
const media = this.repository.create({});
return await this.repository.save(media);
}
But i've got this error : UnhandledPromiseRejectionWarning: Error: You need to provide explicit type for UploadResolver#upload parameter #0
How to fix this error ? Thanks
https://19majkel94.github.io/type-graphql/docs/scalars.html#custom-scalars
You need to provide the scalar type to the @Arg
decorator due to limited TypeScript reflection capability. And the TS type is Upload
object, not the GQL scalar instance.
async upload(@Arg('file', type => GraphQLUpload) file: Upload): Promise<Media> {
Thanks @19majkel94 it works
@19majkel94 where do you import TS type Upload from?
@danpaugo
I've found some types definition in github issue:
https://github.com/jaydenseric/apollo-upload-server/issues/70
And I've enhanced them with Upload
interface:
declare module "apollo-upload-server" {
import { GraphQLScalarType } from "graphql";
import { RequestHandler } from "express";
import { Readable } from "stream";
export interface UploadMiddlewareOptions {
maxFieldSize?: number;
maxFileSize?: number;
maxFiles?: number;
}
export interface Upload {
stream: Readable;
filename: string;
mimetype: string;
encoding: string;
}
export const GraphQLUpload: GraphQLScalarType;
export function apolloUploadExpress(
options?: UploadMiddlewareOptions,
): RequestHandler;
}
I will try to upload this definition to DefinitelyTyped repo to make @types
work.
Hi , i still experience troubles with it the package now renamed graphql-upload should still be working but i keep having
the cannot find declaration types
issue despite the fact that i used the example shown above...it is like tsnode completely ignores the declaration files.
Here is the error i keep having. I use apollo-server 2.3.1 which comes embedded with graphql-upload 5new name for apollo-server-upload). Here is what i am getting as errors:
node:60159) UnhandledPromiseRejectionWarning: TSError: ⨯ Unable to compile TypeScript: src/GraphqlExpress/resolvers/FileUpload_resolver.ts(3,29): error TS7016: Could not find a declaration file for module 'graphql-upload'. '/Users/macbook/Desktop/Z-projects/GESSMS/node_modules/graphql-upload/lib/index.js' implicitly has an 'any' type. Try
npm install @types/graphql-upload
if it exists or add a new declaration (.d.ts) file containingdeclare module 'graphql-upload';
at createTSError (/Users/macbook/Desktop/Z-projects/GESSMS/node_modules/ts-node/src/index.ts:261:12)
at getOutput (/Users/macbook/Desktop/Z-projects/GESSMS/node_modules/ts-node/src/index.ts:367:40)
at Object.compile (/Users/macbook/Desktop/Z-projects/GESSMS/node_modules/ts-node/src/index.ts:558:11)
at Module.m._compile (/Users/macbook/Desktop/Z-projects/GESSMS/node_modules/ts-node/src/index.ts:439:43)
at Module._extensions..js (module.js:663:10)
at Object.require.extensions.(anonymous function) [as .ts] (/Users/macbook/Desktop/Z-projects/GESSMS/node_modules/ts-node/src/index.ts:442:12)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Module.require (module.js:596:17)
(node:60159) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 4) (node:60159) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate theNode.js process with a non-zero exit code.
Can you help me please?
@zjjt
it is like tsnode completely ignores the declaration files.
Can you help me please?
It's not a problem with TypeGraphQL itself.
Please read the docs for ts-node
or open an issue in ts-node
repository.
@19majkel94 thank you for replying.
@daviddlv have you a example? for upload with scalar on type-graphql?
@johinsDev , here an example of my resolver : https://gist.github.com/daviddlv/0259ce8b64a3e23611a96b0c52c27a27
@johinsDev , here an example of my resolver : https://gist.github.com/daviddlv/0259ce8b64a3e23611a96b0c52c27a27
thanks, its cool. but what have you FileInput?
I put the FileInput file in the gist
@daviddlv @19majkel94
I tried to use your gist, but I'm getting (node:18235) UnhandledPromiseRejectionWarning: Error: Cannot determine GraphQL input type for stream
.
import { Stream } from 'stream';
import { Field, InputType, Int } from 'type-graphql';
@InputType()
export class FileInput {
@Field(type => Stream) // <<== the problem
stream: Stream;
@Field() filename: string;
@Field() mimetype: string;
@Field() encoding: string;
}
Here's the js output:
const type_graphql_1 = require("type-graphql");
const stream_1 = require("stream");
let FileInput = class FileInput {
};
__decorate([
type_graphql_1.Field(type => stream_1.Stream),
__metadata("design:type", stream_1.Stream)
], FileInput.prototype, "stream", void 0);
__decorate([
type_graphql_1.Field(),
__metadata("design:type", String)
], FileInput.prototype, "filename", void 0);
__decorate([
type_graphql_1.Field(),
__metadata("design:type", String)
], FileInput.prototype, "mimetype", void 0);
__decorate([
type_graphql_1.Field(),
__metadata("design:type", String)
], FileInput.prototype, "encoding", void 0);
FileInput = __decorate([
type_graphql_1.InputType()
], FileInput);
exports.FileInput = FileInput;
@laukaichung All you need is:
@Arg('file', type => GraphQLUpload)
file: FileInput
the FileInput
might be just an TS interface, no need for an @InputType
because it won't work.
hi @19majkel94 , i have issue,, with arg type of array, here is example:
@ArgsType()
export class XArg {
@Field()
name: string;
@Field({ nullable: true })
value?: string;
}
// resolver
@Mutation(returns => Response)
async xCreate(
@Ctx() context: Context,
@Arg("xarr") xarr: Array<XArg>
): Promise<ResponseInterface> {}
Error:
You need to provide explicit type for XResolver#xCreate parameter #1
thanks before
@sgtkuncoro
provide explicit type
@Arg("xarr", type => [XArg]) xarr
Working solution for me:
import { Resolver, Mutation, Arg } from 'type-graphql'
import { GraphQLUpload, FileUpload } from 'graphql-upload'
import os from 'os'
import { createWriteStream } from 'fs'
import path from 'path'
@Resolver()
export default class SharedResolver {
@Mutation(() => ImageResource)
async uploadImage(
@Arg('file', () => GraphQLUpload)
file: FileUpload
): Promise<ImageResource> {
const { createReadStream, filename } = await file
const destinationPath = path.join(os.tmpdir(), filename)
const url = await new Promise((res, rej) =>
createReadStream()
.pipe(createWriteStream(destinationPath))
.on('error', rej)
.on('finish', () => {
// Do your custom business logic
// Delete the tmp file uploaded
unlink(destinationPath, () => {
res('your image url..')
})
})
)
return {
url
}
}
}
Thank you for proposed solution @andfk @daviddlv . It seems to be working until I try to upload more than 10 files at once. In that case I am getting this warning:
MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 exit listeners added. Use emitter.setMaxListeners() to increase limit
demo: | at _addListener (events.js:280:19)
demo: | at process.addListener (events.js:297:10)
demo: | at _fs.default.open (***/node_modules/fs-packages/api/capacitor/lib/index.js:140:17)
demo: | at FSReqWrap.oncomplete (fs.js:135:15)
My resolver looks like this:
const fs = require('fs');
import { UploadResult } from '../graphql/models/file';
import { GraphQLUpload, FileUpload } from 'graphql-upload';
import { Resolver, Mutation, Arg } from 'type-graphql';
import isArray from 'lodash/isArray';
@Resolver()
class FileResolver {
@Mutation(() => UploadResult)
async fileUpload(@Arg('fileInput', () => GraphQLUpload) fileInput: FileUpload): Promise<UploadResult> {
let readableStreams = [];
if (isArray(fileInput)) {
readableStreams = await Promise.all(fileInput);
} else {
readableStreams[0] = await fileInput;
}
const pipedStreams = readableStreams.map((readStreamInstance) => {
const { filename, createReadStream } = readStreamInstance;
const writableStream = fs.createWriteStream(`./${filename}`, { autoClose: true });
return new Promise<string>((resolve, reject) => {
createReadStream()
.pipe(writableStream)
.on('error', (error: any) => {
reject(error);
})
.on('finish', () => {
resolve(filename);
});
})
});
const results = await Promise.all(pipedStreams);
return {
uploaded: results
}
}
}
The warning gets fired even if I comment-out the whole resolver-function body and just return some random string array. So I suspect that the error is not coming from the resolver itself. It's rather coming from some underlying implementation.
Does anybody has similar problem?
So the warning is coming from eventemitter which is used by nodejs streams. You can bypass the warning by require('events').EventEmitter.defaultMaxListeners = uploadMultipleMaxFiles;
I wanted to be sure that I don't have any memory leakage, so I wrote a "test" with multiple uploads - https://gist.github.com/jordan-jarolim/4d374c1b864de4c6321f611f748dc5bd and check memory management using --expose-gc --inspect=9222
flags for node process and chrome://inspect tool.
Would love to use this, but when I tried I got this error message:
Error: This implementation of ApolloServer does not support file uploads because the environment cannot accept multi-part forms
This happens when I try to set the uploads
key on the new ApolloServer
I'm creating. Without it, I get a invalid json
error. Any ideas?
Apollo Server version? Apolo + express, + koa ...?
Hey guys, @andfk implementation does not work for me. It fails with this message: got invalid value {}; Expected type Upload. Upload value invalid.
This is what my resolver looks like:
import { Resolver, Mutation, Arg, Int } from 'type-graphql';
import { GraphQLUpload, FileUpload } from 'graphql-upload';
@Resolver()
export class UploadResolver {
@Mutation(_ => Int)
singleUpload(@Arg('file', () => GraphQLUpload) file: FileUpload) {
console.log(file);
return 3;
}
}
This is the query I execute (I have also tried in the app with same result):
curl localhost:3333/graphql \
-F operations='{ "query": "mutation ($file: Upload!) { singleUpload(file: $file) }", "variables": { "file": null } }' \
-F map='{ "0": ["variables.file"] }' \
-F 0=@wsebr3bveoy31.png
{
"errors": [
{
"message":"Variable \"$file\" got invalid value {}; Expected type Upload. Upload value invalid.",
"locations":[{"line":1,"column":11}],
"extensions":{"code":"INTERNAL_SERVER_ERROR",
"exception": {
"message":"Upload value invalid.",
"stacktrace":[
"GraphQLError: Upload value invalid.",
" at GraphQLScalarType.parseValue (/project/node_modules/graphql-upload/lib/GraphQLUpload.js:66:11)",
" at coerceInputValueImpl
[-- snip --]
The relevant dependencies as follows:
"apollo-server-express": "^2.10.0",
"express": "4.17.1",
"graphql": "^14.6.0",
"graphql-tag": "^2.10.3",
"graphql-upload": "^10.0.0",
Am I missing something?
FWIW, here is the React implementation of upload, that returns the same error:
import React from 'react';
import { useApolloClient, useMutation } from '@apollo/react-hooks';
import gql from 'graphql-tag';
const SINGLE_UPLOAD_MUTATION = gql`
mutation singleUpload($file: Upload!) {
singleUpload(file: $file)
}
`;
export const UploadFile = () => {
const [uploadFileMutation] = useMutation(SINGLE_UPLOAD_MUTATION);
const apolloClient = useApolloClient();
const onChange = ({
target: {
validity,
files: [file]
}
}) =>
validity.valid &&
uploadFileMutation({ variables: { file } }).then(() => {
apolloClient.resetStore();
});
return <input type="file" required onChange={onChange} />;
};
@naishe have you added the express middleware?
Yes, I like this:
const app = express();
// -- snip --
apolloServer.applyMiddleware({ app });
I think I figured the problem. import { GraphQLUpload, FileUpload } from 'graphql-upload';
was the issue. It seems the graphql-upload
library is not needed with the latest Apollo Server. The following code works:
import { Resolver, Mutation, Arg, Int } from 'type-graphql';
import { GraphQLUpload } from 'apollo-server-express';
export interface FileUpload {
filename: string;
mimetype: string;
encoding: string;
createReadStream(): ReadStream;
}
@Resolver()
export class UploadResolver {
@Mutation(_ => Int)
async singleUpload(@Arg('file', () => GraphQLUpload) file: FileUpload) {
console.log(file);
return 4; // ideally, you'd return something sensible like an URL
}
Yes, apollo server has this built-in. For other cases, you need to apply the upload middleware:
express()
.use(
'/graphql',
graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 }),
graphqlHTTP({ schema })
)
.listen(3000)
apollo-server-express
use the version 8 of graphql-upload
and it not support node version 13
throwing this error Maximum call stack size exceeded
this error solved in graphql-upload
in this issues
but when we install the new version of graphql-upload
the server response with throwing got invalid value {}; Expected type Upload. Upload value invalid.
when i host graphql-upload
on monorepo for using the right version of that type-graphql
throwing this error : Cannot determine GraphQL input type for image
I solved this with disabling apollo-server
upload property :
const apolloServer = new ApolloServer({
schema,
context: ({ req }) => ({ req }),
introspection: true,
uploads: false // disable apollo upload property
});
install the new version of graphql-upload
: yarn add graphql-upload
Setup the graphql-upload middleware.
const app = Express();
app.use(graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 }));
apolloServer.applyMiddleware({
app
});
and then setup the upload mutation
:
import { Resolver, Mutation, Arg, Int } from 'type-graphql';
import { GraphQLUpload, FileUpload } from "graphql-upload";
import { createWriteStream } from "fs";
@Resolver()
export class UploadResolver {
@Mutation(_ => Promise<Boolean>)
async singleUpload(@Arg('file', () => GraphQLUpload) file: FileUpload) {
const { createReadStream, filename } = await file;
const writableStream = createWriteStream(
`${__dirname}/../../../files/images/${filename}`,
{ autoClose: true }
);
return new Promise((res, rej) => {
createReadStream()
.pipe(writableStream)
.on("finish", () => res(true))
.on("error", () => rej(false));
});
}
I solved this with disabling
apollo-server
upload property :const apolloServer = new ApolloServer({ schema, context: ({ req }) => ({ req }), introspection: true, uploads: false // disable apollo upload property });
install the new version of
graphql-upload
:yarn add graphql-upload
Setup the graphql-upload middleware.
const app = Express(); app.use(graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 })); apolloServer.applyMiddleware({ app });
and then setup the upload
mutation
:import { Resolver, Mutation, Arg, Int } from 'type-graphql'; import { GraphQLUpload, FileUpload } from "graphql-upload"; import { createWriteStream } from "fs"; @Resolver() export class UploadResolver { @Mutation(_ => Promise<Boolean>) async singleUpload(@Arg('file', () => GraphQLUpload) file: FileUpload) { const { createReadStream, filename } = await file; const writableStream = createWriteStream( `${__dirname}/../../../files/images/${filename}`, { autoClose: true } ); return new Promise((res, rej) => { createReadStream() .pipe(writableStream) .on("finish", () => res(true)) .on("error", () => rej(false)); }); }
This solution worked for me, make sure you guys have created the folder where the files will be uploaded, otherwise you'll get an error
@hemedani
But how?
When I copy your code I get this on the Promise<Boolean>
line:
Value of type 'PromiseConstructor' is not callable. Did you mean to include 'new'?
I finally think I have tested all possible here posted solutions, but end up all the time with this error. Has anybody the same problem or is it just me?
(node:20149) UnhandledPromiseRejectionWarning: Error: Cannot determine GraphQL output type for stream at Function.getGraphQLOutputType (..../node_modules/type-graphql/dist/schema/schema-generator.js:395:19)
Edit: NVM, it came from another Module, where I used Buffer as type 🤦♂️
@theerfan just use @Mutation( () => Boolean )
without Promise constructor
Please help I am getting "Variable \"$file\" got invalid value {}; Upload value invalid." when calling mutation from apollo client
import { Mutation, Resolver, Args, Query, FieldResolver, Root, Arg } from 'type-graphql';
import { Person, FindManyWorkerArgs, Position } from 'prisma/generated/type-graphql';
import { PersonService } from '../services/person.service';
import { CreateWorkerArgs, UpdateWorkerArgs } from '../dtos/person.input';
import { Worker, File } from 'prisma/generated/type-graphql'
import { GraphQLUpload, FileUpload } from 'graphql-upload';
import { PaginatedWorker } from '../dtos/paginated-person.type';
import { WorkerService } from '../services/worker.service';
import { PositionService } from 'src/position/services/position.service';
import { Inject } from 'typedi';
import { BadRequestException } from '@nestjs/common';
@Resolver(of => Worker)
export class WorkerResolver {
constructor(
private readonly workerService: WorkerService,
private readonly personService: PersonService,
private readonly positionService: PositionService
) { }
@Mutation(returns => Worker)
async createWorker(@Args() args: CreateWorkerArgs, @Arg('file', type => GraphQLUpload, { nullable: true }) file?: FileUpload): Promise<Worker> {
return this.workerService.createWorker(args.data , file);
}
}
Solution found: Importing GraphQLUpload from apollo-server and FileUpload from graphql-upload solved the problem
Not working for me on Node.js v14.6.0. Have basically tried every combination, but keep getting the following error:
[GraphQL Error]: {
"message": "Missing multipart field ‘operations’ (https://github.com/jaydenseric/graphql-multipart-request-spec).",
"extensions": {
"code": "INTERNAL_SERVER_ERROR"
}
}
Running the following cURL command (notice how "operations" is clearly specified):
curl --location --request POST 'http://localhost:4000/graphql' \
--header 'Accept-Encoding: gzip, deflate, br' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Connection: keep-alive' \
--header 'DNT: 1' \
--header 'Origin: http://localhost:4000' \
--form 'operations={"query":"mutation($file: Upload!) {\n uploadRandomFile(file:$file)\n}"}' \
--form 'map={"0": ["variables.file"]}' \
--form '0=@/C:/Users/somepic.png'
Resolver
import { GraphQLUpload, FileUpload } from "graphql-upload";
import { createWriteStream } from "fs";
@Mutation(returns => Boolean)
async uploadRandomFile(@Arg("file", () => GraphQLUpload)
{
createReadStream,
filename,
}: FileUpload) {
return new Promise(async (resolve, reject) =>
createReadStream()
.pipe(createWriteStream(`${__dirname}/../../../uploads/${filename}`, { autoClose: true }))
.on("finish", () => resolve(true))
.on("error", () => reject(false))
);
}
Any ideas?
EDIT: I'm an idiot, turns out I had accidentally put the uploads: false
inside context
in the ApolloServer constructor. All working now
Great examples here. My question is around a multi-part form submission. Do you have multiple Args in this case, or create an input with a property of GraphQLUpload ?
Hello guys, I am having trouble to get the file upload working. Only a fraction of file gets uploaded. And my mutation resolver returning null instead of boolean.
// PostResolver.ts
@Mutation(() => Boolean)
@UseMiddleware(isAuth)
async addPost(
@Arg('file', () => GraphQLUpload)
file: FileUpload
): Promise<boolean> {
const { filename, createReadStream } = file;
console.log(file);
const uploadTime = new Date().toISOString();
const pathName = path.join(
__dirname,
`../../images/${uploadTime}_${filename}`
);
return new Promise((resolve, reject) =>
createReadStream()
.pipe(createWriteStream(pathName, { autoClose: true }))
.on('finish', () => resolve(true))
.on('error', () => reject(false))
);
}
A help will be appreciated. :pray:
@aseerkt I have the same problem, finally I use sharp to save the file in the server.
const getBuffer = (file: FileUpload) => {
const stream = file.createReadStream();
return new Promise<Buffer>((resolve, reject) => {
const buffers: Buffer[] = [];
stream.on('error', (error) => reject(error));
stream.on('data', (data: Buffer) => buffers.push(data));
stream.on('end', () => resolve(Buffer.concat(buffers)));
});
};
const imageBuffer = await getBuffer(file);
await sharp(imageBuffer).toFile(`uploads/images/${image.fileName()}`);
How can we use with with form data with other fields.
For example: A form that has an image, title, description
The examples above all gibe me the following error: Error: There can be only one type named "Upload". because Apollo has its own upload feature since 2.0. How can I use this in here?
The examples above all gibe me the following error: Error: There can be only one type named "Upload". because Apollo has its own upload feature since 2.0. How can I use this in here?
As @hemedani pointed out, try setting uploads: false
in your ApolloServer config.
Please help I am getting "Variable "$file" got invalid value {}; Upload value invalid." when calling mutation from apollo client
import { Mutation, Resolver, Args, Query, FieldResolver, Root, Arg } from 'type-graphql'; import { Person, FindManyWorkerArgs, Position } from 'prisma/generated/type-graphql'; import { PersonService } from '../services/person.service'; import { CreateWorkerArgs, UpdateWorkerArgs } from '../dtos/person.input'; import { Worker, File } from 'prisma/generated/type-graphql' import { GraphQLUpload, FileUpload } from 'graphql-upload'; import { PaginatedWorker } from '../dtos/paginated-person.type'; import { WorkerService } from '../services/worker.service'; import { PositionService } from 'src/position/services/position.service'; import { Inject } from 'typedi'; import { BadRequestException } from '@nestjs/common'; @Resolver(of => Worker) export class WorkerResolver { constructor( private readonly workerService: WorkerService, private readonly personService: PersonService, private readonly positionService: PositionService ) { } @Mutation(returns => Worker) async createWorker(@Args() args: CreateWorkerArgs, @Arg('file', type => GraphQLUpload, { nullable: true }) file?: FileUpload): Promise<Worker> { return this.workerService.createWorker(args.data , file); } }
look at this
Please help I am getting "Variable "$file" got invalid value {}; Upload value invalid." when calling mutation from apollo client
import { Mutation, Resolver, Args, Query, FieldResolver, Root, Arg } from 'type-graphql'; import { Person, FindManyWorkerArgs, Position } from 'prisma/generated/type-graphql'; import { PersonService } from '../services/person.service'; import { CreateWorkerArgs, UpdateWorkerArgs } from '../dtos/person.input'; import { Worker, File } from 'prisma/generated/type-graphql' import { GraphQLUpload, FileUpload } from 'graphql-upload'; import { PaginatedWorker } from '../dtos/paginated-person.type'; import { WorkerService } from '../services/worker.service'; import { PositionService } from 'src/position/services/position.service'; import { Inject } from 'typedi'; import { BadRequestException } from '@nestjs/common'; @Resolver(of => Worker) export class WorkerResolver { constructor( private readonly workerService: WorkerService, private readonly personService: PersonService, private readonly positionService: PositionService ) { } @Mutation(returns => Worker) async createWorker(@Args() args: CreateWorkerArgs, @Arg('file', type => GraphQLUpload, { nullable: true }) file?: FileUpload): Promise<Worker> { return this.workerService.createWorker(args.data , file); } }
look at this
check this link https://stackoverflow.com/questions/60059940/graphql-apollo-upload-in-nestjs-returns-invalid-value
In nextjs, I have this error
with this config
what Im doing wrong ?
I suspect your problem is around your read and write streams, I don't think it has to do with typegraphql and uploading files ?
I read the files in as follows - but I write to S3 bucket (setting the body using createReadStream() which doesn't really help you for that). I'd look into making sure you're using the create read/write streams correctly. Some snippets from how I do it:
@Arg('files', () => GraphQLUpload) files: FileUpload[]
export interface FileUpload { filename: string; mimetype: string; encoding: string; createReadStream(): ReadStream; }
const readableStreams = await Promise.all(files);
const pipedStreams = readableStreams.map((readStreamInstance) => { const { filename, createReadStream } = readStreamInstance;
On Fri, Sep 17, 2021 at 5:16 AM SedkiDataBank @.***> wrote:
I am getting an unresolved error, anyone can take a look? tyvm
{ "errors": [ { "message": "Unexpected error value: false", "locations": [ { "line": 2, "column": 3 } ], "path": [ "addCandidateResume" ], "extensions": { "code": "INTERNAL_SERVER_ERROR", "exception": { "stacktrace": [ "Error: Unexpected error value: false", " at asErrorInstance (/Users/sed9ydatabank/Documents/real-deal/ovice-rms/ovice-rms-server/node_modules/graphql/execution/execute.js:516:10)", " at processTicksAndRejections (internal/process/task_queues.js:95:5)" ] } } } ], "data": null }
import { Resolver, Mutation, Arg } from "type-graphql";import { GraphQLUpload, FileUpload } from "graphql-upload";import { createWriteStream } from "fs";
@Resolver()export class CandidateResumeResolver { @Mutation(() => Boolean) async addCandidateResume( @Arg("resume", () => GraphQLUpload) { createReadStream, filename }: FileUpload ): Promise
{ return new Promise(async (resolve, reject) => createReadStream() .pipe(createWriteStream(__dirname + /../../../resumes/${filename}
)) .on("finish", () => { resolve(true); }) .on("error", () => reject(false)) ); }}const apolloServer = new ApolloServer({ schema, uploads: false });
app.use(graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 }));
I have created a resumes folder but I am getting this error.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MichalLytek/type-graphql/issues/37#issuecomment-921642395, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABAKNFBF5PKIJKSO6TR2PLUCMBPTANCNFSM4ETHD66Q . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
Hi guys i have a similar problem when I load images with a resolver in GraphQL using a inputType class in NestJS, I get 0-byte files when i upload to s3. However, if I add everything as args, the files arrive correctly, I don't see too many differences, what could be the problem?
**mutation:**
@Mutation(() => Course)
async addResources(
@Args({ name: 'input', type: () => CreateResources }) input: CreateResources,
@CurrentUser() user: User
) {
const type = EXTRARESOURCES;
const result = await this.courseService.addExtraResources(
user,
input,
type
);
if (!result) errorInvalidInput(type);
return result;
}
inputType files arrive with 0 bytes
@InputType()
export class CreateResources {
@IsOptional()
@Field(() => [CreateResourceLinkInput], { nullable: true })
links: CreateResourceLinkInput[];
@IsOptional()
@Field(() => [CreateResourceVideoInput], { nullable: true })
videos: CreateResourceVideoInput[];
@IsOptional()
@Field(() => [GraphQLUpload], { nullable: true })
documents: Promise<[FileUpload]>;
@IsOptional()
@Field(() => [GraphQLUpload], { nullable: true })
images: Promise<[FileUpload]>;
}
All as args works fine
@Mutation(() => Course)
async AddResources(
@Args({ name: 'links', type: () => [CreateResourceLinkInput], nullable: true }) links: [CreateResourceLinkInput],
@Args({ name: 'videos', type: () => [CreateResourceVideoInput], nullable: true }) videos: [CreateResourceVideoInput],
@Args({ name: 'documents', type: () => [GraphQLUpload], nullable: true }) documents: [FileUpload],
@Args({ name: 'images', type: () => [GraphQLUpload], nullable: true }) images: [FileUpload],
@CurrentUser() user: User
) {
const type =EXTRARESOURCES;
const input = {
links,
videos,
documents,
images
};
const result = await this.courseService.addExtraResources(
user,
input,
type
);
if (!result) errorInvalidInput(type);
return result;
}
in NestJS
@SergioSuarezDev So you should ask on Nest github/discord as their implementation is quite different from TypeGraphQL.
Since apollo-upload-server is deprecated, how can we move on with apollo-upload did anyone find a way dealing with apollo-upload when it comes to file uploads ?
Packages:
"@apollo/server": "^4.3.0",
"fastify": "^4.11.0",
"@as-integrations/fastify": "^1.2.0",
"graphql-upload-ts": "^2.0.5",
I use graphql-upload-ts
for implementarion TypeScript
by graphql-upload
Mutation
import { FileUpload, GraphQLUpload } from 'graphql-upload-ts'
@Mutation(() => Boolean)
async uploadService(
@Arg('picture', () => GraphQLUpload)
{ createReadStream, filename }: FileUpload
) {
return new Promise(async (resolve, reject) =>
createReadStream()
.pipe(createWriteStream(__dirname + '/' + filename))
.on('finish', () => resolve(true))
.on('error', () => reject(false)),
)
}
Receiver error:
{
"errors": [
{
"message": "Variable \"$picture\" got invalid value {}; Upload value invalid.",
"locations": [
{
"line": 1,
"column": 24
}
],
"extensions": {
"code": "BAD_USER_INPUT",
"stacktrace": [
"GraphQLError: Variable \"$picture\" got invalid value {}; Upload value invalid.",
" at /home/psoeng/www/pso-easynr10/node_modules/graphql/execution/values.js:147:11",
" at coerceInputValueImpl (/home/psoeng/www/pso-easynr10/node_modules/graphql/utilities/coerceInputValue.js:154:9)",
" at coerceInputValueImpl (/home/psoeng/www/pso-easynr10/node_modules/graphql/utilities/coerceInputValue.js:49:14)",
" at coerceInputValue (/home/psoeng/www/pso-easynr10/node_modules/graphql/utilities/coerceInputValue.js:32:10)",
" at coerceVariableValues (/home/psoeng/www/pso-easynr10/node_modules/graphql/execution/values.js:132:69)",
" at getVariableValues (/home/psoeng/www/pso-easynr10/node_modules/graphql/execution/values.js:45:21)",
" at buildExecutionContext (/home/psoeng/www/pso-easynr10/node_modules/graphql/execution/execute.js:280:63)",
" at execute (/home/psoeng/www/pso-easynr10/node_modules/graphql/execution/execute.js:116:22)",
" at executeIncrementally (/home/psoeng/www/pso-easynr10/node_modules/@apollo/server/src/incrementalDeliveryPolyfill.ts:109:17)",
" at processTicksAndRejections (node:internal/process/task_queues:95:5)"
]
}
}
]
}
All solutions posted here, dont work for me. Any solutions fot this? thx
@Tjerk-Haaye-Henricus You finded any solutions for your problem?
Integration with https://github.com/jaydenseric/apollo-upload-server