Missing multipart field ‘operations’ with graphql-upload and apollo-server - node.js

Hello I am trying to upload a file using graphql in order to do this I have the following code:
index.js
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const { graphqlUploadExpress } = require('graphql-upload');
async function startApolloServer() {
const resolvers = {
Query: {
hello: () => 'Hello world!',
},
Mutation: {
singleUpload: async (parent, { file }) => {
const { createReadStream, filename, mimetype, encoding } = await file;
const stream = createReadStream();
const out = require('fs').createWriteStream(filename);
stream.pipe(out);
return { filename, mimetype, encoding, url: '' }
}
}
};
const server = new ApolloServer({
typeDefs:gql`
type Query {
hello: String!
}
type UploadedFileResponse {
filename: String!
mimetype: String!
encoding: String!
url: String!
}
type Mutation {
singleUpload(file: Upload!): UploadedFileResponse!
}`
, resolvers },{uploads:false});
await server.start();
const app = express();
app.use(graphqlUploadExpress({ maxFileSize: 1000000000, maxFiles: 10 }));
server.applyMiddleware({ app });
await new Promise(resolve => app.listen({ port: 4000 }, resolve));
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
return { server, app };
}
startApolloServer()
And in order to call the endpoint I am using the following curl:
curl localhost:4000/graphql \
-F operations='{ "query": "mutation ($file: Upload!) { singleUpload(file: $file) { filename } }", "variables": { "file": null } }' \
-F map='{ "0": ["variables.file"] }' \
-F 0=#/home/user/a.txt
But when I execute this I got the following error:
Missing multipart field ‘operations’
If I remove app.use(graphqlUploadExpress({ maxFileSize: 1000000000, maxFiles: 10 }));
I got another error
function deprecated(...args) {
RangeError: Maximum call stack size exceeded
But in this case I can write a empty file with the correct name.
Any idea about how can I finish this poc in order to upload a file using apollo-graphql.
Package.json
"dependencies": {
"apollo-server": "^2.25.2",
"apollo-server-express": "^2.25.2",
"graphql": "^15.5.1",
"graphql-upload": "^12.0.0"
},
"devDependencies": {
"nodemon": "^2.0.12"
},
But I tried whit this too
"resolutions": {
"**/**/fs-capacitor": "^6.2.0",
"**/graphql-upload": "^11.0.0"
}
Node version: 14.16.1 and 14.17.3
Thanks

In your typDefs, add: scalar Upload
In resolvers, add: Upload: GraphQLUpload
GraphQLUpload is imported from 'graphql-upload': import { GraphQLUpload } from "graphql-upload";

Related

Apollo GraphQL cannot query _service

I'm new in GraphQL. When I copied this code from Apollo GraphQL docs (and just add one more line for console.log error), I have this issue. Please let me know how to fix it.
const { ApolloServer, gql } = require('apollo-server-express');
const express = require('express');
const typeDefs = gql`
type Book {
title: String
author: String
}
type Query {
books: [Book]
}
`;
const books = [
{
title: 'The Awakening',
author: 'Kate Chopin',
},
{
title: 'City of Glass',
author: 'Paul Auster',
},
];
const resolvers = {
Query: {
books: () => books,
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
formatError: (err) => console.log(err), // <-- only add 1 more line
});
(async () => {
const app = express();
await server.start();
server.applyMiddleware({ app });
app.listen(4000);
})();
And here is my package.json
"dependencies": {
"apollo-server-express": "^3.6.3",
"express": "^4.17.2",
"graphql": "^16.3.0"
}
Then, when I open graphql studio playground at http://localhost:4000/graphql -> click on Query your server -> I got this error on terminal
[ValidationError: Cannot query field "_service" on type "Query".] {
locations: [ { line: 2, column: 9 } ],
path: undefined,
extensions: {
code: 'GRAPHQL_VALIDATION_FAILED',
exception: { stacktrace: [Array] }
}
}```
I have checked again and this is an error from inside GrapqhQL Studio and it was fixed now.

Apollo Uploading Files, createReadStream is not a function

I tried to get this working for several days and getting now where. I do believe that that the client side is function properly but I'm not hundred percent certain. I know the resolver on the server is getting called. At one point I was able to destructure the file param in the resolver. But now when I destructure, I get undefined. Not sure what is up with that at one point it was destructuring just fine. The client project is setup to connect to two different GraphQL servers, one is for standard database and subscriptions and the other is file uploader. That is why I left the subscription in the dependences of the client.
I wanna say thank you for taking the time to look at this.
My Server Version Info
"#graphql-tools/schema": "^7.1.5",
"apollo-cache-inmemory": "^1.6.6",
"apollo-server-express": "^2.25.0",
"express": "^4.17.1",
"express-jwt": "^6.0.0",
"graphql": "^15.5.0",
"graphql-middleware": "^6.0.10",
"graphql-shield": "^7.5.0",
"graphql-upload": "^12.0.0",
My Main File
import { ApolloError, ApolloServer, makeExecutableSchema } from "apollo-server-express"
import { applyMiddleware } from "graphql-middleware"
import express from "express"
import { graphqlUploadExpress } from 'graphql-upload'
import makeDir from 'make-dir'
const app = express()
const cors = require('cors')
app.use(cors())
const bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.use(graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 }));
const apolloServer = new ApolloServer({
uploads: false,
...
schema: applyMiddleware(
makeExecutableSchema({ typeDefs, resolvers }),
permissions
),
context: ({ req, res }) => {
...
},
});
apolloServer.applyMiddleware({ app });
...
async function StartServer() {
await makeDir(UPLOAD_DIR)
app.listen({ host: HOST, port: PORT }, () => {
console.log(`
🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀
Apollo File Server ready at http://${HOST}:${PORT}${apolloServer.graphqlPath}
Started at ${datetime}
isDevelopmentMode ${isDevelopmentMode}
`)
});
}
StartServer()
My Schema
type File {
name: String!
size: Int!
}
extend type Mutation {
singleUpload(file: Upload!): File!,
}
My Resolver
singleUpload: async (parent, { file }) => {
console.log('singleUpload------------------------------------------------------------------------------>>>', file)
console.log('singleUpload------------------------------------------------------------------------------>>> 0')
const { createReadStream, filename, mimetype, encoding } = await file;
console.log('singleUpload------------------------------------------------------------------------------>>> 1', filename)
const stream = createReadStream();
console.log('singleUpload------------------------------------------------------------------------------>>> 2')
const pathName = `${UPLOAD_DIR}${filename}`;
console.log('singleUpload------------------------------------------------------------------------------>>> 3')
await stream.pipe(fs.createWriteStream(pathName));
console.log('singleUpload------------------------------------------------------------------------------>>> 4')
return {
name: `http://localhost:4001/images/${filename}`,
size: 1,
};
},
My Client side
Version Info
"#apollo/client": "^3.2.7",
"#apollo/react-hoc": "^4.0.0",
"#apollo/react-hooks": "^4.0.0",
"#graphql-codegen/introspection": "^1.18.1",
"#graphql-codegen/schema-ast": "^1.18.1",
"#graphql-tools/load-files": "^6.2.5",
"#graphql-tools/merge": "^6.2.6",
"apollo-boost": "^0.4.9",
"apollo-link-ws": "^1.0.20",
"apollo-upload-client": "^16.0.0",
"graphql": "^14.7.0",
"graphql-scalars": "^1.7.0",
"react": "^16.14.0",
"react-apollo": "^3.1.5",
"react-app-rewire-define-plugin": "^1.0.0",
"react-app-rewired": "^2.1.8",
"react-dom": "^16.14.0",
"react-router-dom": "^5.2.0",
"react-scripts": "^3.4.1",
"subscriptions-transport-ws": "^0.9.18",
"typescript": "^3.7.3",
The Apollo Client
const uploadLink = createUploadLink({
uri: 'http://localhost:4001/graphql', // Apollo Server is served from port 4000
headers: {
"keep-alive": "true",
'content-type': 'application/json',
...((accessToken !== undefined && accessToken !== null) ? { Authorization: `Bearer ${accessToken}` } : {}),
...((accessToken !== undefined && accessToken !== null) ? { 'x-token': accessToken } : {}),
...((refreshToken !== undefined && refreshToken !== null) ? { 'x-refresh-token': refreshToken } : {}),
}
})
const clientUpload = new ApolloClient({
cache: cache,
link: uploadLink
})
The Uploader Component
const mutUploadFile = gql`
mutation singleUpload($file: Upload!) {
singleUpload(file: $file) {
name
#filename
#mimetype
#encoding
#url
}
}`
export function FileUploadSimpleA() {
const onChange = ((e: any) => {
console.log( 'onChange-------------------------')
const file = e.target.files[0]
console.log('file:', file)
if (file)
clientUpload.mutate({
mutation: mutUploadFile,
variables: {
file: file
}
})
.then(result => {
console.log( 'then-------------------------')
console.log(result)
clientUpload.resetStore();
})
.catch(error => {
console.log( 'catch-------------------------')
console.log(error)
}
);
});
return <input type="file" required onChange={onChange} />;
}
export default FileUploadSimpleA
Console of the browser
fileUploadSimple.tsx:50 onChange-------------------------
fileUploadSimple.tsx:52 file:: File {name:
"322abcbafe59a52481e6a0b6b84ffbc4.jpg", lastModified: 1614644398495, lastModifiedDate: Mon Mar 01 2021 18:19:58 GMT-0600 (Central Standard Time), webkitRelativePath: "", size: 68817, …}
fileUploadSimple.tsx:66 catch-------------------------
fileUploadSimple.tsx:67 Error: createReadStream is not a function

