I'm trying to do file uploads using a fastify
server using mercurius
, type-graphql
and mercurius-upload
plugin. Here is my server code:
import "reflect-metadata";
import "dotenv/config";
import _ from "node-env-types";
import Fastify from "fastify";
import mercurius from "mercurius";
import { buildSchema } from "type-graphql";
import { CtxType } from "./types";
import { resolvers } from "./resolvers";
import { PrismaClient } from "@prisma/client";
import cors from "@fastify/cors";
import cookie from "@fastify/cookie";
import { tokenRoute } from "./routes/token";
import fastifyStatic from "@fastify/static";
import path from "path";
import MercuriusGQLUpload from "mercurius-upload";
_();
const PORT: any = process.env.PORT || 3001;
const HOST =
process.env.NODE_ENV === "production"
? "0.0.0.0"
: "localhost" || "127.0.0.1";
(async () => {
const fastify = Fastify({
logger: false,
ignoreTrailingSlash: true,
});
const prisma = new PrismaClient();
const schema = await buildSchema({
resolvers,
validate: false,
});
fastify.register(cors, {
credentials: true,
origin: ["http://localhost:3000"],
});
fastify.register(cookie, {
secret: "my-secret",
parseOptions: {
sameSite: "lax",
httpOnly: false,
secure: false,
maxAge: 1000 * 60 * 60 * 24 * 7,
},
});
fastify.register(fastifyStatic, {
root: path.join(__dirname.replace("dist", ""), "storage"),
prefixAvoidTrailingSlash: true,
prefix: "/petmall/api/storage",
});
fastify.register(MercuriusGQLUpload, {});
fastify.register(tokenRoute);
fastify.register(mercurius, {
context: (request, reply): CtxType => {
return {
request,
reply,
prisma,
};
},
graphiql: true,
schema: schema as any,
errorHandler(error, request, reply) {
console.log(error);
console.error(error.message);
},
});
fastify.listen({ port: PORT, host: HOST }, (error, address) => {
if (error) {
console.error(error);
process.exit(1);
}
console.log(` Server is now listening on ${address}`);
});
})();
Here is my PetResolver
import { Arg, Mutation, Resolver } from "type-graphql";
import { NewPetInputType } from "./inputs/inputTypes";
@Resolver()
export class PetResolver {
@Mutation(() => Boolean)
async add(@Arg("input", () => NewPetInputType) { image }: NewPetInputType) {
console.log(image);
return true;
}
}
Here in my NewPetInputType
import { InputType, Field, Float, Int, registerEnumType } from "type-graphql";
import { Category, Gender } from "../../../types";
import GraphQLUpload from "graphql-upload/GraphQLUpload.js";
import { FileUpload } from "graphql-upload/Upload";
registerEnumType(Gender, {
name: "Gender", // this one is mandatory
});
registerEnumType(Category, {
name: "Category", // this one is mandatory
});
@InputType()
export class LocationInput {
@Field(() => String, { nullable: true })
district?: string;
@Field(() => String, { nullable: true })
city?: string;
@Field(() => String, { nullable: true })
street?: string;
@Field(() => String, { nullable: true })
region?: string;
@Field(() => String, { nullable: true })
country?: string;
@Field(() => String, { nullable: true })
postalCode?: string;
@Field(() => String, { nullable: true })
subregion?: string;
@Field(() => String, { nullable: true })
timezone?: string;
@Field(() => String, { nullable: true })
streetNumber?: string;
@Field(() => String, { nullable: true })
name?: string;
@Field(() => String, { nullable: true })
isoCountryCode?: string;
}
@InputType()
export class NewPetInputType {
@Field(() => GraphQLUpload)
image: FileUpload;
@Field(() => LocationInput, { nullable: true })
location?: LocationInput;
@Field(() => String, { nullable: false })
description: string;
@Field(() => Category, { nullable: false })
category: Category;
@Field(() => Gender, { nullable: false })
gender: Gender;
@Field(() => Float, { nullable: false })
price: number;
@Field(() => Int, { nullable: false })
age: number;
@Field(() => String, { nullable: false })
name: string;
}
On the client I'm using React-Native
and URQL
but when I submit to the file to the server I'm getting the following error.
errors: [
GraphQLError: Variable "$input" got invalid value { uri: "file:///var/mobile/Containers/Data/Application/6833698F-0EB9-4FCE-AD0F-8DBE529CC55C/Library/Caches/ExponentExperienceData/%2540crispen_dev%252Fmobile/ImagePicker/2DD6F719-DD56-444B-A486-E272FC67793A.jpg", name: "IMG_6129.jpg", type: "image/png" } at "input.image"; Upload value invalid.
....
Graphql validation error
What maybe possibly the problem here?