Jean-Sébastien Herbaux 357fd163b0
V4/graphql customization (#10850)
* Add basic implementation for the graphql extension service

* Add createPolicyContext in @strapi/utils

* policiesMiddleware implementation for graphql

* wrapResolvers first implementation (authentication, middlewares, policies)

* move the content API schema build from /generators to /content-api. Extract types' register functions into a dedicated folder

* fix schema generation on bootstrap

* update the graphql service file to match new services arch

* fix single type queries

* simplify entity's resolver

* use apollo graphql conventions for resolver's args naming

* use the graphql extension system in i18n to add a locale arg to localized queries & mutations
2021-09-01 12:06:51 +02:00

92 lines
2.6 KiB
JavaScript

'use strict';
const nexus = require('nexus');
const { merge } = require('lodash/fp');
/**
* @typedef StrapiGraphQLExtensionConfiguration
* @property {NexusGen[]} types - A collection of Nexus types
* @property {string} typeDefs - Type definitions (SDL format)
* @property {object} resolvers - A resolver map
* @property {object} resolversConfig - An object that bind a configuration to a resolver based on an absolute path (the key)
* @property {NexusPlugin[]} plugins - A collection of Nexus plugins
*/
/**
* @typedef {function({ strapi: object, nexus: object, typeRegistry: object }): StrapiGraphQLExtensionConfiguration} StrapiGraphQLExtensionConfigurationFactory
*/
const defaultState = {
types: [],
typeDefs: [],
resolvers: {},
resolversConfig: {},
plugins: [],
};
const createExtension = ({ strapi } = {}) => {
const configs = [];
return {
/**
* Register a new extension configuration
* @param {StrapiGraphQLExtensionConfiguration | StrapiGraphQLExtensionConfigurationFactory} configuration
* @return {this}
*/
use(configuration) {
configs.push(configuration);
return this;
},
/**
* Convert the registered configuration into a single extension object & return it
* @param {object} options
* @param {object} options.typeRegistry
* @return {object}
*/
generate({ typeRegistry }) {
const resolveConfig = config => {
return typeof config === 'function' ? config({ strapi, nexus, typeRegistry }) : config;
};
// Evaluate & merge every registered configuration object, then return the result
return configs.reduce((acc, configuration) => {
const { types, typeDefs, resolvers, resolversConfig, plugins } = resolveConfig(
configuration
);
// Register type definitions
if (typeof typeDefs === 'string') {
acc.typeDefs.push(typeDefs);
}
// Register nexus types
if (Array.isArray(types)) {
acc.types.push(...types);
}
// Register nexus plugins
if (Array.isArray(plugins)) {
acc.plugins.push(...plugins);
}
// Register resolvers
if (typeof resolvers === 'object') {
acc.resolvers = merge(acc.resolvers, resolvers);
}
// Register resolvers configuration
if (typeof resolversConfig === 'object') {
// TODO: smarter merge for auth, middlewares & policies
acc.resolversConfig = merge(acc.resolversConfig, resolversConfig);
}
return acc;
}, defaultState);
},
};
};
module.exports = createExtension;