Unknown type "Upload" - Apollo Server Express with graphql-upload Node 14

I am working with GraphQL and is facing an issue with File Upload. My Node version is v14.16.0
I am getting error as below
Error: Unknown type "Upload". Did you mean "Float"?
Below are the package version installed
Package versions
"dependencies": {
"apollo-server-express": "^2.23.0",
"bcryptjs": "^2.4.3",
"compression": "^1.7.4",
"consola": "^2.15.3",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"graphql-upload": "^11.0.0",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.12.5",
"nodemon": "^2.0.7",
"yup": "^0.32.9"
}
Below is my server setup done with apollo-server-express and graphql-upload package
import express from "express";
import consola from "consola";
import { ApolloServer } from "apollo-server-express";
const { error, success } = consola;
import { PORT } from "./config/index.js";
import { typeDefs, resolvers } from "./graphql/index.js";
import * as AppModels from "./models/index.js";
import compression from "compression";
import { graphqlUploadExpress } from "graphql-upload";
//Initialize the app
const app = express();
app.use(compression());
app.use(
graphqlUploadExpress({
maxFileSize: 30000000,
maxFiles: 20,
})
);
const server = new ApolloServer({
typeDefs,
resolvers,
uploads: false,
context: {
...AppModels,
},
});
app.use(express.static("public"));
server.applyMiddleware({ app });
app.listen(PORT, () => {
success({
badge: true,
message: `Server started at ${PORT}`,
});
});
Here are my type definition for imageUpload Mutation
import { gql } from "apollo-server-express";
export default gql`
extend type Mutation {
imageUploader(file: Upload!): String!
}
`;
My resolver looks like this
import { createWriteStream } from "fs";
import { parse, join } from "path";
import { URL } from "../../config/index.js";
export default {
Mutation: {
imageUploader: async (_, { file }) => {
let { filename, createReadStream } = await file;
let stream = createReadStream();
let { name, ext } = parse(filename);
name = name.replace(/([^a-z0-9 ]+)/gi, "-").replace(" ", "_");
let serverFile = `D:/${name}${ext}`;
let writeStream = await createWriteStream(serverFile);
await stream.pipe(writeStream);
//serverFile = `${URL}/${serverFile.split("uploads")[1]}`;
return serverFile;
},
},
};
Well this is for anybody who faces the situation
As we are using the graphl-upload package so we need to define the custom scalar in typedef and assign the Upload type in resolver.
So now my typedef looks like this. Notice the code scalar Upload
import { gql } from "apollo-server-express";
export default gql`
scalar Upload
extend type Mutation {
imageUploader(file: Upload!): String!
}
`;
After typedef changes we need to define a resolver for that scalar. So now the resolver looks like this
import { createWriteStream } from "fs";
import { GraphQLUpload } from "graphql-upload";
import { parse, join } from "path";
import { URL } from "../../config/index.js";
export default {
Upload: GraphQLUpload,
Mutation: {
imageUploader: async (_, { file }) => {
let { filename, createReadStream } = await file;
let stream = createReadStream();
let { name, ext } = parse(filename);
name = name.replace(/([^a-z0-9 ]+)/gi, "-").replace(" ", "_");
let serverFile = `D:/${name}${ext}`;
let writeStream = await createWriteStream(serverFile);
await stream.pipe(writeStream);
//serverFile = `${URL}/${serverFile.split("uploads")[1]}`;
return serverFile;
},
},
};
Above code helped me in getting pass that issue.
I'm using NODE 14
import {ApolloServer} from "apollo-server-express";
...
// If you want to see uploaded images, then you need to add these commands and,
// create a folder to upload images name like 'uploads'
const app = express();
app.use(express.static(join(__dirname, './uploads')));
app.use(graphqlUploadExpress({ maxFileSize: 1000000000, maxFiles: 10 }));
const httpServer = http.createServer(app);
const server = new ApolloServer({
uploads: false, // --------- use this
typeDefs,
resolvers,
plugins: [IN_PROD ? ApolloServerPluginLandingPageGraphQLPlayground() :
ApolloServerPluginLandingPageDisabled(),
ApolloServerPluginDrainHttpServer({httpServer})],
context: {
...AppModels
}
});
after that, in typeDefs,
import { gql } from "apollo-server-express";
export default gql`
scalar Upload // ---- use this
extend type Mutation {
imageUploader(file: Upload!): String!
}
`;
after that, In resolvers
import {parse, join} from 'path';
import {createWriteStream} from 'fs';
import {URL} from "../../../config";
import {GraphQLUpload} from "graphql-upload";
export default {
Upload: GraphQLUpload, // ----- use this
Query: {
info: () => "Hello i am image resolver methods."
},
Mutation: {
imageUploader: async (_, {file}) => {
try {
let {
filename,
createReadStream
} = await file;
let stream = createReadStream();
let {
ext,
name
} = parse(filename);
name = name.replace(/([^a-z0-9 ]+)/gi, '-').replace(' ', '_');
let serverFile = join(__dirname,
`../../../uploads/${name}-${Date.now()}${ext}`);
let writeStream = await createWriteStream(serverFile);
await stream.pipe(writeStream);
let lastPath = serverFile.split('uploads')[1];
lastPath = lastPath.replace('\\', '/');
serverFile = `${URL}${lastPath}`;
return serverFile;
} catch (e) {
console.log("ERROR UPLOAD A IMAGE", e);
throw e;
}
}
}
}
Github link

