2021-08-24 12:10:47 +02:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const { omit } = require('lodash/fp');
|
|
|
|
|
2021-08-24 17:56:44 +02:00
|
|
|
module.exports = ({ strapi }) => {
|
|
|
|
const { isMorphRelation, isMedia } = strapi.plugin('graphql').service('utils').attributes;
|
|
|
|
const { transformArgs } = strapi.plugin('graphql').service('builders').utils;
|
2021-08-24 12:10:47 +02:00
|
|
|
|
2021-08-24 17:56:44 +02:00
|
|
|
return {
|
|
|
|
buildAssociationResolver: ({ contentTypeUID, attributeName }) => {
|
|
|
|
const { entityManager } = strapi.db;
|
2021-08-24 12:10:47 +02:00
|
|
|
|
2021-08-24 17:56:44 +02:00
|
|
|
const contentType = strapi.getModel(contentTypeUID);
|
|
|
|
const attribute = contentType.attributes[attributeName];
|
2021-08-24 12:10:47 +02:00
|
|
|
|
2021-08-24 17:56:44 +02:00
|
|
|
if (!attribute) {
|
|
|
|
throw new Error(
|
|
|
|
`Failed to build an association resolver for ${contentTypeUID}::${attributeName}`
|
|
|
|
);
|
|
|
|
}
|
2021-08-24 12:10:47 +02:00
|
|
|
|
2021-08-24 17:56:44 +02:00
|
|
|
const isMediaAttribute = isMedia(attribute);
|
|
|
|
const isMorphAttribute = isMorphRelation(attribute);
|
2021-08-24 12:10:47 +02:00
|
|
|
|
2021-08-24 17:56:44 +02:00
|
|
|
const targetUID = isMediaAttribute ? 'plugins::upload.file' : attribute.target;
|
|
|
|
const isToMany = isMediaAttribute ? attribute.multiple : attribute.relation.endsWith('Many');
|
2021-08-24 12:10:47 +02:00
|
|
|
|
2021-08-24 17:56:44 +02:00
|
|
|
const targetContentType = strapi.getModel(targetUID);
|
2021-08-24 12:10:47 +02:00
|
|
|
|
2021-09-01 12:06:51 +02:00
|
|
|
return async (parent, args = {}) => {
|
2021-08-24 17:56:44 +02:00
|
|
|
const transformedArgs = transformArgs(args, {
|
|
|
|
contentType: targetContentType,
|
|
|
|
usePagination: true,
|
|
|
|
});
|
2021-08-24 12:10:47 +02:00
|
|
|
|
2021-08-24 17:56:44 +02:00
|
|
|
// 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,
|
|
|
|
};
|
2021-08-24 12:10:47 +02:00
|
|
|
|
2021-08-24 17:56:44 +02:00
|
|
|
// todo[v4]: should we move the .load to the entity service so we can use the same args everywhere?
|
|
|
|
const data = await entityManager.load(
|
|
|
|
contentTypeUID,
|
2021-09-01 12:06:51 +02:00
|
|
|
parent,
|
2021-08-24 17:56:44 +02:00
|
|
|
attributeName,
|
|
|
|
entityManagerArgs
|
|
|
|
);
|
2021-08-24 12:10:47 +02:00
|
|
|
|
2021-08-24 17:56:44 +02:00
|
|
|
// If this a polymorphic association, it returns the raw data
|
|
|
|
if (isMorphAttribute) {
|
|
|
|
return data;
|
|
|
|
}
|
2021-08-24 12:10:47 +02:00
|
|
|
|
2021-08-24 17:56:44 +02:00
|
|
|
// 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 } };
|
|
|
|
}
|
2021-08-24 12:10:47 +02:00
|
|
|
|
2021-08-24 17:56:44 +02:00
|
|
|
// Else, it returns an object that matches
|
|
|
|
// what the entity-response's resolvers expect
|
|
|
|
return { value: data };
|
|
|
|
};
|
|
|
|
},
|
|
|
|
};
|
|
|
|
};
|