diff --git a/.changeset/swift-lobsters-mate.md b/.changeset/swift-lobsters-mate.md new file mode 100644 index 00000000000..752fa93ad48 --- /dev/null +++ b/.changeset/swift-lobsters-mate.md @@ -0,0 +1,5 @@ +--- +'@keystonejs/keystone': patch +--- + +Added a check for invalid relationship configurations. diff --git a/.changeset/unlucky-swans-deliver.md b/.changeset/unlucky-swans-deliver.md new file mode 100644 index 00000000000..c1286c9e6d3 --- /dev/null +++ b/.changeset/unlucky-swans-deliver.md @@ -0,0 +1,5 @@ +--- +'@keystonejs/fields': patch +--- + +Updated internal relationship configurations of `Content` fields to be self-consistent. diff --git a/packages/fields/src/types/CloudinaryImage/ImageBlock.js b/packages/fields/src/types/CloudinaryImage/ImageBlock.js index 7043548c177..073e621ff1c 100644 --- a/packages/fields/src/types/CloudinaryImage/ImageBlock.js +++ b/packages/fields/src/types/CloudinaryImage/ImageBlock.js @@ -83,7 +83,7 @@ export class ImageBlock extends Block { return { [this.path]: { type: RelationshipWrapper, - ref: this.auxList.key, + ref: `${this.auxList.key}.from`, many: true, schemaDoc: 'Images which have been added to the Content field', }, diff --git a/packages/fields/src/types/OEmbed/OEmbedBlock.js b/packages/fields/src/types/OEmbed/OEmbedBlock.js index d1c9172f087..3459982a7aa 100644 --- a/packages/fields/src/types/OEmbed/OEmbedBlock.js +++ b/packages/fields/src/types/OEmbed/OEmbedBlock.js @@ -69,7 +69,7 @@ export class OEmbedBlock extends Block { return { [this.path]: { type: RelationshipWrapper, - ref: this.auxList.key, + ref: `${this.auxList.key}.from`, many: true, schemaDoc: 'Embeds which have been added to the Content field', }, diff --git a/packages/fields/src/types/Unsplash/UnsplashBlock.js b/packages/fields/src/types/Unsplash/UnsplashBlock.js index ce453518e2a..6bd7803c614 100644 --- a/packages/fields/src/types/Unsplash/UnsplashBlock.js +++ b/packages/fields/src/types/Unsplash/UnsplashBlock.js @@ -81,7 +81,7 @@ export class UnsplashBlock extends Block { return { [this.path]: { type: RelationshipWrapper, - ref: this.auxList.key, + ref: `${this.auxList.key}.from`, many: true, schemaDoc: 'Unsplash Images which have been added to the Content field', }, diff --git a/packages/keystone/lib/Keystone/index.js b/packages/keystone/lib/Keystone/index.js index 63f221ddb4a..0543943cdd2 100644 --- a/packages/keystone/lib/Keystone/index.js +++ b/packages/keystone/lib/Keystone/index.js @@ -313,6 +313,45 @@ module.exports = class Keystone { this._extendedMutations = this._extendedMutations.concat(mutations.map(_parseAccess)); } + _consolidateRelationships() { + const rels = {}; + const otherSides = {}; + this.listsArray.forEach(list => { + list.fields + .filter(f => f.isRelationship) + .forEach(f => { + const myRef = `${f.listKey}.${f.path}`; + if (otherSides[myRef]) { + // I'm already there, go and update rels[otherSides[myRef]] with my info + rels[otherSides[myRef]].right = f; + + // Make sure I'm actually referencing the thing on the left + const { left } = rels[otherSides[myRef]]; + if (f.config.ref !== `${left.listKey}.${left.path}`) { + throw new Error( + `${myRef} refers to ${f.config.ref}. Expected ${left.listKey}.${left.path}` + ); + } + } else { + // Got us a new relationship! + rels[myRef] = { left: f }; + if (f.refFieldPath) { + // Populate otherSides + otherSides[f.config.ref] = myRef; + } + } + }); + }); + // See if anything failed to link up. + const badRel = Object.values(rels).find(({ left, right }) => left.refFieldPath && !right); + if (badRel) { + const { left } = badRel; + throw new Error( + `${left.listKey}.${left.path} refers to a non-existant field, ${left.config.ref}` + ); + } + } + /** * @return Promise */ @@ -684,6 +723,7 @@ module.exports = class Keystone { pinoOptions, cors = { origin: true, credentials: true }, } = {}) { + this._consolidateRelationships(); const middlewares = flattenDeep([ this.appVersion.addVersionToHttpHeaders && ((req, res, next) => {