Fix component assoc resolvers in graphql (#9660)

This commit is contained in:
Alexandre BODIN 2021-03-10 10:46:46 +01:00 committed by GitHub
parent 9e22c280de
commit b3635962a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 32 deletions

View File

@ -189,6 +189,22 @@ module.exports = async ({ models, target }, ctx) => {
}; };
}; };
const parseComponentRef = el => {
if (el.ref instanceof mongoose.Types.ObjectId) {
return el.ref.toString();
} else {
return el.ref;
}
};
const parseDynamicZoneRef = el => {
if (el.ref instanceof mongoose.Types.ObjectId) {
return { id: el.ref.toString() };
} else {
return el.ref;
}
};
schema.options.toObject = schema.options.toJSON = { schema.options.toObject = schema.options.toJSON = {
virtuals: true, virtuals: true,
transform: function(doc, returned) { transform: function(doc, returned) {
@ -232,7 +248,7 @@ module.exports = async ({ models, target }, ctx) => {
if (type === 'component') { if (type === 'component') {
if (Array.isArray(returned[name])) { if (Array.isArray(returned[name])) {
const components = returned[name].map(el => el.ref); const components = returned[name].map(parseComponentRef);
// Reformat data by bypassing the many-to-many relationship. // Reformat data by bypassing the many-to-many relationship.
returned[name] = returned[name] =
attribute.repeatable === true ? components : _.first(components) || null; attribute.repeatable === true ? components : _.first(components) || null;
@ -246,7 +262,7 @@ module.exports = async ({ models, target }, ctx) => {
.map(el => { .map(el => {
return { return {
__component: findComponentByGlobalId(el.kind).uid, __component: findComponentByGlobalId(el.kind).uid,
...el.ref, ...parseDynamicZoneRef(el),
}; };
}); });
} }

View File

@ -120,9 +120,7 @@ const generateDynamicZoneDefinitions = (attributes, globalId, schema) => {
if (components.length === 0) { if (components.length === 0) {
// Create dummy type because graphql doesn't support empty ones // Create dummy type because graphql doesn't support empty ones
schema.definition += `type ${typeName} { _:Boolean}`; schema.definition += `type ${typeName} { _:Boolean}`;
schema.definition += `\nscalar EmptyQuery\n`;
} else { } else {
const componentsTypeNames = components.map(componentUID => { const componentsTypeNames = components.map(componentUID => {
const compo = strapi.components[componentUID]; const compo = strapi.components[componentUID];
@ -202,6 +200,11 @@ const buildAssocResolvers = model => {
} }
default: { default: {
resolver[alias] = async (obj, options) => { resolver[alias] = async (obj, options) => {
// force component relations to be refetched
if (model.modelType === 'component') {
obj[alias] = _.get(obj[alias], targetModel.primaryKey, obj[alias]);
}
const loader = strapi.plugins.graphql.services['data-loaders'].loaders[targetModel.uid]; const loader = strapi.plugins.graphql.services['data-loaders'].loaders[targetModel.uid];
const localId = obj[model.primaryKey]; const localId = obj[model.primaryKey];
@ -311,6 +314,8 @@ const buildModels = models => {
const buildModelDefinition = (model, globalType = {}) => { const buildModelDefinition = (model, globalType = {}) => {
const { globalId, primaryKey } = model; const { globalId, primaryKey } = model;
const typeDefObj = buildTypeDefObj(model);
const schema = { const schema = {
definition: '', definition: '',
query: {}, query: {},
@ -323,10 +328,9 @@ const buildModelDefinition = (model, globalType = {}) => {
...buildAssocResolvers(model), ...buildAssocResolvers(model),
}, },
}, },
typeDefObj,
}; };
const typeDefObj = buildTypeDefObj(model);
schema.definition += generateEnumDefinitions(model.attributes, globalId); schema.definition += generateEnumDefinitions(model.attributes, globalId);
generateDynamicZoneDefinitions(model.attributes, globalId, schema); generateDynamicZoneDefinitions(model.attributes, globalId, schema);
@ -397,7 +401,7 @@ const buildSingleType = model => {
}; };
const buildCollectionType = model => { const buildCollectionType = model => {
const { globalId, plugin, modelName, uid } = model; const { plugin, modelName, uid } = model;
const singularName = toSingular(modelName); const singularName = toSingular(modelName);
const pluralName = toPlural(modelName); const pluralName = toPlural(modelName);
@ -406,31 +410,8 @@ const buildCollectionType = model => {
const globalType = _.get(_schema, `type.${model.globalId}`, {}); const globalType = _.get(_schema, `type.${model.globalId}`, {});
const localSchema = { const localSchema = buildModelDefinition(model, globalType);
definition: '', const { typeDefObj } = localSchema;
query: {},
mutation: {},
resolvers: {
Query: {},
Mutation: {},
// define default resolver for this model
[globalId]: {
id: parent => parent[model.primaryKey] || parent.id,
...buildAssocResolvers(model),
},
},
};
const typeDefObj = buildTypeDefObj(model);
localSchema.definition += generateEnumDefinitions(model.attributes, globalId);
generateDynamicZoneDefinitions(model.attributes, globalId, localSchema);
const description = getTypeDescription(globalType, model);
const fields = toSDL(typeDefObj, globalType, model);
const typeDef = `${description}type ${globalId} {${fields}}\n`;
localSchema.definition += typeDef;
// Add definition to the schema but this type won't be "queriable" or "mutable". // Add definition to the schema but this type won't be "queriable" or "mutable".
if (globalType === false) { if (globalType === false) {