mirror of
https://github.com/strapi/strapi.git
synced 2025-12-28 23:57:32 +00:00
Merge pull request #316 from strapi/fix/api-relations-mongoose
Fix api relations
This commit is contained in:
commit
bf50390bb6
@ -30,8 +30,8 @@
|
||||
"strapi-utils": "3.0.0-alpha.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^5.1.0",
|
||||
"eslint": "^4.9.0",
|
||||
"cross-env": "^5.1.1",
|
||||
"eslint": "^4.10.0",
|
||||
"eslint-config-airbnb": "^15.1.0",
|
||||
"eslint-config-airbnb-base": "^11.3.2",
|
||||
"eslint-config-prettier": "^2.6.0",
|
||||
|
||||
@ -482,6 +482,199 @@ module.exports = function(strapi) {
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
manageRelations: async function (model, params) {
|
||||
const models = strapi.models;
|
||||
const Model = strapi.models[model];
|
||||
|
||||
const virtualFields = [];
|
||||
const record = await Model
|
||||
.forge({
|
||||
[Model.primaryKey]: params[Model.primaryKey]
|
||||
})
|
||||
.fetch({
|
||||
withRelated: Model.associations.map(x => x.alias)
|
||||
});
|
||||
|
||||
const response = record ? record.toJSON() : record;
|
||||
|
||||
// Only update fields which are on this document.
|
||||
const values = params.parseRelationships === false ? params.values : Object.keys(JSON.parse(JSON.stringify(params.values))).reduce((acc, current) => {
|
||||
const association = Model.associations.filter(x => x.alias === current)[0];
|
||||
const details = Model._attributes[current];
|
||||
|
||||
if (_.get(Model._attributes, `${current}.isVirtual`) !== true && _.isUndefined(association)) {
|
||||
acc[current] = params.values[current];
|
||||
} else {
|
||||
switch (association.nature) {
|
||||
case 'oneToOne':
|
||||
if (response[current] !== params.values[current]) {
|
||||
const value = _.isNull(params.values[current]) ? response[current] : params.values;
|
||||
|
||||
const recordId = _.isNull(params.values[current]) ? value[Model.primaryKey] || value.id || value._id : typeof value[current] === 'object' ? value[current].id : value[current];
|
||||
|
||||
if (response[current] && _.isObject(response[current]) && response[current][Model.primaryKey] !== value[current]) {
|
||||
virtualFields.push(
|
||||
this.manageRelations(details.collection || details.model, {
|
||||
id: response[current][Model.primaryKey],
|
||||
values: {
|
||||
[details.via]: null
|
||||
},
|
||||
parseRelationships: false
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Remove previous relationship asynchronously if it exists.
|
||||
virtualFields.push(
|
||||
models[details.model || details.collection]
|
||||
.forge({ id : recordId })
|
||||
.fetch({
|
||||
withRelated: models[details.model || details.collection].associations.map(x => x.alias)
|
||||
})
|
||||
.then(response => {
|
||||
const record = response ? response.toJSON() : response;
|
||||
|
||||
if (record && _.isObject(record[details.via])) {
|
||||
return this.manageRelations(model, {
|
||||
id: record[details.via][models[details.model || details.collection].primaryKey] || record[details.via].id,
|
||||
values: {
|
||||
[current]: null
|
||||
},
|
||||
parseRelationships: false
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
})
|
||||
);
|
||||
|
||||
// Update the record on the other side.
|
||||
// When params.values[current] is null this means that we are removing the relation.
|
||||
virtualFields.push(this.manageRelations(details.model || details.collection, {
|
||||
id: recordId,
|
||||
values: {
|
||||
[details.via]: _.isNull(params.values[current]) ? null : value[Model.primaryKey] || params.id || params._id || value.id || value._id
|
||||
},
|
||||
parseRelationships: false
|
||||
}));
|
||||
|
||||
acc[current] = _.isNull(params.values[current]) ? null : typeof value[current] === 'object' ? value[current][Model.primaryKey] : value[current];
|
||||
}
|
||||
|
||||
break;
|
||||
case 'oneToMany':
|
||||
case 'manyToOne':
|
||||
case 'manyToMany':
|
||||
if (details.dominant === true) {
|
||||
acc[current] = params.values[current];
|
||||
} else if (response[current] && _.isArray(response[current]) && current !== 'id') {
|
||||
// Records to add in the relation.
|
||||
const toAdd = _.differenceWith(params.values[current], response[current], (a, b) =>
|
||||
((typeof a === 'number') ? a : a[Model.primaryKey].toString()) === b[Model.primaryKey].toString()
|
||||
);
|
||||
// Records to remove in the relation.
|
||||
const toRemove = _.differenceWith(response[current], params.values[current], (a, b) =>
|
||||
a[Model.primaryKey].toString() === ((typeof b === 'number') ? b : b[Model.primaryKey].toString())
|
||||
)
|
||||
.filter(x => toAdd.find(y => x.id === y.id) === undefined);
|
||||
|
||||
// Push the work into the flow process.
|
||||
toAdd.forEach(value => {
|
||||
value = (typeof value === 'number') ? { id: value } : value;
|
||||
|
||||
value[details.via] = parseFloat(params[Model.primaryKey]);
|
||||
params.values[Model.primaryKey] = parseFloat(params[Model.primaryKey]);
|
||||
|
||||
virtualFields.push(this.addRelation(details.model || details.collection, {
|
||||
id: value[Model.primaryKey] || value.id || value._id,
|
||||
values: association.nature === 'manyToMany' ? params.values : value,
|
||||
foreignKey: current
|
||||
}));
|
||||
});
|
||||
|
||||
toRemove.forEach(value => {
|
||||
value[details.via] = null;
|
||||
|
||||
virtualFields.push(this.removeRelation(details.model || details.collection, {
|
||||
id: value[Model.primaryKey] || value.id || value._id,
|
||||
values: association.nature === 'manyToMany' ? params.values : value,
|
||||
foreignKey: current
|
||||
}));
|
||||
});
|
||||
} else if (_.get(Model._attributes, `${current}.isVirtual`) !== true) {
|
||||
acc[current] = params.values[current];
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
if (!_.isEmpty(values)) {
|
||||
virtualFields.push(Model
|
||||
.forge({
|
||||
[Model.primaryKey]: params[Model.primaryKey]
|
||||
})
|
||||
.save(values, {
|
||||
patch: true
|
||||
}));
|
||||
} else {
|
||||
virtualFields.push(Promise.resolve(_.assign(response, params.values)));
|
||||
}
|
||||
|
||||
// Update virtuals fields.
|
||||
await Promise.all(virtualFields);
|
||||
},
|
||||
|
||||
addRelation: async function (model, params) {
|
||||
const Model = strapi.models[model];
|
||||
const association = Model.associations.filter(x => x.via === params.foreignKey)[0];
|
||||
|
||||
if (!association) {
|
||||
// Resolve silently.
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
switch (association.nature) {
|
||||
case 'oneToOne':
|
||||
case 'oneToMany':
|
||||
return this.manageRelations(model, params)
|
||||
case 'manyToMany':
|
||||
return Model.forge({
|
||||
[Model.primaryKey]: parseFloat(params[Model.primaryKey])
|
||||
})[association.alias]().attach(params.values[Model.primaryKey]);
|
||||
default:
|
||||
// Resolve silently.
|
||||
return Promise.resolve();
|
||||
}
|
||||
},
|
||||
|
||||
removeRelation: async function (model, params) {
|
||||
const Model = strapi.models[model];
|
||||
const association = Model.associations.filter(x => x.via === params.foreignKey)[0];
|
||||
|
||||
if (!association) {
|
||||
// Resolve silently.
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
switch (association.nature) {
|
||||
case 'oneToOne':
|
||||
case 'oneToMany':
|
||||
return this.manageRelations(model, params)
|
||||
case 'manyToMany':
|
||||
return Model.forge({
|
||||
[Model.primaryKey]: parseFloat(params[Model.primaryKey])
|
||||
})[association.alias]().detach(params.values[Model.primaryKey]);
|
||||
default:
|
||||
// Resolve silently.
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -28,7 +28,9 @@ module.exports = {
|
||||
qb.where(key, where.symbol, where.value);
|
||||
});
|
||||
|
||||
qb.orderBy(convertedParams.sort);
|
||||
if (convertedParams.sort) {
|
||||
qb.orderBy(convertedParams.sort);
|
||||
}
|
||||
|
||||
qb.offset(convertedParams.start);
|
||||
|
||||
@ -56,8 +58,10 @@ module.exports = {
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
||||
add: (values) => {
|
||||
return <%= globalID %>.forge(values).save();
|
||||
add: async (values) => {
|
||||
const data = await <%= globalID %>.forge(_.omit(values, _.keys(_.groupBy(strapi.models.<%= id %>.associations, 'alias')))).save();
|
||||
await strapi.hook.bookshelf.manageRelations('<%= id %>', _.merge(_.clone(data.toJSON()), { values }));
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -66,8 +70,9 @@ module.exports = {
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
||||
edit: (params, values) => {
|
||||
return <%= globalID %>.forge(params).save(values, {path: true});
|
||||
edit: async (params, values) => {
|
||||
await strapi.hook.bookshelf.manageRelations('<%= id %>', _.merge(_.clone(params), { values }));
|
||||
return <%= globalID %>.forge(params).save(_.omit(values, _.keys(_.groupBy(strapi.models.<%= id %>.associations, 'alias'))), {path: true});
|
||||
},
|
||||
|
||||
/**
|
||||
@ -77,172 +82,9 @@ module.exports = {
|
||||
*/
|
||||
|
||||
remove: (params) => {
|
||||
_.forEach(<%= globalID %>.associations, async association => {
|
||||
await <%= globalID %>.forge(params)[association.alias]().detach();
|
||||
});
|
||||
return <%= globalID %>.forge(params).destroy();
|
||||
},
|
||||
|
||||
/**
|
||||
* Add relation to a specific <%= id %> (only from a to-many relationships).
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
|
||||
addRelation: (params, values) => {
|
||||
const relation = _.find(strapi.models.<%= id %>.associations, {alias: params.relation});
|
||||
|
||||
if (!_.isEmpty(relation) && _.isArray(values)) {
|
||||
switch (relation.nature) {
|
||||
case 'manyToOne': {
|
||||
const PK = utils.getPK(_.get(relation, relation.type), undefined, strapi.models);
|
||||
|
||||
const arrayOfPromises = _.map(values, function (value) {
|
||||
const parameters = {};
|
||||
|
||||
_.set(parameters, PK, value);
|
||||
_.set(parameters, 'relation', relation.via);
|
||||
|
||||
return strapi.services[_.get(relation, relation.type)].editRelation(parameters, [_.get(params, 'id') || null]);
|
||||
});
|
||||
|
||||
return Promise.all(arrayOfPromises);
|
||||
}
|
||||
case 'manyToMany': {
|
||||
return <%= globalID %>.forge(_.omit(params, 'relation'))[params.relation]().attach(values);
|
||||
}
|
||||
default:
|
||||
return new Error('Impossible to add relation on this type of relation');
|
||||
}
|
||||
}
|
||||
|
||||
return new Error('Relationship Not Found');
|
||||
},
|
||||
|
||||
/**
|
||||
* Edit relation to a specific <%= id %>.
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
|
||||
editRelation: async (params, values) => {
|
||||
const relation = _.find(strapi.models.<%= id %>.associations, {alias: params.relation});
|
||||
|
||||
if (!_.isEmpty(relation) && _.isArray(values)) {
|
||||
switch (relation.nature) {
|
||||
case 'oneWay':
|
||||
case 'oneToOne':
|
||||
case 'oneToMany': {
|
||||
const data = _.set({}, params.relation, _.first(values) || null);
|
||||
|
||||
return <%= globalID %>.forge(_.omit(params, 'relation')).save(data, {path: true});
|
||||
}
|
||||
case 'manyToOne': {
|
||||
const PK = utils.getPK(_.get(relation, relation.type), undefined, strapi.models);
|
||||
|
||||
const results = await <%= globalID %>.forge(_.omit(params, 'relation')).fetch({
|
||||
withRelated: _.get(params, 'relation')
|
||||
});
|
||||
|
||||
// Remove relationship between records.
|
||||
const data = results.toJSON() || {};
|
||||
const currentValues = _.keys(_.groupBy(_.get(data, _.get(params, 'relation')), PK));
|
||||
const valuesToRemove = _.difference(currentValues, values);
|
||||
|
||||
const arrayOfRemovePromises = _.map(valuesToRemove, value => {
|
||||
const params = {};
|
||||
|
||||
_.set(params, PK, value);
|
||||
_.set(params, 'relation', relation.via);
|
||||
|
||||
return strapi.services[_.get(relation, relation.type)].editRelation(params, [null]);
|
||||
});
|
||||
|
||||
await Promise.all(arrayOfRemovePromises);
|
||||
|
||||
// Add relationship between records.
|
||||
const arrayOfAddPromises = _.map(values, value => {
|
||||
const params = {};
|
||||
|
||||
_.set(params, PK, value);
|
||||
_.set(params, 'relation', relation.via);
|
||||
|
||||
return strapi.services[_.get(relation, relation.type)].editRelation(params, [_.get(params, 'id') || null]);
|
||||
});
|
||||
|
||||
await Promise.all(arrayOfAddPromises);
|
||||
|
||||
return;
|
||||
}
|
||||
case 'manyToMany': {
|
||||
const results = <%= globalID %>.forge(_.omit(params, 'relation')).fetch({
|
||||
withRelated: _.get(params, 'relation')
|
||||
});
|
||||
|
||||
const data = results.toJSON() || {};
|
||||
const PK = utils.getPK('<%= globalID %>', <%= globalID %>, strapi.models);
|
||||
|
||||
// Values to add
|
||||
const currentValues = _.keys(_.groupBy(_.get(data, _.get(params, 'relation')), PK));
|
||||
const valuesToAdd = _.difference(_.map(values, o => {
|
||||
return o.toString();
|
||||
}), currentValues);
|
||||
|
||||
try {
|
||||
await <%= globalID %>.forge(_.omit(params, 'relation'))[params.relation]().attach(valuesToAdd);
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// Values to remove
|
||||
const valuesToDrop = _.difference(currentValues, _.map(values, o => {
|
||||
return o.toString();
|
||||
}));
|
||||
|
||||
try {
|
||||
await <%= globalID %>.forge(_.omit(params, 'relation'))[params.relation]().detach(valuesToDrop);
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
default:
|
||||
return new Error('Impossible to update relation on this type of relation');
|
||||
}
|
||||
}
|
||||
|
||||
return new Error ('Relationship Not Found');
|
||||
},
|
||||
|
||||
/**
|
||||
* Promise to remove a specific entry from a specific <%= id %> (only from a to-many relationships).
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
||||
removeRelation: (params, values) => {
|
||||
const relation = _.find(strapi.models.<%= id %>.associations, {alias: params.relation});
|
||||
|
||||
if (!_.isEmpty(relation) && _.isArray(values)) {
|
||||
switch (relation.nature) {
|
||||
case 'manyToOne':
|
||||
const PK = utils.getPK(_.get(relation, relation.type), undefined, strapi.models);
|
||||
|
||||
const arrayOfPromises = _.map(values, value => {
|
||||
const parameters = {};
|
||||
|
||||
_.set(parameters, PK, value);
|
||||
_.set(parameters, 'relation', relation.via);
|
||||
|
||||
return strapi.services[_.get(relation, relation.type)].editRelation(parameters, [null]);
|
||||
});
|
||||
|
||||
return Promise.all(arrayOfPromises);
|
||||
case 'manyToMany':
|
||||
return <%= globalID %>.forge(_.omit(params, 'relation'))[params.relation]().detach(values);
|
||||
default:
|
||||
return new Error('Impossible to delete relation on this type of relation');
|
||||
}
|
||||
}
|
||||
|
||||
return new Error('Relationship Not Found');
|
||||
}
|
||||
};
|
||||
|
||||
@ -26,7 +26,7 @@ module.exports = {
|
||||
.sort(convertedParams.sort)
|
||||
.skip(convertedParams.start)
|
||||
.limit(convertedParams.limit)
|
||||
.populate(_.keys(_.pickBy(strapi.models.<%= humanizeId %>.attributes, { autoPopulate: true })).join(' '));
|
||||
.populate(_.keys(_.groupBy(_.reject(strapi.models.<%= id %>.associations, {autoPopulate: false}), 'alias')).join(' '));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -38,7 +38,7 @@ module.exports = {
|
||||
fetch: (params) => {
|
||||
return <%= globalID %>
|
||||
.findOne(params)
|
||||
.populate(_.keys(_.pickBy(strapi.models.<%= humanizeId %>.attributes, { autoPopulate: true })).join(' '));
|
||||
.populate(_.keys(_.groupBy(_.reject(strapi.models.<%= id %>.associations, {autoPopulate: false}), 'alias')).join(' '));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -47,8 +47,10 @@ module.exports = {
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
||||
add: (values) => {
|
||||
return <%= globalID %>.create(values);
|
||||
add: async (values) => {
|
||||
const data = await <%= globalID %>.create(_.omit(values, _.keys(_.groupBy(strapi.models.<%= id %>.associations, 'alias'))));
|
||||
await strapi.hook.mongoose.manageRelations('<%= id %>', _.merge(_.clone(data), { values }));
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -57,10 +59,11 @@ module.exports = {
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
||||
edit: (params, values) => {
|
||||
edit: async (params, values) => {
|
||||
// Note: The current method will return the full response of Mongo.
|
||||
// To get the updated object, you have to execute the `findOne()` method
|
||||
// or use the `findOneOrUpdate()` method with `{ new:true }` option.
|
||||
await strapi.hook.mongoose.manageRelations('<%= id %>', _.merge(_.clone(params), { values }));
|
||||
return <%= globalID %>.update(params, values, { multi: true });
|
||||
},
|
||||
|
||||
@ -70,9 +73,22 @@ module.exports = {
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
||||
remove: params => {
|
||||
remove: async params => {
|
||||
// Note: To get the full response of Mongo, use the `remove()` method
|
||||
// or add spent the parameter `{ passRawResult: true }` as second argument.
|
||||
return <%= globalID %>.findOneAndRemove(params, {});
|
||||
const data = await <%= globalID %>.findOneAndRemove(params, {})
|
||||
.populate(_.keys(_.groupBy(_.reject(strapi.models.<%= id %>.associations, {autoPopulate: false}), 'alias')).join(' '));
|
||||
|
||||
_.forEach(<%= globalID %>.associations, async association => {
|
||||
const search = (_.endsWith(association.nature, 'One')) ? { [association.via]: data._id } : { [association.via]: { $in: [data._id] } };
|
||||
const update = (_.endsWith(association.nature, 'One')) ? { [association.via]: null } : { $pull: { [association.via]: data._id } };
|
||||
|
||||
await strapi.models[association.model || association.collection].update(
|
||||
search,
|
||||
update,
|
||||
{ multi: true });
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"connection": "<%= connection %>",
|
||||
"tableName": "<%= idPluralized %>",
|
||||
"collectionName": "<%= idPluralized %>",
|
||||
"options": {
|
||||
"increments": true,
|
||||
"timestamps": true,
|
||||
|
||||
@ -342,6 +342,151 @@ module.exports = function (strapi) {
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
manageRelations: async function (model, params) {
|
||||
const models = strapi.models;
|
||||
const Model = strapi.models[model];
|
||||
|
||||
const virtualFields = [];
|
||||
const response = await Model
|
||||
.findOne({
|
||||
[Model.primaryKey]: params._id || params.id
|
||||
})
|
||||
.populate(_.keys(_.groupBy(_.reject(Model.associations, {autoPopulate: false}), 'alias')).join(' '));
|
||||
|
||||
// Only update fields which are on this document.
|
||||
const values = params.parseRelationships === false ? params.values : Object.keys(JSON.parse(JSON.stringify(params.values))).reduce((acc, current) => {
|
||||
const association = Model.associations.filter(x => x.alias === current)[0];
|
||||
const details = Model._attributes[current];
|
||||
|
||||
if (_.get(Model._attributes, `${current}.isVirtual`) !== true && _.isUndefined(association)) {
|
||||
acc[current] = params.values[current];
|
||||
} else {
|
||||
switch (association.nature) {
|
||||
case 'oneToOne':
|
||||
if (response[current] !== params.values[current]) {
|
||||
const value = _.isNull(params.values[current]) ? response[current] : params.values;
|
||||
|
||||
const recordId = _.isNull(params.values[current]) ? value[Model.primaryKey] || value.id || value._id : value[current];
|
||||
|
||||
if (response[current] && _.isObject(response[current]) && response[current][Model.primaryKey] !== value[current]) {
|
||||
virtualFields.push(
|
||||
this.manageRelations(details.model || details.collection, {
|
||||
_id: response[current][Model.primaryKey],
|
||||
values: {
|
||||
[details.via]: null
|
||||
},
|
||||
parseRelationships: false
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Remove previous relationship asynchronously if it exists.
|
||||
virtualFields.push(
|
||||
models[details.model || details.collection]
|
||||
.findOne({ id : recordId })
|
||||
.populate(_.keys(_.groupBy(_.reject(models[details.model || details.collection].associations, {autoPopulate: false}), 'alias')).join(' '))
|
||||
.then(record => {
|
||||
if (record && _.isObject(record[details.via])) {
|
||||
return this.manageRelations(details.model || details.collection, {
|
||||
id: record[details.via][Model.primaryKey] || record[details.via].id,
|
||||
values: {
|
||||
[current]: null
|
||||
},
|
||||
parseRelationships: false
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
})
|
||||
);
|
||||
|
||||
// Update the record on the other side.
|
||||
// When params.values[current] is null this means that we are removing the relation.
|
||||
virtualFields.push(this.manageRelations(details.model || details.collection, {
|
||||
id: recordId,
|
||||
values: {
|
||||
[details.via]: _.isNull(params.values[current]) ? null : value[Model.primaryKey] || params.id || params._id || value.id || value._id
|
||||
},
|
||||
parseRelationships: false
|
||||
}));
|
||||
|
||||
acc[current] = _.isNull(params.values[current]) ? null : value[current];
|
||||
}
|
||||
|
||||
break;
|
||||
case 'oneToMany':
|
||||
case 'manyToOne':
|
||||
case 'manyToMany':
|
||||
if (details.dominant === true) {
|
||||
acc[current] = params.values[current];
|
||||
} else if (response[current] && _.isArray(response[current]) && current !== 'id') {
|
||||
// Records to add in the relation.
|
||||
const toAdd = _.differenceWith(params.values[current], response[current], (a, b) =>
|
||||
((typeof a === 'string') ? a : a[Model.primaryKey].toString()) === b[Model.primaryKey].toString()
|
||||
);
|
||||
// Records to remove in the relation.
|
||||
const toRemove = _.differenceWith(response[current], params.values[current], (a, b) =>
|
||||
a[Model.primaryKey].toString() === ((typeof b === 'string') ? b : b[Model.primaryKey].toString())
|
||||
)
|
||||
.filter(x => toAdd.find(y => x.id === y.id) === undefined);
|
||||
|
||||
// Push the work into the flow process.
|
||||
toAdd.forEach(value => {
|
||||
value = (typeof value === 'string') ? { _id: value } : value;
|
||||
|
||||
if (association.nature === 'manyToMany' && !_.isArray(params.values[Model.primaryKey])) {
|
||||
value[details.via] = (value[details.via] || []).concat([response[Model.primaryKey]]);
|
||||
} else {
|
||||
value[details.via] = params[Model.primaryKey];
|
||||
}
|
||||
|
||||
virtualFields.push(this.manageRelations(details.model || details.collection, {
|
||||
id: value[Model.primaryKey] || value.id || value._id,
|
||||
values: value,
|
||||
foreignKey: current
|
||||
}));
|
||||
});
|
||||
|
||||
toRemove.forEach(value => {
|
||||
value = (typeof value === 'string') ? { _id: value } : value;
|
||||
|
||||
if (association.nature === 'manyToMany' && !_.isArray(params.values[Model.primaryKey])) {
|
||||
value[details.via] = value[details.via].filter(x => x.toString() !== response[Model.primaryKey].toString());
|
||||
} else {
|
||||
value[details.via] = null;
|
||||
}
|
||||
|
||||
virtualFields.push(this.manageRelations(details.model || details.collection, {
|
||||
id: value[Model.primaryKey] || value.id || value._id,
|
||||
values: value,
|
||||
foreignKey: current
|
||||
}));
|
||||
});
|
||||
} else if (_.get(Model._attributes, `${current}.isVirtual`) !== true) {
|
||||
acc[current] = params.values[current];
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
virtualFields.push(Model
|
||||
.update({
|
||||
[Model.primaryKey]: params[Model.primaryKey] || params.id
|
||||
}, values, {
|
||||
strict: false
|
||||
}));
|
||||
|
||||
// Update virtuals fields.
|
||||
const process = await Promise.all(virtualFields);
|
||||
|
||||
return process[process.length - 1];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ module.exports = {
|
||||
return await this
|
||||
.forge()
|
||||
.fetchAll({
|
||||
withRelated: this.associations.map(x => x.alias).join(' ')
|
||||
withRelated: this.associations.map(x => x.alias)
|
||||
});
|
||||
},
|
||||
|
||||
@ -21,7 +21,7 @@ module.exports = {
|
||||
[this.primaryKey]: params[this.primaryKey]
|
||||
})
|
||||
.fetch({
|
||||
withRelated: this.associations.map(x => x.alias).join(' ')
|
||||
withRelated: this.associations.map(x => x.alias)
|
||||
});
|
||||
|
||||
return record ? record.toJSON() : record;
|
||||
|
||||
@ -49,8 +49,8 @@
|
||||
"strapi-helper-plugin": "3.0.0-alpha.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^5.1.0",
|
||||
"eslint": "^4.9.0",
|
||||
"cross-env": "^5.1.1",
|
||||
"eslint": "^4.10.0",
|
||||
"eslint-config-airbnb": "^15.1.0",
|
||||
"eslint-config-airbnb-base": "^11.3.2",
|
||||
"eslint-config-prettier": "^2.6.0",
|
||||
|
||||
@ -36,8 +36,8 @@
|
||||
"strapi-generate-api": "3.0.0-alpha.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^5.1.0",
|
||||
"eslint": "^4.9.0",
|
||||
"cross-env": "^5.1.1",
|
||||
"eslint": "^4.10.0",
|
||||
"eslint-config-airbnb": "^15.1.0",
|
||||
"eslint-config-airbnb-base": "^11.3.2",
|
||||
"eslint-config-prettier": "^2.6.0",
|
||||
|
||||
@ -59,7 +59,9 @@ module.exports = {
|
||||
|
||||
generateAPI: (name, description, connection, collectionName, attributes) => {
|
||||
description = _.replace(description, /\"/g, '\\"');
|
||||
|
||||
|
||||
const template = _.get(strapi.config.currentEnvironment, `database.connections.${connection}.connector`, 'strapi-mongoose').split('-')[1];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const scope = {
|
||||
generatorType: 'api',
|
||||
@ -70,7 +72,8 @@ module.exports = {
|
||||
description,
|
||||
attributes,
|
||||
connection,
|
||||
collectionName: !_.isEmpty(collectionName) ? collectionName : undefined
|
||||
collectionName: !_.isEmpty(collectionName) ? collectionName : undefined,
|
||||
tpl: template
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -33,8 +33,8 @@
|
||||
"reactstrap": "^4.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^5.1.0",
|
||||
"eslint": "^4.9.0",
|
||||
"cross-env": "^5.1.1",
|
||||
"eslint": "^4.10.0",
|
||||
"eslint-config-airbnb": "^15.1.0",
|
||||
"eslint-config-airbnb-base": "^11.3.2",
|
||||
"eslint-config-prettier": "^2.6.0",
|
||||
|
||||
@ -242,7 +242,7 @@ module.exports = {
|
||||
collection: association.collection,
|
||||
via: association.via || undefined,
|
||||
nature: infos.nature,
|
||||
autoPopulate: (_.get(association, 'autoPopulate') || _.get(strapi.config, 'jsonapi.enabled')) === true,
|
||||
autoPopulate: _.get(association, 'autoPopulate', true),
|
||||
dominant: details.dominant !== true
|
||||
});
|
||||
} else if (association.hasOwnProperty('model')) {
|
||||
@ -252,7 +252,7 @@ module.exports = {
|
||||
model: association.model,
|
||||
via: association.via || undefined,
|
||||
nature: infos.nature,
|
||||
autoPopulate: (_.get(association, 'autoPopulate') || _.get(strapi.config, 'jsonapi.enabled')) === true,
|
||||
autoPopulate: _.get(association, 'autoPopulate', true),
|
||||
dominant: details.dominant !== true
|
||||
});
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
const glob = require('glob');
|
||||
const path = require('path');
|
||||
const { after, includes, indexOf, dropRight, uniq, isUndefined, get, defaultsDeep, set } = require('lodash');
|
||||
const { after, includes, indexOf, dropRight, uniq, isUndefined, get, defaultsDeep, set, merge} = require('lodash');
|
||||
|
||||
module.exports = function() {
|
||||
// Method to initialize hooks and emit an event.
|
||||
@ -16,7 +16,9 @@ module.exports = function() {
|
||||
}
|
||||
}, this.config.hook.timeout || 1000);
|
||||
|
||||
module(this).initialize.call(module, err => {
|
||||
const loadedModule = module(this);
|
||||
|
||||
loadedModule.initialize.call(module, err => {
|
||||
timeout = false;
|
||||
|
||||
if (err) {
|
||||
@ -26,6 +28,9 @@ module.exports = function() {
|
||||
}
|
||||
|
||||
this.hook[hook].loaded = true;
|
||||
|
||||
this.hook[hook] = merge(this.hook[hook], loadedModule);
|
||||
|
||||
this.emit('hook:' + hook + ':loaded');
|
||||
// Remove listeners.
|
||||
this.removeAllListeners('hook:' + hook + ':loaded');
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
const glob = require('glob');
|
||||
const path = require('path');
|
||||
const { parallel } = require('async');
|
||||
const { after, includes, indexOf, drop, dropRight, uniq, defaultsDeep, get, set, isEmpty, isUndefined, union } = require('lodash');
|
||||
const { after, includes, indexOf, drop, dropRight, uniq, defaultsDeep, get, set, isEmpty, isUndefined, union, merge } = require('lodash');
|
||||
|
||||
module.exports = function() {
|
||||
const accepted = Object.keys(this.plugins).map(url => `^\/${url}/`).concat(['^\/admin/']);
|
||||
@ -26,6 +26,8 @@ module.exports = function() {
|
||||
}
|
||||
}, this.config.middleware.timeout || 1000);
|
||||
|
||||
this.middleware[middleware] = merge(this.middleware[middleware], module);
|
||||
|
||||
module.initialize.call(module, err => {
|
||||
timeout = false;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user