mirror of
https://github.com/vale981/grapher
synced 2025-03-05 09:31:42 -05:00
Merge pull request #302 from cult-of-coders/fix/many-uniqueness
Removed exception for uniqueness on many field
This commit is contained in:
commit
24a140ae08
1 changed files with 91 additions and 55 deletions
|
@ -2,11 +2,11 @@ import LinkMany from './linkTypes/linkMany.js';
|
|||
import LinkManyMeta from './linkTypes/linkManyMeta.js';
|
||||
import LinkOne from './linkTypes/linkOne.js';
|
||||
import LinkOneMeta from './linkTypes/linkOneMeta.js';
|
||||
import {LinkConfigSchema, LinkConfigDefaults} from './config.schema.js';
|
||||
import { LinkConfigSchema, LinkConfigDefaults } from './config.schema.js';
|
||||
import smartArguments from './linkTypes/lib/smartArguments';
|
||||
import dot from 'dot-object';
|
||||
import {check} from 'meteor/check';
|
||||
import {_} from 'meteor/underscore';
|
||||
import { check } from 'meteor/check';
|
||||
import { _ } from 'meteor/underscore';
|
||||
|
||||
export default class Linker {
|
||||
/**
|
||||
|
@ -118,8 +118,9 @@ export default class Linker {
|
|||
*/
|
||||
isOneResult() {
|
||||
return (
|
||||
(this.isVirtual() && this.linkConfig.relatedLinker.linkConfig.unique)
|
||||
|| (!this.isVirtual() && this.isSingle())
|
||||
(this.isVirtual() &&
|
||||
this.linkConfig.relatedLinker.linkConfig.unique) ||
|
||||
(!this.isVirtual() && this.isSingle())
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -141,15 +142,23 @@ export default class Linker {
|
|||
*/
|
||||
_validateAndClean() {
|
||||
if (!this.linkConfig.collection) {
|
||||
throw new Meteor.Error('invalid-config', `For the link ${this.linkName} you did not provide a collection.`)
|
||||
throw new Meteor.Error(
|
||||
'invalid-config',
|
||||
`For the link ${
|
||||
this.linkName
|
||||
} you did not provide a collection.`
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof(this.linkConfig.collection) === 'string') {
|
||||
if (typeof this.linkConfig.collection === 'string') {
|
||||
const collectionName = this.linkConfig.collection;
|
||||
this.linkConfig.collection = Mongo.Collection.get(collectionName);
|
||||
|
||||
if (!this.linkConfig.collection) {
|
||||
throw new Meteor.Error('invalid-collection', `Could not find a collection with the name: ${collectionName}`);
|
||||
throw new Meteor.Error(
|
||||
'invalid-collection',
|
||||
`Could not find a collection with the name: ${collectionName}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +173,12 @@ export default class Linker {
|
|||
this.linkConfig.field = this._generateFieldName();
|
||||
} else {
|
||||
if (this.linkConfig.field == this.linkName) {
|
||||
throw new Meteor.Error('invalid-config', `For the link ${this.linkName} you must not use the same name for the field, otherwise it will cause conflicts when fetching data`);
|
||||
throw new Meteor.Error(
|
||||
'invalid-config',
|
||||
`For the link ${
|
||||
this.linkName
|
||||
} you must not use the same name for the field, otherwise it will cause conflicts when fetching data`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +191,7 @@ export default class Linker {
|
|||
* @private
|
||||
*/
|
||||
_prepareVirtual() {
|
||||
const {collection, inversedBy} = this.linkConfig;
|
||||
const { collection, inversedBy } = this.linkConfig;
|
||||
let linker = collection.getLinker(inversedBy);
|
||||
|
||||
if (!linker) {
|
||||
|
@ -186,11 +200,17 @@ export default class Linker {
|
|||
Meteor.startup(() => {
|
||||
linker = collection.getLinker(inversedBy);
|
||||
if (!linker) {
|
||||
throw new Meteor.Error(`You tried setting up an inversed link in "${this.mainCollection._name}" pointing to collection: "${collection._name}" link: "${inversedBy}", but no such link was found. Maybe a typo ?`)
|
||||
throw new Meteor.Error(
|
||||
`You tried setting up an inversed link in "${
|
||||
this.mainCollection._name
|
||||
}" pointing to collection: "${
|
||||
collection._name
|
||||
}" link: "${inversedBy}", but no such link was found. Maybe a typo ?`
|
||||
);
|
||||
} else {
|
||||
this._setupVirtualConfig(linker);
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
this._setupVirtualConfig(linker);
|
||||
}
|
||||
|
@ -204,12 +224,14 @@ export default class Linker {
|
|||
const virtualLinkConfig = linker.linkConfig;
|
||||
|
||||
if (!virtualLinkConfig) {
|
||||
throw new Meteor.Error(`There is no link-config for the related collection on ${inversedBy}. Make sure you added the direct links before specifying virtual ones.`)
|
||||
throw new Meteor.Error(
|
||||
`There is no link-config for the related collection on ${inversedBy}. Make sure you added the direct links before specifying virtual ones.`
|
||||
);
|
||||
}
|
||||
|
||||
_.extend(this.linkConfig, {
|
||||
metadata: virtualLinkConfig.metadata,
|
||||
relatedLinker: linker
|
||||
relatedLinker: linker,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -229,7 +251,10 @@ export default class Linker {
|
|||
return LinkOne;
|
||||
}
|
||||
|
||||
throw new Meteor.Error('invalid-strategy', `${this.strategy} is not a valid strategy`);
|
||||
throw new Meteor.Error(
|
||||
'invalid-strategy',
|
||||
`${this.strategy} is not a valid strategy`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -237,7 +262,10 @@ export default class Linker {
|
|||
* @private
|
||||
*/
|
||||
_generateFieldName() {
|
||||
let cleanedCollectionName = this.linkConfig.collection._name.replace(/\./g, '_');
|
||||
let cleanedCollectionName = this.linkConfig.collection._name.replace(
|
||||
/\./g,
|
||||
'_'
|
||||
);
|
||||
let defaultFieldPrefix = this.linkName + '_' + cleanedCollectionName;
|
||||
|
||||
switch (this.strategy) {
|
||||
|
@ -260,14 +288,20 @@ export default class Linker {
|
|||
this.mainCollection.after.remove((userId, doc) => {
|
||||
// this problem may occur when you do a .remove() before Meteor.startup()
|
||||
if (!this.linkConfig.relatedLinker) {
|
||||
console.warn(`There was an error finding the link for removal for collection: "${this.mainCollection._name}" with link: "${this.linkName}". This may occur when you do a .remove() before Meteor.startup()`);
|
||||
console.warn(
|
||||
`There was an error finding the link for removal for collection: "${
|
||||
this.mainCollection._name
|
||||
}" with link: "${
|
||||
this.linkName
|
||||
}". This may occur when you do a .remove() before Meteor.startup()`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let accessor = this.createLink(doc);
|
||||
|
||||
_.each(accessor.fetch(), linkedObj => {
|
||||
const {relatedLinker} = this.linkConfig;
|
||||
const { relatedLinker } = this.linkConfig;
|
||||
// We do this check, to avoid self-referencing hell when defining virtual links
|
||||
// Virtual links if not found "compile-time", we will try again to reprocess them on Meteor.startup
|
||||
// if a removal happens before Meteor.startup this may fail
|
||||
|
@ -281,7 +315,7 @@ export default class Linker {
|
|||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
_initIndex() {
|
||||
|
@ -293,32 +327,31 @@ export default class Linker {
|
|||
|
||||
if (this.linkConfig.index) {
|
||||
if (this.isVirtual()) {
|
||||
throw new Meteor.Error('You cannot set index on an inversed link.');
|
||||
throw new Meteor.Error(
|
||||
'You cannot set index on an inversed link.'
|
||||
);
|
||||
}
|
||||
|
||||
let options;
|
||||
if (this.linkConfig.unique) {
|
||||
if (this.isMany()) {
|
||||
throw new Meteor.Error('You cannot set unique property on a multi field.');
|
||||
}
|
||||
|
||||
options = {unique: true}
|
||||
options = { unique: true };
|
||||
}
|
||||
|
||||
this.mainCollection._ensureIndex({[field]: 1}, options);
|
||||
this.mainCollection._ensureIndex({ [field]: 1 }, options);
|
||||
} else {
|
||||
if (this.linkConfig.unique) {
|
||||
if (this.isVirtual()) {
|
||||
throw new Meteor.Error('You cannot set unique property on an inversed link.');
|
||||
throw new Meteor.Error(
|
||||
'You cannot set unique property on an inversed link.'
|
||||
);
|
||||
}
|
||||
|
||||
if (this.isMany()) {
|
||||
throw new Meteor.Error('You cannot set unique property on a multi field.');
|
||||
}
|
||||
|
||||
this.mainCollection._ensureIndex({
|
||||
[field]: 1
|
||||
}, {unique: true})
|
||||
this.mainCollection._ensureIndex(
|
||||
{
|
||||
[field]: 1,
|
||||
},
|
||||
{ unique: true }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -333,19 +366,22 @@ export default class Linker {
|
|||
this.mainCollection.after.remove((userId, doc) => {
|
||||
this.getLinkedCollection().remove({
|
||||
_id: {
|
||||
$in: smartArguments.getIds(doc[this.linkStorageField])
|
||||
}
|
||||
})
|
||||
})
|
||||
$in: smartArguments.getIds(doc[this.linkStorageField]),
|
||||
},
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.mainCollection.after.remove((userId, doc) => {
|
||||
const linker = this.mainCollection.getLink(doc, this.linkName);
|
||||
const ids = linker.find({}, {fields: {_id: 1}}).fetch().map(item => item._id);
|
||||
const ids = linker
|
||||
.find({}, { fields: { _id: 1 } })
|
||||
.fetch()
|
||||
.map(item => item._id);
|
||||
|
||||
this.getLinkedCollection().remove({
|
||||
_id: {$in: ids}
|
||||
})
|
||||
})
|
||||
_id: { $in: ids },
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,21 +396,25 @@ export default class Linker {
|
|||
|
||||
const packageExists = !!Package['herteby:denormalize'];
|
||||
if (!packageExists) {
|
||||
throw new Meteor.Error('missing-package', `Please add the herteby:denormalize package to your Meteor application in order to make caching work`)
|
||||
throw new Meteor.Error(
|
||||
'missing-package',
|
||||
`Please add the herteby:denormalize package to your Meteor application in order to make caching work`
|
||||
);
|
||||
}
|
||||
|
||||
const {field, body, bypassSchema} = this.linkConfig.denormalize;
|
||||
const { field, body, bypassSchema } = this.linkConfig.denormalize;
|
||||
let cacheConfig;
|
||||
|
||||
let referenceFieldSuffix = '';
|
||||
if (this.isMeta()) {
|
||||
referenceFieldSuffix = (this.isSingle() ? '._id' : ':_id');
|
||||
referenceFieldSuffix = this.isSingle() ? '._id' : ':_id';
|
||||
}
|
||||
|
||||
if (this.isVirtual()) {
|
||||
let inversedLink = this.linkConfig.relatedLinker.linkConfig;
|
||||
|
||||
let type = inversedLink.type == 'many' ? 'many-inverse' : 'inversed';
|
||||
let type =
|
||||
inversedLink.type == 'many' ? 'many-inverse' : 'inversed';
|
||||
|
||||
cacheConfig = {
|
||||
type: type,
|
||||
|
@ -382,7 +422,7 @@ export default class Linker {
|
|||
fields: body,
|
||||
referenceField: inversedLink.field + referenceFieldSuffix,
|
||||
cacheField: field,
|
||||
bypassSchema: !!bypassSchema
|
||||
bypassSchema: !!bypassSchema,
|
||||
};
|
||||
} else {
|
||||
cacheConfig = {
|
||||
|
@ -391,14 +431,14 @@ export default class Linker {
|
|||
fields: body,
|
||||
referenceField: this.linkConfig.field + referenceFieldSuffix,
|
||||
cacheField: field,
|
||||
bypassSchema: !!bypassSchema
|
||||
bypassSchema: !!bypassSchema,
|
||||
};
|
||||
}
|
||||
|
||||
if (this.isVirtual()) {
|
||||
Meteor.startup(() => {
|
||||
this.mainCollection.cache(cacheConfig);
|
||||
})
|
||||
});
|
||||
} else {
|
||||
this.mainCollection.cache(cacheConfig);
|
||||
}
|
||||
|
@ -425,12 +465,8 @@ export default class Linker {
|
|||
const cacheBody = this.linkConfig.denormalize.body;
|
||||
|
||||
const cacheBodyFields = _.keys(dot.dot(cacheBody));
|
||||
const bodyFields = _.keys(
|
||||
dot.dot(
|
||||
_.omit(body, '_id')
|
||||
)
|
||||
);
|
||||
const bodyFields = _.keys(dot.dot(_.omit(body, '_id')));
|
||||
|
||||
return _.difference(bodyFields, cacheBodyFields).length === 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue