162 lines
4.9 KiB
JavaScript
Raw Normal View History

'use strict';
/**
* Module dependencies
*/
// Public node modules.
const _ = require('lodash');
const { ApolloServer } = require('apollo-server-koa');
const { buildFederatedSchema } = require('@apollo/federation');
const depthLimit = require('graphql-depth-limit');
2019-04-09 21:51:28 +02:00
const loadConfigs = require('./load-config');
const attachMetadataToResolvers = (schema, { api, plugin }) => {
const { resolver = {} } = schema;
if (_.isEmpty(resolver)) return schema;
Object.keys(resolver).forEach(type => {
if (!_.isPlainObject(resolver[type])) return;
Object.keys(resolver[type]).forEach(resolverName => {
if (!_.isPlainObject(resolver[type][resolverName])) return;
resolver[type][resolverName]['_metadatas'] = {
api,
plugin,
};
});
});
return schema;
};
module.exports = strapi => {
2019-04-09 21:51:28 +02:00
const { appPath, installedPlugins } = strapi.config;
return {
async beforeInitialize() {
2018-03-28 20:13:09 +02:00
// Try to inject this hook just after the others hooks to skip the router processing.
if (!strapi.config.get('hook.load.after')) {
_.set(strapi.config.hook.load, 'after', []);
}
strapi.config.hook.load.after.push('graphql');
// Load core utils.
2019-04-09 21:51:28 +02:00
2019-06-10 20:37:13 +02:00
const { api, plugins, extensions } = await loadConfigs({
appPath,
installedPlugins,
});
_.merge(strapi, { api, plugins });
2018-03-31 18:55:08 +02:00
/*
* Create a merge of all the GraphQL configuration.
*/
const apisSchemas = Object.keys(strapi.api || {}).map(key => {
const schema = _.get(strapi.api[key], 'config.schema.graphql', {});
return attachMetadataToResolvers(schema, { api: key });
});
2019-04-09 21:51:28 +02:00
const pluginsSchemas = Object.keys(strapi.plugins || {}).map(key => {
const schema = _.get(strapi.plugins[key], 'config.schema.graphql', {});
return attachMetadataToResolvers(schema, { plugin: key });
});
2019-04-09 21:51:28 +02:00
const extensionsSchemas = Object.keys(extensions || {}).map(key => {
const schema = _.get(extensions[key], 'config.schema.graphql', {});
return attachMetadataToResolvers(schema, { plugin: key });
});
2019-04-09 21:51:28 +02:00
const baseSchema = mergeSchemas([...apisSchemas, ...pluginsSchemas, ...extensionsSchemas]);
2019-06-10 20:37:13 +02:00
2019-04-09 21:51:28 +02:00
// save the final schema in the plugin's config
_.set(strapi, ['plugins', 'graphql', 'config', '_schema', 'graphql'], baseSchema);
},
initialize() {
const { typeDefs, resolvers } = strapi.plugins.graphql.services[
'schema-generator'
].generateSchema();
if (_.isEmpty(typeDefs)) {
strapi.log.warn('The GraphQL schema has not been generated because it is empty');
2019-08-14 14:15:45 +02:00
return;
}
// Get federation config
const isFederated = _.get(strapi.plugins.graphql, 'config.federation', false);
const schemaDef = {};
if (isFederated) {
schemaDef.schema = buildFederatedSchema([{ typeDefs, resolvers }]);
} else {
schemaDef.typeDefs = typeDefs;
schemaDef.resolvers = resolvers;
}
const serverParams = {
...schemaDef,
context: ({ ctx }) => {
// Initiliase loaders for this request.
2019-04-09 21:51:28 +02:00
// TODO: set loaders in the context not globally
strapi.plugins.graphql.services['data-loaders'].initializeLoader();
return {
context: ctx,
};
},
formatError: err => {
const formatError = _.get(strapi.plugins.graphql, 'config.formatError', null);
return typeof formatError === 'function' ? formatError(err) : err;
},
validationRules: [depthLimit(strapi.plugins.graphql.config.depthLimit)],
tracing: _.get(strapi.plugins.graphql, 'config.tracing', false),
playground: false,
2019-08-21 11:05:33 +02:00
cors: false,
bodyParserConfig: true,
introspection: _.get(strapi.plugins.graphql, 'config.introspection', true),
engine: _.get(strapi.plugins.graphql, 'config.engine', false),
};
// Disable GraphQL Playground in production environment.
if (
strapi.config.environment !== 'production' ||
strapi.plugins.graphql.config.playgroundAlways
) {
serverParams.playground = {
endpoint: `${strapi.config.server.url}${strapi.plugins.graphql.config.endpoint}`,
shareEnabled: strapi.plugins.graphql.config.shareEnabled,
};
}
const server = new ApolloServer(serverParams);
server.applyMiddleware({
app: strapi.app,
path: strapi.plugins.graphql.config.endpoint,
});
},
};
};
2019-04-09 21:51:28 +02:00
/**
* Merges a list of schemas
* @param {Array<Object>} schemas - The list of schemas to merge
*/
const mergeSchemas = schemas => {
return schemas.reduce((acc, el) => {
const { definition, query, mutation, type, resolver } = el;
return _.merge(acc, {
definition: `${acc.definition || ''} ${definition || ''}`,
query: `${acc.query || ''} ${query || ''}`,
mutation: `${acc.mutation || ''} ${mutation || ''}`,
type,
resolver,
});
}, {});
};