From 0eeaa91c7afc8a0d372768a00e67140ecc5d754f Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 18 Aug 2021 16:09:27 +0200 Subject: [PATCH] Handle polymorphic relations in assocs resolvers --- .../graphql/services/schema/builders/type.js | 2 ++ .../services/schema/resolvers/association.js | 24 +++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/plugins/graphql/services/schema/builders/type.js b/packages/plugins/graphql/services/schema/builders/type.js index 53c15ff970..31de174b6a 100644 --- a/packages/plugins/graphql/services/schema/builders/type.js +++ b/packages/plugins/graphql/services/schema/builders/type.js @@ -246,6 +246,8 @@ const addPolymorphicRelationalAttribute = options => { if (isToManyRelation) { builder = builder.list; } + // todo[v4]: How to handle polymorphic relation w/ entity response collection types? + // -> Currently return raw polymorphic entities const resolve = buildAssociationResolver({ contentTypeUID: contentType.uid, diff --git a/packages/plugins/graphql/services/schema/resolvers/association.js b/packages/plugins/graphql/services/schema/resolvers/association.js index 8fdb9bc9af..787386dc21 100644 --- a/packages/plugins/graphql/services/schema/resolvers/association.js +++ b/packages/plugins/graphql/services/schema/resolvers/association.js @@ -17,8 +17,12 @@ const buildAssociationResolver = ({ contentTypeUID, attributeName, strapi }) => ); } - // todo[v4]: make sure polymorphic relations aren't breaking here - const targetUID = utils.isMedia(attribute) ? 'plugins::upload.file' : attribute.target; + const isMedia = utils.isMedia(attribute); + const isMorph = utils.isMorphRelation(attribute); + + const targetUID = isMedia ? 'plugins::upload.file' : attribute.target; + const isToMany = isMedia ? attribute.multiple : attribute.relation.endsWith('Many'); + const targetContentType = strapi.getModel(targetUID); return async (parent, args = {}) => { @@ -27,20 +31,30 @@ const buildAssociationResolver = ({ contentTypeUID, attributeName, strapi }) => usePagination: true, }); - // todo[v4]: move the .load to the entity service? + // Since we're using the entity-manager & not the entity-service to load the + // association, we need to apply some transformation to the transformed args object const entityManagerArgs = { ...omit(['start', 'filters'], transformedArgs), where: transformedArgs.filters, offset: transformedArgs.start, }; + // todo[v4]: move the .load to the entity service so we can use the same args everywhere? const data = await entityManager.load(contentTypeUID, parent, attributeName, entityManagerArgs); - // todo[v4]: Replace with a check on the attribute (handle case where data is null but for an array - if (Array.isArray(data)) { + // If this a polymorphic association, it returns the raw data + if (isMorph) { + return data; + } + + // If this is a to-many relation, it returns an object that + // matches what the entity-response-collection's resolvers expect + else if (isToMany) { return { nodes: data, info: { args: transformedArgs, resourceUID: targetUID } }; } + // Else, it returns an object that matches + // what the entity-response's resolvers expect return { value: data }; }; };