File Upload React Native, Node JS, MongoDB, Multer, Grid FS

I am very new to React Native development. I am struggling from the past 2 days to crack the file/image upload with React Native to MongoDB(Grid FS). I literally read all the related forums but there is no luck. I read couple of forums and they gave a sample example but I wasn't succeeded. Here are the sample codes that I wrote.
Client JS (React Native):
import React, { Component } from "react";
import { View, Text, Image, Button, Platform } from "react-native";
import ImagePicker from "react-native-image-picker";
class ImagePickerComponent extends Component {
state = {
photo: null
};
handleChoosePhoto = () => {
const options = {
noData: true
};
ImagePicker.launchImageLibrary(options, response => {
if (response.uri) {
this.setState({ photo: response });
}
});
};
handleUploadPhoto = () => {
const { photo } = this.state;
const bodyJson = { userId: "123" };
console.log("PHOTO");
console.log(photo);
const data = new FormData();
data.append("name", "avatar");
data.append("file", {
uri: photo.uri,
type: photo.type,
name: photo.fileName
});
const config = {
method: "POST",
headers: {
Accept: "application/json"
// "Content-Type": "multipart/form-data"
},
body: data
};
fetch("http://localhost:3900/api/uploadFiles/upload", config)
.then(checkStatusAndGetJSONResponse => {
console.log("checkStatusAndGetJSONResponse");
console.log(checkStatusAndGetJSONResponse);
})
.catch(err => {
console.log(err);
});
};
createFormData = (photo, body) => {
console.log("PHOTO");
console.log(photo);
const data = new FormData();
data.append("photo", {
name: photo.fileName,
type: photo.type,
uri:
Platform.OS === "android" ? photo.uri : photo.uri.replace("file://", "")
});
Object.keys(body).forEach(key => {
data.append(key, body[key]);
});
return data;
};
render() {
const { photo } = this.state;
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
{photo && (
<React.Fragment>
<Image
source={{ uri: photo.uri }}
style={{ width: 300, height: 300 }}
/>
<Button title="Upload" onPress={this.handleUploadPhoto} />
</React.Fragment>
)}
<Button title="Choose Photo" onPress={this.handleChoosePhoto} />
</View>
);
}
}
export default ImagePickerComponent;
And below is the server JS file that handles to store the file in MongoDB with Multer.
const express = require("express");
const router = express();
const multer = require("multer");
const GridFsStorage = require("multer-gridfs-storage");
const path = require("path");
const crypto = require("crypto");
// Create storage engine
const storage = new GridFsStorage({
url: "mongodb://localhost/vidly",
file: (req, file) => {
console.log("In Storage: ");
console.log(file);
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString("hex") + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: "uploads"
};
console.log("fileInfo");
console.log(fileInfo);
resolve(fileInfo);
});
});
}
});
const upload = multer({ storage }).single("file");
// #route POST /upload
// #desc Uploads file to DB
//upload.single("file"),
// router.post("/upload", upload.single("file"), (req, res) => {
// console.log("In Upload Function");
// console.log(req);
// res.json({ file: req.file });
// // res.redirect("/");
// });
router.post("/upload", upload, (req, res) => {
console.log(req);
console.log("file", req.file);
console.log("body", req.body);
res.status(200).json({
message: "success!"
});
});
router.get("/me", (req, res) => {
res.json("Hello!");
});
module.exports = router;
Also, Here is the server package.json files that I am using.
"dependencies": {
"#hapi/joi": "^15.0.3",
"body-parser": "^1.19.0",
"config": "^3.1.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-async-errors": "^3.1.1",
"express-multipart-file-parser": "^0.1.2",
"gridfs-stream": "^1.1.1",
"mongoose": "^5.5.11",
"multer": "^1.4.1",
"multer-gridfs-storage": "^3.2.3",
"winston": "^3.2.1"
}
I am not getting any exception but the file is not storing into the mongoDB. Looks like Multer is not picking up the file from the request. My Server code is working when I test with POSTMAN but its not working with React Native.
I captured the Sample request & response from the react native debugger.
Also, Here are the logs from the server for failing request (From react Native).
route:
Route {
path: '/single',
stack:
[ Layer {
handle: [Function: multerMiddleware],
name: 'multerMiddleware',
params: undefined,
path: undefined,
keys: [],
regexp: /^\/?$/i,
method: 'post' },
Layer {
handle: [Function],
name: '<anonymous>',
params: undefined,
path: undefined,
keys: [],
regexp: /^\/?$/i,
method: 'post' } ],
methods: { post: true } },
**body:** [Object: null prototype] { photo: '[object Object]' },
__onFinished: null }
**undefined**
If we observe the request body we are getting an object.
Here is the server request that was captured through POSTMAN (Its a successful Request).
body: [Object: null prototype] {},
route:
Route {
path: '/upload',
stack:
[ Layer {
handle: [Function: multerMiddleware],
name: 'multerMiddleware',
params: undefined,
path: undefined,
keys: [],
regexp: { /^\/?$/i fast_star: false, fast_slash: false },
method: 'post' },
Layer {
handle: [Function],
name: '<anonymous>',
params: undefined,
path: undefined,
keys: [],
regexp: { /^\/?$/i fast_star: false, fast_slash: false },
method: 'post' } ],
methods: { post: true } },
file:
{ fieldname: 'file',
originalname: 'testAlert.html',
encoding: '7bit',
mimetype: 'text/html',
id: 5d1e3084e3aa4de0b8320773,
filename: 'e7d2080ddbe2cbf2ac7167d79b8ff0f2.html',
metadata: null,
bucketName: 'uploads',
chunkSize: 261120,
size: 148961,
md5: '4e68af2f75a34d2d7371f21544fe9b58',
uploadDate: 2019-07-04T16:59:48.602Z,
contentType: 'text/html' },
__onFinished: null }
If we observe both the requests file object is coming as a separate section through POSTMAN but not the case with react native. Can anyone please help me on this.? Why its not working with React-Native.? I stuck over here. Please help me on this.?
Thanks & Regards,
Amar.T

