Make GraphQL polymorphic relationships working with Bookshelf

This commit is contained in:
Aurelsicoko 2018-04-11 12:53:07 +02:00
parent c59ad9d958
commit 17c46b331d
4 changed files with 83 additions and 30 deletions

View File

@ -176,6 +176,7 @@ module.exports = function(strapi) {
attrs[association.alias] = attrs[association.alias].related;
break;
case 'manyMorphToOne':
case 'manyMorphToMany':
attrs[association.alias] = attrs[association.alias].map(obj => obj.related);
break;
default:
@ -226,7 +227,6 @@ module.exports = function(strapi) {
const association = definition.associations
.filter(association => association.nature.toLowerCase().indexOf('morph') !== -1)
.filter(association => association.alias === path || association.via === path)[0];
if (association) {
// Override on polymorphic path only.
if (_.isString(path) && path === association.via) {

View File

@ -29,16 +29,37 @@ module.exports = {
.count();
},
findOne: async function (params) {
findOne: async function (params, populate, raw = true) {
const record = await this
.forge({
[this.primaryKey]: params[this.primaryKey]
})
.fetch({
withRelated: this.associations.map(x => x.alias)
withRelated: populate || this.associations.map(x => x.alias)
});
return record ? record.toJSON() : record;
const data = record ? record.toJSON() : record;
// Retrieve data manually.
if (_.isEmpty(populate)) {
const arrayOfPromises = this.associations
.filter(association => ['manyMorphToOne', 'manyMorphToMany'].includes(association.nature))
.map(association => {
return this.morph.forge()
.where({
[`${this.collectionName}_id`]: params[this.primaryKey]
})
.fetchAll()
});
const related = await Promise.all(arrayOfPromises);
related.forEach((value, index) => {
data[this.associations[index].alias] = value ? value.toJSON() : value;
});
}
return data;
},
create: async function (params) {

View File

@ -475,7 +475,9 @@ module.exports = {
acc.resolver[globalId] = {};
}
if (association.nature === 'manyMorphToMany') {
switch (association.nature) {
case 'manyMorphToOne':
case 'manyMorphToMany':
return _.merge(acc.resolver[globalId], {
[association.alias]: async (obj, options, context) => {
const [ withRelated, withoutRelated ] = await Promise.all([
@ -492,7 +494,10 @@ module.exports = {
const entry = withRelated.toJSON ? withRelated.toJSON() : withRelated;
entry[association.alias].map((entry, index) => {
entry._type = withoutRelated[association.alias][index].kind;
const type = withoutRelated[association.alias][index].kind ||
_.upperFirst(_.camelCase(withoutRelated[association.alias][index][`${association.alias}_type`]));
entry._type = type;
return entry;
});
@ -500,6 +505,8 @@ module.exports = {
return entry[association.alias];
}
});
break;
default:
}
// TODO:
@ -520,13 +527,13 @@ module.exports = {
} else {
// Get attribute.
const attr = association.plugin ?
strapi.plugins[association.plugin].models[association.collection].attributes[association.via]:
strapi.models[association.collection].attributes[association.via];
strapi.plugins[association.plugin].models[params.model].attributes[association.via]:
strapi.models[params.model].attributes[association.via];
// Get refering model.
const ref = attr.plugin ?
strapi.plugins[attr.plugin].models[attr.model || attr.collection]:
strapi.models[attr.model || attr.collection];
strapi.plugins[attr.plugin].models[params.model]:
strapi.models[params.model];
// Apply optional arguments to make more precise nested request.
const convertedParams = strapi.utils.models.convertParams(name, this.convertToParams(options));

View File

@ -0,0 +1,25 @@
module.exports = {
type: {
UsersPermissionsPermission: false // Make this type NOT queriable.
},
resolver: {
Query: {
role: {
resolverOf: 'UsersPermissions.getRole',
resolver: async (obj, options, ctx) => {
await strapi.plugins['users-permissions'].controllers.userspermissions.getRole(ctx);
return ctx.body.role;
}
},
roles: {
resolverOf: 'UsersPermissions.getRoles', // Apply the `getRoles` permissions on the resolver.
resolver: async (obj, options, ctx) => {
await strapi.plugins['users-permissions'].controllers.userspermissions.getRoles(ctx);
return ctx.body.roles;
}
}
}
}
};