mirror of
https://github.com/strapi/strapi.git
synced 2025-07-25 09:56:53 +00:00
Group schema + auto populate for mongoose
This commit is contained in:
parent
2753176d89
commit
5f29e81556
@ -119,7 +119,8 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
|
||||
// Add every relationships to the loaded model for Bookshelf.
|
||||
// Basic attributes don't need this-- only relations.
|
||||
_.forEach(definition.attributes, (details, name) => {
|
||||
Object.keys(definition.attributes).forEach(name => {
|
||||
const details = definition.attributes[name];
|
||||
if (details.type !== undefined) {
|
||||
return;
|
||||
}
|
||||
@ -433,7 +434,7 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
attrs[key] =
|
||||
definition.attributes[key].repeatable === true
|
||||
? groups
|
||||
: _.first(groups);
|
||||
: _.first(groups) || null;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -43,6 +43,7 @@ module.exports = function(strapi) {
|
||||
.map(async connectionName => {
|
||||
const connection = connections[connectionName];
|
||||
const instance = new Mongoose();
|
||||
|
||||
_.defaults(connection.settings, strapi.config.hook.settings.mongoose);
|
||||
|
||||
const {
|
||||
@ -65,9 +66,6 @@ module.exports = function(strapi) {
|
||||
|
||||
// Connect to mongo database
|
||||
const connectOptions = {};
|
||||
const options = {
|
||||
useFindAndModify: false,
|
||||
};
|
||||
|
||||
if (!_.isEmpty(username)) {
|
||||
connectOptions.user = username;
|
||||
@ -86,8 +84,6 @@ module.exports = function(strapi) {
|
||||
connectOptions.dbName = database;
|
||||
connectOptions.useCreateIndex = true;
|
||||
|
||||
options.debug = debug === true || debug === 'true';
|
||||
|
||||
try {
|
||||
/* FIXME: for now, mongoose doesn't support srv auth except the way including user/pass in URI.
|
||||
* https://github.com/Automattic/mongoose/issues/6881 */
|
||||
@ -117,7 +113,8 @@ module.exports = function(strapi) {
|
||||
require(initFunctionPath)(instance, connection);
|
||||
}
|
||||
|
||||
Object.keys(options, key => instance.set(key, options[key]));
|
||||
instance.set('debug', debug === true || debug === 'true');
|
||||
instance.set('useFindAndModify', false);
|
||||
|
||||
const ctx = {
|
||||
instance,
|
||||
|
@ -2,41 +2,107 @@
|
||||
|
||||
const _ = require('lodash');
|
||||
const mongoose = require('mongoose');
|
||||
const mongooseUtils = require('mongoose/lib/utils');
|
||||
|
||||
const utilsModels = require('strapi-utils').models;
|
||||
const utils = require('./utils/');
|
||||
const utils = require('./utils');
|
||||
const relations = require('./relations');
|
||||
|
||||
module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
const { instance } = ctx;
|
||||
|
||||
const loadedAttributes = _.after(_.size(models), () => {
|
||||
_.forEach(models, (definition, model) => {
|
||||
try {
|
||||
let collection =
|
||||
strapi.config.hook.settings.mongoose.collections[
|
||||
mongooseUtils.toCollectionName(definition.globalName)
|
||||
];
|
||||
|
||||
// Parse every authenticated model.
|
||||
Object.keys(models).map(model => {
|
||||
const definition = models[model];
|
||||
definition.orm = 'mongoose';
|
||||
definition.associations = [];
|
||||
definition.globalName = _.upperFirst(_.camelCase(definition.globalId));
|
||||
definition.loadedModel = {};
|
||||
// Set the default values to model settings.
|
||||
_.defaults(definition, {
|
||||
primaryKey: '_id',
|
||||
});
|
||||
|
||||
if (!plugin) {
|
||||
global[definition.globalName] = {};
|
||||
}
|
||||
|
||||
const groupAttributes = Object.keys(definition.attributes).filter(
|
||||
key => definition.attributes[key].type === 'group'
|
||||
);
|
||||
|
||||
const scalarAttributes = Object.keys(definition.attributes).filter(key => {
|
||||
const { type } = definition.attributes[key];
|
||||
return type !== undefined && type !== null && type !== 'group';
|
||||
});
|
||||
|
||||
const relationalAttributes = Object.keys(definition.attributes).filter(
|
||||
key => {
|
||||
const { type } = definition.attributes[key];
|
||||
return type === undefined;
|
||||
}
|
||||
);
|
||||
|
||||
// handle gorup attrs
|
||||
if (groupAttributes.length > 0) {
|
||||
// create join morph collection thingy
|
||||
groupAttributes.forEach(name => {
|
||||
definition.loadedModel[name] = [
|
||||
{
|
||||
kind: String,
|
||||
ref: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
refPath: `${name}.kind`,
|
||||
},
|
||||
},
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
// handle scalar attrs
|
||||
scalarAttributes.forEach(name => {
|
||||
const attr = definition.attributes[name];
|
||||
|
||||
definition.loadedModel[name] = {
|
||||
...attr,
|
||||
type: utils(instance).convertType(attr.type),
|
||||
};
|
||||
});
|
||||
|
||||
// handle relational attrs
|
||||
relationalAttributes.forEach(name => {
|
||||
buildRelation({
|
||||
definition,
|
||||
model,
|
||||
instance,
|
||||
name,
|
||||
attribute: definition.attributes[name],
|
||||
});
|
||||
});
|
||||
|
||||
const schema = new instance.Schema(
|
||||
_.omitBy(definition.loadedModel, ({ type }) => type === 'virtual')
|
||||
);
|
||||
|
||||
// Initialize lifecycle callbacks.
|
||||
const preLifecycle = {
|
||||
validate: 'beforeCreate',
|
||||
find: 'beforeFetchAll',
|
||||
findOne: 'beforeFetch',
|
||||
findOneAndUpdate: 'beforeUpdate',
|
||||
findOneAndRemove: 'beforeDestroy',
|
||||
remove: 'beforeDestroy',
|
||||
update: 'beforeUpdate',
|
||||
updateOne: 'beforeUpdate',
|
||||
find: 'beforeFetchAll',
|
||||
findOne: 'beforeFetch',
|
||||
save: 'beforeSave',
|
||||
};
|
||||
|
||||
const findLifecycles = [
|
||||
'find',
|
||||
'findOne',
|
||||
'findOneAndUpdate',
|
||||
'findOneAndRemove',
|
||||
];
|
||||
|
||||
/*
|
||||
Override populate path for polymorphic association.
|
||||
It allows us to make Upload.find().populate('related')
|
||||
@ -44,77 +110,24 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
*/
|
||||
|
||||
const morphAssociations = definition.associations.filter(
|
||||
association =>
|
||||
association.nature.toLowerCase().indexOf('morph') !== -1
|
||||
association => association.nature.toLowerCase().indexOf('morph') !== -1
|
||||
);
|
||||
|
||||
if (morphAssociations.length > 0) {
|
||||
morphAssociations.forEach(association => {
|
||||
Object.keys(preLifecycle)
|
||||
.filter(key => key.indexOf('find') !== -1)
|
||||
.forEach(key => {
|
||||
collection.schema.pre(key, function(next) {
|
||||
if (
|
||||
this._mongooseOptions.populate &&
|
||||
this._mongooseOptions.populate[association.alias]
|
||||
) {
|
||||
if (
|
||||
association.nature === 'oneToManyMorph' ||
|
||||
association.nature === 'manyToManyMorph'
|
||||
) {
|
||||
this._mongooseOptions.populate[
|
||||
association.alias
|
||||
].match = {
|
||||
[`${association.via}.${association.filter}`]: association.alias,
|
||||
[`${association.via}.kind`]: definition.globalId,
|
||||
};
|
||||
|
||||
// Select last related to an entity.
|
||||
this._mongooseOptions.populate[
|
||||
association.alias
|
||||
].options = {
|
||||
sort: '-createdAt',
|
||||
};
|
||||
} else {
|
||||
this._mongooseOptions.populate[
|
||||
association.alias
|
||||
].path = `${association.alias}.ref`;
|
||||
}
|
||||
} else {
|
||||
if (!this._mongooseOptions.populate) {
|
||||
this._mongooseOptions.populate = {};
|
||||
}
|
||||
|
||||
// Images are not displayed in populated data.
|
||||
// We automatically populate morph relations.
|
||||
if (
|
||||
association.nature === 'oneToManyMorph' ||
|
||||
association.nature === 'manyToManyMorph'
|
||||
) {
|
||||
this._mongooseOptions.populate[association.alias] = {
|
||||
path: association.alias,
|
||||
match: {
|
||||
[`${association.via}.${association.filter}`]: association.alias,
|
||||
[`${association.via}.kind`]: definition.globalId,
|
||||
},
|
||||
options: {
|
||||
sort: '-createdAt',
|
||||
},
|
||||
select: undefined,
|
||||
model: undefined,
|
||||
_docs: {},
|
||||
};
|
||||
}
|
||||
}
|
||||
next();
|
||||
const populateFn = createOnFetchPopulateFn({
|
||||
groupAttributes,
|
||||
morphAssociations,
|
||||
definition,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_.forEach(preLifecycle, (fn, key) => {
|
||||
findLifecycles.forEach(key => {
|
||||
schema.pre(key, populateFn);
|
||||
});
|
||||
|
||||
Object.keys(preLifecycle).forEach(key => {
|
||||
const fn = preLifecycle[key];
|
||||
|
||||
if (_.isFunction(target[model.toLowerCase()][fn])) {
|
||||
collection.schema.pre(key, function(next) {
|
||||
schema.pre(key, function(next) {
|
||||
target[model.toLowerCase()]
|
||||
[fn](this)
|
||||
.then(next)
|
||||
@ -136,9 +149,11 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
|
||||
// Mongoose doesn't allow post 'remove' event on model.
|
||||
// See https://github.com/Automattic/mongoose/issues/3054
|
||||
_.forEach(postLifecycle, (fn, key) => {
|
||||
Object.keys(postLifecycle).forEach(key => {
|
||||
const fn = postLifecycle[key];
|
||||
|
||||
if (_.isFunction(target[model.toLowerCase()][fn])) {
|
||||
collection.schema.post(key, function(doc, next) {
|
||||
schema.post(key, function(doc, next) {
|
||||
target[model.toLowerCase()]
|
||||
[fn](this, doc)
|
||||
.then(next)
|
||||
@ -156,7 +171,7 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
return model.type === 'virtual';
|
||||
}),
|
||||
(value, key) => {
|
||||
collection.schema.virtual(key.replace('_v', ''), {
|
||||
schema.virtual(key.replace('_v', ''), {
|
||||
ref: value.ref,
|
||||
localField: '_id',
|
||||
foreignField: value.via,
|
||||
@ -175,9 +190,9 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
? _.get(definition, 'options.timestamps[1]')
|
||||
: 'updatedAt',
|
||||
};
|
||||
collection.schema.set('timestamps', timestamps);
|
||||
schema.set('timestamps', timestamps);
|
||||
} else {
|
||||
collection.schema.set(
|
||||
schema.set(
|
||||
'timestamps',
|
||||
_.get(definition, 'options.timestamps') === true
|
||||
);
|
||||
@ -189,7 +204,7 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
: false
|
||||
);
|
||||
}
|
||||
collection.schema.set(
|
||||
schema.set(
|
||||
'minimize',
|
||||
_.get(definition, 'options.minimize', false) === true
|
||||
);
|
||||
@ -197,7 +212,7 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
// Save all attributes (with timestamps)
|
||||
target[model].allAttributes = _.clone(definition.attributes);
|
||||
|
||||
collection.schema.options.toObject = collection.schema.options.toJSON = {
|
||||
schema.options.toObject = schema.options.toJSON = {
|
||||
virtuals: true,
|
||||
transform: function(doc, returned) {
|
||||
// Remover $numberDecimal nested property.
|
||||
@ -221,21 +236,32 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
break;
|
||||
case 'manyMorphToMany':
|
||||
case 'manyMorphToOne':
|
||||
returned[association.alias] = returned[
|
||||
association.alias
|
||||
].map(obj => obj.ref);
|
||||
returned[association.alias] = returned[association.alias].map(
|
||||
obj => obj.ref
|
||||
);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
groupAttributes.forEach(name => {
|
||||
const attribute = definition.attributes[name];
|
||||
|
||||
if (Array.isArray(returned[name])) {
|
||||
const groups = returned[name].map(el => el.ref);
|
||||
// Reformat data by bypassing the many-to-many relationship.
|
||||
returned[name] =
|
||||
attribute.repeatable === true ? groups : _.first(groups) || null;
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// Instantiate model.
|
||||
const Model = instance.model(
|
||||
definition.globalId,
|
||||
collection.schema,
|
||||
schema,
|
||||
definition.collectionName
|
||||
);
|
||||
|
||||
@ -249,94 +275,87 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
// Push attributes to be aware of model schema.
|
||||
target[model]._attributes = definition.attributes;
|
||||
target[model].updateRelations = relations.update;
|
||||
} catch (err) {
|
||||
strapi.log.error('Impossible to register the `' + model + '` model.');
|
||||
strapi.log.error(err);
|
||||
strapi.stop();
|
||||
});
|
||||
};
|
||||
|
||||
const createOnFetchPopulateFn = ({
|
||||
morphAssociations,
|
||||
groupAttributes,
|
||||
definition,
|
||||
}) => {
|
||||
return function(next) {
|
||||
morphAssociations.forEach(association => {
|
||||
if (
|
||||
this._mongooseOptions.populate &&
|
||||
this._mongooseOptions.populate[association.alias]
|
||||
) {
|
||||
if (
|
||||
association.nature === 'oneToManyMorph' ||
|
||||
association.nature === 'manyToManyMorph'
|
||||
) {
|
||||
this._mongooseOptions.populate[association.alias].match = {
|
||||
[`${association.via}.${association.filter}`]: association.alias,
|
||||
[`${association.via}.kind`]: definition.globalId,
|
||||
};
|
||||
|
||||
// Select last related to an entity.
|
||||
this._mongooseOptions.populate[association.alias].options = {
|
||||
sort: '-createdAt',
|
||||
};
|
||||
} else {
|
||||
this._mongooseOptions.populate[
|
||||
association.alias
|
||||
].path = `${association.alias}.ref`;
|
||||
}
|
||||
} else {
|
||||
if (!this._mongooseOptions.populate) {
|
||||
this._mongooseOptions.populate = {};
|
||||
}
|
||||
// Images are not displayed in populated data.
|
||||
// We automatically populate morph relations.
|
||||
if (
|
||||
association.nature === 'oneToManyMorph' ||
|
||||
association.nature === 'manyToManyMorph'
|
||||
) {
|
||||
this._mongooseOptions.populate[association.alias] = {
|
||||
path: association.alias,
|
||||
match: {
|
||||
[`${association.via}.${association.filter}`]: association.alias,
|
||||
[`${association.via}.kind`]: definition.globalId,
|
||||
},
|
||||
options: {
|
||||
sort: '-createdAt',
|
||||
},
|
||||
select: undefined,
|
||||
model: undefined,
|
||||
_docs: {},
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
groupAttributes.forEach(name => {
|
||||
if (
|
||||
this._mongooseOptions.populate &&
|
||||
this._mongooseOptions.populate[name]
|
||||
) {
|
||||
this._mongooseOptions.populate[name].path = `${name}.ref`;
|
||||
} else {
|
||||
this._mongooseOptions.populate[name] = {
|
||||
path: `${name}.ref`,
|
||||
_docs: {},
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Parse every authenticated model.
|
||||
_.forEach(models, (definition, model) => {
|
||||
definition.globalName = _.upperFirst(_.camelCase(definition.globalId));
|
||||
next();
|
||||
};
|
||||
};
|
||||
|
||||
// Make sure the model has a connection.
|
||||
// If not, use the default connection.
|
||||
if (_.isEmpty(definition.connection)) {
|
||||
definition.connection =
|
||||
strapi.config.currentEnvironment.database.defaultConnection;
|
||||
}
|
||||
|
||||
// Make sure this connection exists.
|
||||
if (!_.has(strapi.config.connections, definition.connection)) {
|
||||
strapi.log.error(
|
||||
'The connection `' +
|
||||
definition.connection +
|
||||
'` specified in the `' +
|
||||
model +
|
||||
'` model does not exist.'
|
||||
);
|
||||
strapi.stop();
|
||||
}
|
||||
|
||||
// Add some informations about ORM & client connection
|
||||
definition.orm = 'mongoose';
|
||||
definition.client = _.get(
|
||||
strapi.config.connections[definition.connection],
|
||||
'client'
|
||||
);
|
||||
definition.associations = [];
|
||||
|
||||
// Register the final model for Mongoose.
|
||||
definition.loadedModel = _.cloneDeep(definition.attributes);
|
||||
|
||||
// Initialize the global variable with the
|
||||
// capitalized model name.
|
||||
if (!plugin) {
|
||||
global[definition.globalName] = {};
|
||||
}
|
||||
|
||||
if (_.isEmpty(definition.attributes)) {
|
||||
// Generate empty schema
|
||||
_.set(
|
||||
strapi.config.hook.settings.mongoose,
|
||||
'collections.' +
|
||||
mongooseUtils.toCollectionName(definition.globalName) +
|
||||
'.schema',
|
||||
new instance.Schema({})
|
||||
);
|
||||
|
||||
return loadedAttributes();
|
||||
}
|
||||
|
||||
// Call this callback function after we are done parsing
|
||||
// all attributes for relationships-- see below.
|
||||
const done = _.after(_.size(definition.attributes), () => {
|
||||
// Generate schema without virtual populate
|
||||
const schema = new instance.Schema(
|
||||
_.omitBy(definition.loadedModel, model => {
|
||||
return model.type === 'virtual';
|
||||
})
|
||||
);
|
||||
|
||||
_.set(
|
||||
strapi.config.hook.settings.mongoose,
|
||||
'collections.' +
|
||||
mongooseUtils.toCollectionName(definition.globalName) +
|
||||
'.schema',
|
||||
schema
|
||||
);
|
||||
|
||||
loadedAttributes();
|
||||
});
|
||||
|
||||
// Add every relationships to the loaded model for Bookshelf.
|
||||
// Basic attributes don't need this-- only relations.
|
||||
_.forEach(definition.attributes, (details, name) => {
|
||||
const buildRelation = ({ definition, model, instance, attribute, name }) => {
|
||||
const verbose =
|
||||
_.get(
|
||||
utilsModels.getNature(details, name, undefined, model.toLowerCase()),
|
||||
utilsModels.getNature(attribute, name, undefined, model.toLowerCase()),
|
||||
'verbose'
|
||||
) || '';
|
||||
|
||||
@ -344,21 +363,15 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
utilsModels.defineAssociations(
|
||||
model.toLowerCase(),
|
||||
definition,
|
||||
details,
|
||||
attribute,
|
||||
name
|
||||
);
|
||||
|
||||
if (_.isEmpty(verbose)) {
|
||||
definition.loadedModel[name].type = utils(instance).convertType(
|
||||
details.type
|
||||
);
|
||||
}
|
||||
|
||||
switch (verbose) {
|
||||
case 'hasOne': {
|
||||
const ref = details.plugin
|
||||
? strapi.plugins[details.plugin].models[details.model].globalId
|
||||
: strapi.models[details.model].globalId;
|
||||
const ref = attribute.plugin
|
||||
? strapi.plugins[attribute.plugin].models[attribute.model].globalId
|
||||
: strapi.models[attribute.model].globalId;
|
||||
|
||||
definition.loadedModel[name] = {
|
||||
type: instance.Schema.Types.ObjectId,
|
||||
@ -370,9 +383,9 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
const FK = _.find(definition.associations, {
|
||||
alias: name,
|
||||
});
|
||||
const ref = details.plugin
|
||||
? strapi.plugins[details.plugin].models[details.collection].globalId
|
||||
: strapi.models[details.collection].globalId;
|
||||
const ref = attribute.plugin
|
||||
? strapi.plugins[attribute.plugin].models[attribute.collection].globalId
|
||||
: strapi.models[attribute.collection].globalId;
|
||||
|
||||
if (FK) {
|
||||
definition.loadedModel[name] = {
|
||||
@ -383,7 +396,7 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
};
|
||||
|
||||
// Set this info to be able to see if this field is a real database's field.
|
||||
details.isVirtual = true;
|
||||
attribute.isVirtual = true;
|
||||
} else {
|
||||
definition.loadedModel[name] = [
|
||||
{
|
||||
@ -398,9 +411,9 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
const FK = _.find(definition.associations, {
|
||||
alias: name,
|
||||
});
|
||||
const ref = details.plugin
|
||||
? strapi.plugins[details.plugin].models[details.model].globalId
|
||||
: strapi.models[details.model].globalId;
|
||||
const ref = attribute.plugin
|
||||
? strapi.plugins[attribute.plugin].models[attribute.model].globalId
|
||||
: strapi.models[attribute.model].globalId;
|
||||
|
||||
if (
|
||||
FK &&
|
||||
@ -417,7 +430,7 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
};
|
||||
|
||||
// Set this info to be able to see if this field is a real database's field.
|
||||
details.isVirtual = true;
|
||||
attribute.isVirtual = true;
|
||||
} else {
|
||||
definition.loadedModel[name] = {
|
||||
type: instance.Schema.Types.ObjectId,
|
||||
@ -431,12 +444,12 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
const FK = _.find(definition.associations, {
|
||||
alias: name,
|
||||
});
|
||||
const ref = details.plugin
|
||||
? strapi.plugins[details.plugin].models[details.collection].globalId
|
||||
: strapi.models[details.collection].globalId;
|
||||
const ref = attribute.plugin
|
||||
? strapi.plugins[attribute.plugin].models[attribute.collection].globalId
|
||||
: strapi.models[attribute.collection].globalId;
|
||||
|
||||
// One-side of the relationship has to be a virtual field to be bidirectional.
|
||||
if ((FK && _.isUndefined(FK.via)) || details.dominant !== true) {
|
||||
if ((FK && _.isUndefined(FK.via)) || attribute.dominant !== true) {
|
||||
definition.loadedModel[name] = {
|
||||
type: 'virtual',
|
||||
ref,
|
||||
@ -444,7 +457,7 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
};
|
||||
|
||||
// Set this info to be able to see if this field is a real database's field.
|
||||
details.isVirtual = true;
|
||||
attribute.isVirtual = true;
|
||||
} else {
|
||||
definition.loadedModel[name] = [
|
||||
{
|
||||
@ -459,9 +472,9 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
const FK = _.find(definition.associations, {
|
||||
alias: name,
|
||||
});
|
||||
const ref = details.plugin
|
||||
? strapi.plugins[details.plugin].models[details.model].globalId
|
||||
: strapi.models[details.model].globalId;
|
||||
const ref = attribute.plugin
|
||||
? strapi.plugins[attribute.plugin].models[attribute.model].globalId
|
||||
: strapi.models[attribute.model].globalId;
|
||||
|
||||
definition.loadedModel[name] = {
|
||||
type: 'virtual',
|
||||
@ -471,16 +484,16 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
};
|
||||
|
||||
// Set this info to be able to see if this field is a real database's field.
|
||||
details.isVirtual = true;
|
||||
attribute.isVirtual = true;
|
||||
break;
|
||||
}
|
||||
case 'morphMany': {
|
||||
const FK = _.find(definition.associations, {
|
||||
alias: name,
|
||||
});
|
||||
const ref = details.plugin
|
||||
? strapi.plugins[details.plugin].models[details.collection].globalId
|
||||
: strapi.models[details.collection].globalId;
|
||||
const ref = attribute.plugin
|
||||
? strapi.plugins[attribute.plugin].models[attribute.collection].globalId
|
||||
: strapi.models[attribute.collection].globalId;
|
||||
|
||||
definition.loadedModel[name] = {
|
||||
type: 'virtual',
|
||||
@ -489,13 +502,13 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
};
|
||||
|
||||
// Set this info to be able to see if this field is a real database's field.
|
||||
details.isVirtual = true;
|
||||
attribute.isVirtual = true;
|
||||
break;
|
||||
}
|
||||
case 'belongsToMorph': {
|
||||
definition.loadedModel[name] = {
|
||||
kind: String,
|
||||
[details.filter]: String,
|
||||
[attribute.filter]: String,
|
||||
ref: {
|
||||
type: instance.Schema.Types.ObjectId,
|
||||
refPath: `${name}.kind`,
|
||||
@ -507,7 +520,7 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
definition.loadedModel[name] = [
|
||||
{
|
||||
kind: String,
|
||||
[details.filter]: String,
|
||||
[attribute.filter]: String,
|
||||
ref: {
|
||||
type: instance.Schema.Types.ObjectId,
|
||||
refPath: `${name}.kind`,
|
||||
@ -519,8 +532,4 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -8,8 +8,14 @@ const Mongoose = require('mongoose');
|
||||
*/
|
||||
|
||||
module.exports = (mongoose = Mongoose) => {
|
||||
mongoose.Schema.Types.Decimal = require('mongoose-float').loadType(mongoose, 2);
|
||||
mongoose.Schema.Types.Float = require('mongoose-float').loadType(mongoose, 20);
|
||||
mongoose.Schema.Types.Decimal = require('mongoose-float').loadType(
|
||||
mongoose,
|
||||
2
|
||||
);
|
||||
mongoose.Schema.Types.Float = require('mongoose-float').loadType(
|
||||
mongoose,
|
||||
20
|
||||
);
|
||||
|
||||
/**
|
||||
* Convert MongoDB ID to the stringify version as GraphQL throws an error if not.
|
||||
@ -20,8 +26,7 @@ module.exports = (mongoose = Mongoose) => {
|
||||
return this.toString();
|
||||
};
|
||||
|
||||
const utils = {
|
||||
convertType: mongooseType => {
|
||||
const convertType = mongooseType => {
|
||||
switch (mongooseType.toLowerCase()) {
|
||||
case 'array':
|
||||
return Array;
|
||||
@ -52,16 +57,11 @@ module.exports = (mongoose = Mongoose) => {
|
||||
case 'text':
|
||||
return 'String';
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
valueToId: value => {
|
||||
if (utils.isMongoId(value)) {
|
||||
return mongoose.Types.ObjectId(value);
|
||||
}
|
||||
};
|
||||
|
||||
return value;
|
||||
},
|
||||
isMongoId: value => {
|
||||
const isMongoId = value => {
|
||||
if (value instanceof mongoose.Types.ObjectId) {
|
||||
return true;
|
||||
}
|
||||
@ -74,8 +74,19 @@ module.exports = (mongoose = Mongoose) => {
|
||||
// it returns for instance true for any integer value
|
||||
const hexadecimal = /^[0-9A-F]+$/i;
|
||||
return hexadecimal.test(value) && value.length === 24;
|
||||
},
|
||||
};
|
||||
|
||||
return utils;
|
||||
const valueToId = value => {
|
||||
if (isMongoId(value)) {
|
||||
return mongoose.Types.ObjectId(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
return {
|
||||
convertType,
|
||||
valueToId,
|
||||
isMongoId,
|
||||
};
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user