server.register() function throwing "register is missing", even though i have properly registered the plugins for graphql

I have created a node js project with graph ql (with a very basic schema) but when i am trying to start the server after registering the plugins for graphql and graphiql, i am getting the register is missing error. Below is my code
const hapi=require('hapi');
const { graphqlHapi, graphiqlHapi } = require('apollo-server-hapi');
const { makeExecutableSchema } = require('graphql-tools');
const graphqlSchema = require('./graphql/schema');
const createResolvers = require('./graphql/resolvers');
const executableSchema = makeExecutableSchema({
typeDefs: [graphqlSchema],
resolvers: createResolvers(),
});
const server=hapi.server({
port: 4000,
host:'localhost'
});
server.register({
plugin: graphqlHapi,
options: {
path: '/graphql',
graphqlOptions: () => ({
pretty: true,
schema: executableSchema,
}),
},
});
server.register({
plugin: graphiqlHapi,
options: {
path: '/graphiql',
graphiqlOptions: {
endpointURL: '/graphql',
},
},
});
const init= async()=>{
routes(server);
await server.start();
console.log(`Server is running at: ${server.info.uri}`);
}
init();
I had initially given the key name as register instead of plugin in the server.register() functions. In either case, i am getting the below error
(node:19104) DeprecationWarning: current URL string parser is
deprecated, and will be removed in a future version. To use the new
parser, pass option { useNewUrlParser: true } to MongoClient.connect.
(node:19104) UnhandledPromiseRejectionWarning: AssertionError
[ERR_ASSERTION]: I nvalid plugin options {
"plugin": {
"options": {
"path": "/graphql",
"graphqlOptions": () => ({\r\n pretty: true,\r\n schema: exe cutableSchema,\r\n })
},
"register" [1]: -- missing -- } }
Please help me out in understanding whenter code herey this happening and how it can be rectified.
Below is the dependencies in my project
apollo-server-hapi": "^2.3.1", "graphql": "^14.0.2", "graphql-tools":
"^4.0.3", "hapi": "^17.8.1",
EDIT
Code after making the suggested changes
const hapi=require('hapi');
const { graphqlHapi, graphiqlHapi } = require('apollo-server-hapi');
const { makeExecutableSchema } = require('graphql-tools');
const graphqlSchema = require('./graphql/schema');
const createResolvers = require('./graphql/resolvers');
const executableSchema = makeExecutableSchema({
typeDefs: [graphqlSchema],
resolvers: createResolvers(),
});
async function start_server() {
const server=hapi.server({
port: 4000,
host:'localhost'
});
await server.register({
plugin: graphqlHapi,
options: {
path: '/graphql',
graphqlOptions: () => ({
pretty: true,
schema: executableSchema,
}),
route: {
cors: true,
},
},
});
await server.register({
plugin: graphiqlHapi,
options: {
path: '/graphiql',
graphiqlOptions: {
endpointURL: '/graphql',
},
route: {
cors: true,
},
},
});
try {
await server.start();
console.log(`Server is running at: ${server.info.uri}`);
} catch (err) {
console.log(`Error while starting server: ${err.message}`)
}
}
start_server();
There is no need to register the plugins in the latest release of apollo-server-hapi. It contains GraphQL playground instead of graphiql.
The below changes need to be done instead of registering.
const {ApolloServer} = require('apollo-server-hapi');
const executableSchema = makeExecutableSchema({
typeDefs: [graphqlSchema],
resolvers: createResolvers(),
});
const server = new ApolloServer({
schema:executableSchema
});
async function start_server() {
const app=hapi.server({
port: 4000,
host:'localhost'
});
await server.applyMiddleware({ app });
try {
await app.start();
console.log(`Server is running at: ${app.info.uri}`);
} catch (err) {
console.log(`Error while starting server: ${err.message}`)
}
}
start_server();

Resources