import { ApolloError, ApolloServer } from 'apollo-server-express'; import { QueryFailedError } from 'typeorm'; import { TypeormDataLoader } from '../entities/utils'; import logger from '../logger'; import { ContextType } from '../types'; import { extractAuthDataFromRequest } from './auth'; import { buildSchema, dataSources } from './'; let apollo: ApolloServer; export const setupApolloServer = async (): Promise => { if (apollo) { return apollo; } else { const schema = await buildSchema(); apollo = new ApolloServer({ playground: process.env.NODE_ENV !== 'production' ? { settings: { ['request.credentials']: 'include', }, } : undefined, schema, dataSources, async context({ req, res }): Promise> { const authData = await extractAuthDataFromRequest(req, res); return { ...authData, req, res, dbDataLoader: new TypeormDataLoader(), }; }, debug: ['development', 'test'].includes(process.env.NODE_ENV!), plugins: [ { requestDidStart(requestCtx) { if (requestCtx.request.query) { logger.info( requestCtx.request.query .replace(/(\r\n|\n|\r)/gm, ' ') .replace(/( )+/gm, ' ') ); } }, }, ], formatError: (error) => { if (process.env.NODE_ENV !== 'test') { logger.error(error); } // Do not expose typeorm errors to the client if not in development if ( process.env.NODE_ENV !== 'development' && (error instanceof QueryFailedError || error.originalError instanceof QueryFailedError) ) { return new ApolloError('Something went wrong'); } return error; }, uploads: false, // use graphqlUploadExpress instead }); } return apollo; };