149 lines
3.6 KiB
JavaScript
Raw Normal View History

'use strict';
const { isEmpty, mergeWith, isArray } = require('lodash/fp');
2021-09-29 13:10:33 +02:00
const { execute, subscribe } = require('graphql');
const { SubscriptionServer } = require('subscriptions-transport-ws');
const { ApolloServer } = require('apollo-server-koa');
2021-08-10 17:28:53 +02:00
const {
ApolloServerPluginLandingPageDisabled,
ApolloServerPluginLandingPageGraphQLPlayground,
2021-08-10 17:28:53 +02:00
} = require('apollo-server-core');
const depthLimit = require('graphql-depth-limit');
const { graphqlUploadKoa } = require('graphql-upload');
2021-10-27 18:54:58 +02:00
const formatGraphqlError = require('./format-graphql-error');
const merge = mergeWith((a, b) => {
if (isArray(a) && isArray(b)) {
return a.concat(b);
}
});
module.exports = async ({ strapi }) => {
2021-08-10 17:28:53 +02:00
// Generate the GraphQL schema for the content API
const schema = strapi
.plugin('graphql')
.service('content-api')
.buildSchema();
2021-08-10 17:28:53 +02:00
if (isEmpty(schema)) {
strapi.log.warn('The GraphQL schema has not been generated because it is empty');
return;
}
const { config } = strapi.plugin('graphql');
2021-09-29 13:10:33 +02:00
const path = config('endpoint', '/graphql');
const defaultServerConfig = {
2021-08-10 17:28:53 +02:00
// Schema
schema,
2021-08-10 17:28:53 +02:00
// Initialize loaders for this request.
context: ({ ctx }) => ({
state: ctx.state,
koaContext: ctx,
}),
2021-08-10 17:28:53 +02:00
// Validation
validationRules: [depthLimit(config('depthLimit'))],
2021-08-10 17:28:53 +02:00
2021-10-27 18:54:58 +02:00
// Errors
formatError: formatGraphqlError,
2021-08-10 17:28:53 +02:00
// Misc
cors: false,
2021-08-10 17:28:53 +02:00
uploads: false,
bodyParserConfig: true,
2021-08-10 17:28:53 +02:00
plugins: [
process.env.NODE_ENV === 'production'
? ApolloServerPluginLandingPageDisabled()
: ApolloServerPluginLandingPageGraphQLPlayground(),
2021-08-10 17:28:53 +02:00
],
};
const serverConfig = merge(defaultServerConfig, config('apolloServer', {}));
2021-09-29 13:10:33 +02:00
// Handle subscriptions
if (config('subscriptions', true)) {
const subscriptionServer = SubscriptionServer.create(
{ schema, execute, subscribe },
{ server: strapi.server.httpServer, path }
);
serverConfig.plugins.push({
async serverWillStart() {
return {
async drainServer() {
subscriptionServer.close();
},
};
},
});
}
2021-08-10 17:28:53 +02:00
// Create a new Apollo server
const server = new ApolloServer(serverConfig);
2021-08-10 17:28:53 +02:00
// Register the upload middleware
2021-09-28 11:11:03 +02:00
useUploadMiddleware(strapi, path);
2021-08-10 17:28:53 +02:00
try {
// Since Apollo-Server v3, server.start() must be called before using server.applyMiddleware()
await server.start();
} catch (e) {
strapi.log.error('Failed to start the Apollo server', e.message);
}
2021-09-29 13:10:33 +02:00
// Link the Apollo server & the Strapi app
strapi.server.routes([
{
method: 'ALL',
2021-09-21 19:38:15 +02:00
path,
handler: [
(ctx, next) => {
ctx.state.route = {
info: {
// Indicate it's a content API route
type: 'content-api',
},
};
return strapi.auth.authenticate(ctx, next);
},
// Apollo Server
2021-09-21 19:38:15 +02:00
server.getMiddleware({ path }),
],
config: {
auth: false,
},
},
]);
2021-08-10 17:28:53 +02:00
// Register destroy behavior
// We're doing it here instead of exposing a destroy method to the strapi-server.js
// file since we need to have access to the ApolloServer instance
strapi.plugin('graphql').destroy = async () => {
2021-08-10 17:28:53 +02:00
await server.stop();
};
};
2021-08-10 17:28:53 +02:00
/**
* Register the upload middleware powered by graphql-upload in Strapi
* @param {object} strapi
2021-09-28 11:11:03 +02:00
* @param {string} path
2021-08-10 17:28:53 +02:00
*/
2021-09-28 11:11:03 +02:00
const useUploadMiddleware = (strapi, path) => {
const uploadMiddleware = graphqlUploadKoa();
2021-08-10 17:28:53 +02:00
strapi.server.app.use((ctx, next) => {
2021-09-28 11:11:03 +02:00
if (ctx.path === path) {
return uploadMiddleware(ctx, next);
}
return next();
});
};