From 184acc74c68403d1182dbd9f199520e58562dc2f Mon Sep 17 00:00:00 2001 From: Fred Marecesche Date: Mon, 9 Sep 2019 08:40:19 +0100 Subject: [PATCH] Prevent TypeError if many-to-one reference exists In the case of many-to-one references, the foreign reference is a string rather than an array. In this case, trying to create the reverse linkage results in a TypeError from attemtping to `push()` to a string. This checks the `push()` method can indeed be used to prevent such TypeError(s). --- .../__tests__/__snapshots__/normalize.js.snap | 293 ++++++++++++++++ .../src/__tests__/data.json | 316 ++++++++++++++++++ .../gatsby-source-contentful/src/normalize.js | 11 +- 3 files changed, 617 insertions(+), 3 deletions(-) diff --git a/packages/gatsby-source-contentful/src/__tests__/__snapshots__/normalize.js.snap b/packages/gatsby-source-contentful/src/__tests__/__snapshots__/normalize.js.snap index b192da000c1a9..34ae2d5ca71a1 100644 --- a/packages/gatsby-source-contentful/src/__tests__/__snapshots__/normalize.js.snap +++ b/packages/gatsby-source-contentful/src/__tests__/__snapshots__/normalize.js.snap @@ -1913,6 +1913,153 @@ Our Lemnos products are made carefully by our craftsmen finely honed skillful te }, }, ], + Array [ + Object { + "fields": Object { + "author": Object { + "en-US": Object { + "sys": Object { + "id": "qYfB1lzHTNpofY3Oqvjpk", + "linkType": "Entry", + "type": "Link", + }, + }, + }, + "slug": Object { + "en-US": "post-one", + }, + "title": Object { + "en-US": "Post one", + }, + }, + "sys": Object { + "contentType": Object { + "sys": Object { + "id": "blogPost", + "linkType": "ContentType", + "type": "Link", + }, + }, + "contentful_id": "5U1Lm7y197ZCNUI9USWPUV", + "createdAt": "2019-09-09T06:54:07.673Z", + "createdBy": Object { + "sys": Object { + "id": "2cRG5PXyp1roAoTOywZTW6", + "linkType": "User", + "type": "Link", + }, + }, + "environment": Object { + "sys": Object { + "id": "master", + "linkType": "Environment", + "type": "Link", + }, + }, + "firstPublishedAt": "2019-09-09T06:54:28.959Z", + "id": "c5U1Lm7y197ZCNUI9USWPUV", + "publishedAt": "2019-09-09T06:58:04.316Z", + "publishedBy": Object { + "sys": Object { + "id": "2cRG5PXyp1roAoTOywZTW6", + "linkType": "User", + "type": "Link", + }, + }, + "publishedCounter": 3, + "publishedVersion": 11, + "space": Object { + "sys": Object { + "id": "rocybtov1ozk", + "linkType": "Space", + "type": "Link", + }, + }, + "type": "Entry", + "updatedAt": "2019-09-09T06:58:04.316Z", + "updatedBy": Object { + "sys": Object { + "id": "2cRG5PXyp1roAoTOywZTW6", + "linkType": "User", + "type": "Link", + }, + }, + "version": 12, + }, + }, + ], + Array [ + Object { + "fields": Object { + "favouritePost": Object { + "en-US": Object { + "sys": Object { + "id": "c5U1Lm7y197ZCNUI9USWPUV", + "linkType": "Entry", + "type": "Link", + }, + }, + }, + "name": Object { + "en-US": "Fred", + }, + }, + "sys": Object { + "contentType": Object { + "sys": Object { + "id": "author", + "linkType": "ContentType", + "type": "Link", + }, + }, + "contentful_id": "qYfB1lzHTNpofY3Oqvjpk", + "createdAt": "2019-09-09T06:54:16.287Z", + "createdBy": Object { + "sys": Object { + "id": "2cRG5PXyp1roAoTOywZTW6", + "linkType": "User", + "type": "Link", + }, + }, + "environment": Object { + "sys": Object { + "id": "master", + "linkType": "Environment", + "type": "Link", + }, + }, + "firstPublishedAt": "2019-09-09T06:54:22.644Z", + "id": "qYfB1lzHTNpofY3Oqvjpk", + "publishedAt": "2019-09-09T06:54:38.816Z", + "publishedBy": Object { + "sys": Object { + "id": "2cRG5PXyp1roAoTOywZTW6", + "linkType": "User", + "type": "Link", + }, + }, + "publishedCounter": 2, + "publishedVersion": 6, + "space": Object { + "sys": Object { + "id": "rocybtov1ozk", + "linkType": "Space", + "type": "Link", + }, + }, + "type": "Entry", + "updatedAt": "2019-09-09T06:54:38.816Z", + "updatedBy": Object { + "sys": Object { + "id": "2cRG5PXyp1roAoTOywZTW6", + "linkType": "User", + "type": "Link", + }, + }, + "version": 7, + }, + }, + ], ] `; @@ -1972,6 +2119,12 @@ Object { "name": "brand___NODE", }, ], + "c5U1Lm7y197ZCNUI9USWPUV": Array [ + Object { + "id": "qYfB1lzHTNpofY3Oqvjpk", + "name": "author___NODE", + }, + ], "c651CQ8rLoIYCeY6G0QG22q": Array [ Object { "id": "c3DVqIYj4dOwwcKu6sgqOgg", @@ -2008,6 +2161,12 @@ Object { "name": "product___NODE", }, ], + "qYfB1lzHTNpofY3Oqvjpk": Array [ + Object { + "id": "c5U1Lm7y197ZCNUI9USWPUV", + "name": "blog post___NODE", + }, + ], "wtrHxeu3zEoEce2MokCSi": Array [ Object { "id": "c5KsDBWseXY6QegucYAoacS", @@ -2030,6 +2189,8 @@ Set { "c4BqrajvA8E6qwgkieoqmqO", "c71mfnH4QKsSsQmgoaQuq6O", "c4L2GhTsJtCseMYM8Wia64i", + "c5U1Lm7y197ZCNUI9USWPUV", + "qYfB1lzHTNpofY3Oqvjpk", "c3wtvPBbBjiMKqKKga8I2Cu", "KTRF62Q4gg60q6WCsWKw8", "Xc0ny7GWsMEMCeASWO2um", @@ -4297,5 +4458,137 @@ Unsere Lemnos Produkte werden sorgfältig von unseren Handwerkern fein geschliff "parent": "uuid-from-gatsby", }, ], + Array [ + Object { + "children": Array [], + "description": "", + "displayField": "title", + "id": "uuid-from-gatsby", + "internal": Object { + "contentDigest": "6ea09658e67ecfc838a195ab96bd8ef9", + "type": "ContentfulContentType", + }, + "name": "Blog Post", + "parent": null, + }, + ], + Array [ + Object { + "author___NODE": "uuid-from-gatsby", + "children": Array [], + "contentful_id": "c5U1Lm7y197ZCNUI9USWPUV", + "createdAt": "2019-09-09T06:54:07.673Z", + "id": "uuid-from-gatsby", + "internal": Object { + "contentDigest": "972a70e0665af76f7bc8e053fa803826", + "type": "ContentfulBlogPost", + }, + "node_locale": "en-US", + "parent": "Blog Post", + "slug": "post-one", + "title": "Post one", + "updatedAt": "2019-09-09T06:58:04.316Z", + }, + ], + Array [ + Object { + "children": Array [], + "description": "", + "displayField": "title", + "id": "uuid-from-gatsby", + "internal": Object { + "contentDigest": "6ea09658e67ecfc838a195ab96bd8ef9", + "type": "ContentfulContentType", + }, + "name": "Blog Post", + "parent": null, + }, + ], + Array [ + Object { + "author___NODE": "uuid-from-gatsby", + "children": Array [], + "contentful_id": "c5U1Lm7y197ZCNUI9USWPUV", + "createdAt": "2019-09-09T06:54:07.673Z", + "id": "uuid-from-gatsby", + "internal": Object { + "contentDigest": "63156d744a2ae97f222299a400750d46", + "type": "ContentfulBlogPost", + }, + "node_locale": "de", + "parent": "Blog Post", + "slug": "post-one", + "title": "Post one", + "updatedAt": "2019-09-09T06:58:04.316Z", + }, + ], + Array [ + Object { + "children": Array [], + "description": "", + "displayField": "name", + "id": "uuid-from-gatsby", + "internal": Object { + "contentDigest": "feb97892424b0df5c4d78a7a36e6bb6c", + "type": "ContentfulContentType", + }, + "name": "Author", + "parent": null, + }, + ], + Array [ + Object { + "blog post___NODE": Array [ + "uuid-from-gatsby", + ], + "children": Array [], + "contentful_id": "qYfB1lzHTNpofY3Oqvjpk", + "createdAt": "2019-09-09T06:54:16.287Z", + "favouritePost___NODE": "uuid-from-gatsby", + "id": "uuid-from-gatsby", + "internal": Object { + "contentDigest": "55478da16d88e82dd0a94180aa966976", + "type": "ContentfulAuthor", + }, + "name": "Fred", + "node_locale": "en-US", + "parent": "Author", + "updatedAt": "2019-09-09T06:54:38.816Z", + }, + ], + Array [ + Object { + "children": Array [], + "description": "", + "displayField": "name", + "id": "uuid-from-gatsby", + "internal": Object { + "contentDigest": "feb97892424b0df5c4d78a7a36e6bb6c", + "type": "ContentfulContentType", + }, + "name": "Author", + "parent": null, + }, + ], + Array [ + Object { + "blog post___NODE": Array [ + "uuid-from-gatsby", + ], + "children": Array [], + "contentful_id": "qYfB1lzHTNpofY3Oqvjpk", + "createdAt": "2019-09-09T06:54:16.287Z", + "favouritePost___NODE": "uuid-from-gatsby", + "id": "uuid-from-gatsby", + "internal": Object { + "contentDigest": "60afe7cfb871c52d3e1c8b856f00be5b", + "type": "ContentfulAuthor", + }, + "name": "Fred", + "node_locale": "de", + "parent": "Author", + "updatedAt": "2019-09-09T06:54:38.816Z", + }, + ], ] `; diff --git a/packages/gatsby-source-contentful/src/__tests__/data.json b/packages/gatsby-source-contentful/src/__tests__/data.json index b882d366938b2..d20414affd31b 100644 --- a/packages/gatsby-source-contentful/src/__tests__/data.json +++ b/packages/gatsby-source-contentful/src/__tests__/data.json @@ -1815,6 +1815,149 @@ "en-US": "Shop for toys, games, educational aids" } } + }, + { + "sys": { + "space": { + "sys": { + "type": "Link", + "linkType": "Space", + "id": "rocybtov1ozk" + } + }, + "id": "c5U1Lm7y197ZCNUI9USWPUV", + "type": "Entry", + "createdAt": "2019-09-09T06:54:07.673Z", + "updatedAt": "2019-09-09T06:58:04.316Z", + "environment": { + "sys": { + "id": "master", + "type": "Link", + "linkType": "Environment" + } + }, + "publishedVersion": 11, + "publishedAt": "2019-09-09T06:58:04.316Z", + "firstPublishedAt": "2019-09-09T06:54:28.959Z", + "createdBy": { + "sys": { + "type": "Link", + "linkType": "User", + "id": "2cRG5PXyp1roAoTOywZTW6" + } + }, + "updatedBy": { + "sys": { + "type": "Link", + "linkType": "User", + "id": "2cRG5PXyp1roAoTOywZTW6" + } + }, + "publishedCounter": 3, + "version": 12, + "publishedBy": { + "sys": { + "type": "Link", + "linkType": "User", + "id": "2cRG5PXyp1roAoTOywZTW6" + } + }, + "contentType": { + "sys": { + "type": "Link", + "linkType": "ContentType", + "id": "blogPost" + } + }, + "contentful_id": "5U1Lm7y197ZCNUI9USWPUV" + }, + "fields": { + "title": { + "en-US": "Post one" + }, + "slug": { + "en-US": "post-one" + }, + "author": { + "en-US": { + "sys": { + "type": "Link", + "linkType": "Entry", + "id": "qYfB1lzHTNpofY3Oqvjpk" + } + } + } + } + }, + { + "sys": { + "space": { + "sys": { + "type": "Link", + "linkType": "Space", + "id": "rocybtov1ozk" + } + }, + "id": "qYfB1lzHTNpofY3Oqvjpk", + "type": "Entry", + "createdAt": "2019-09-09T06:54:16.287Z", + "updatedAt": "2019-09-09T06:54:38.816Z", + "environment": { + "sys": { + "id": "master", + "type": "Link", + "linkType": "Environment" + } + }, + "publishedVersion": 6, + "publishedAt": "2019-09-09T06:54:38.816Z", + "firstPublishedAt": "2019-09-09T06:54:22.644Z", + "createdBy": { + "sys": { + "type": "Link", + "linkType": "User", + "id": "2cRG5PXyp1roAoTOywZTW6" + } + }, + "updatedBy": { + "sys": { + "type": "Link", + "linkType": "User", + "id": "2cRG5PXyp1roAoTOywZTW6" + } + }, + "publishedCounter": 2, + "version": 7, + "publishedBy": { + "sys": { + "type": "Link", + "linkType": "User", + "id": "2cRG5PXyp1roAoTOywZTW6" + } + }, + "contentType": { + "sys": { + "type": "Link", + "linkType": "ContentType", + "id": "author" + } + }, + "contentful_id": "qYfB1lzHTNpofY3Oqvjpk" + }, + "fields": { + "name": { + "en-US": "Fred" + }, + "favouritePost": { + "en-US": { + "sys": { + "type": "Link", + "linkType": "Entry", + "id": "c5U1Lm7y197ZCNUI9USWPUV" + } + } + } + } } ], "assets": [ @@ -2806,6 +2949,179 @@ "omitted": false } ] + }, + { + "sys": { + "space": { + "sys": { + "type": "Link", + "linkType": "Space", + "id": "rocybtov1ozk" + } + }, + "id": "blogPost", + "type": "ContentType", + "createdAt": "2019-09-05T20:44:05.442Z", + "updatedAt": "2019-09-09T06:53:15.783Z", + "environment": { + "sys": { + "id": "master", + "type": "Link", + "linkType": "Environment" + } + }, + "publishedVersion": 12, + "publishedAt": "2019-09-09T06:53:15.783Z", + "firstPublishedAt": "2019-09-05T20:44:49.375Z", + "createdBy": { + "sys": { + "type": "Link", + "linkType": "User", + "id": "2cRG5PXyp1roAoTOywZTW6" + } + }, + "updatedBy": { + "sys": { + "type": "Link", + "linkType": "User", + "id": "2cRG5PXyp1roAoTOywZTW6" + } + }, + "publishedCounter": 6, + "version": 13, + "publishedBy": { + "sys": { + "type": "Link", + "linkType": "User", + "id": "2cRG5PXyp1roAoTOywZTW6" + } + } + }, + "displayField": "title", + "name": "Blog Post", + "description": "", + "fields": [ + { + "id": "title", + "name": "Title", + "type": "Symbol", + "localized": false, + "required": true, + "validations": [ + ], + "disabled": false, + "omitted": false + }, + { + "id": "slug", + "name": "Slug", + "type": "Symbol", + "localized": false, + "required": false, + "validations": [ + ], + "disabled": false, + "omitted": false + }, + { + "id": "author", + "name": "Author", + "type": "Link", + "localized": false, + "required": false, + "validations": [ + { + "linkContentType": [ + "author" + ] + } + ], + "disabled": false, + "omitted": false, + "linkType": "Entry" + } + ] + }, + { + "sys": { + "space": { + "sys": { + "type": "Link", + "linkType": "Space", + "id": "rocybtov1ozk" + } + }, + "id": "author", + "type": "ContentType", + "createdAt": "2019-09-09T06:52:36.276Z", + "updatedAt": "2019-09-09T06:52:53.557Z", + "environment": { + "sys": { + "id": "master", + "type": "Link", + "linkType": "Environment" + } + }, + "publishedVersion": 2, + "publishedAt": "2019-09-09T06:52:53.557Z", + "firstPublishedAt": "2019-09-09T06:52:53.557Z", + "createdBy": { + "sys": { + "type": "Link", + "linkType": "User", + "id": "2cRG5PXyp1roAoTOywZTW6" + } + }, + "updatedBy": { + "sys": { + "type": "Link", + "linkType": "User", + "id": "2cRG5PXyp1roAoTOywZTW6" + } + }, + "publishedCounter": 1, + "version": 3, + "publishedBy": { + "sys": { + "type": "Link", + "linkType": "User", + "id": "2cRG5PXyp1roAoTOywZTW6" + } + } + }, + "displayField": "name", + "name": "Author", + "description": "", + "fields": [ + { + "id": "name", + "name": "Name", + "type": "Symbol", + "localized": false, + "required": true, + "validations": [ + ], + "disabled": false, + "omitted": false + }, + { + "id": "favouritePost", + "name": "favouritePost", + "type": "Link", + "localized": false, + "required": false, + "validations": [ + { + "linkContentType": [ + "blogPost" + ] + } + ], + "disabled": false, + "omitted": false, + "linkType": "Entry" + } + ] } ], "defaultLocale": "en-US", diff --git a/packages/gatsby-source-contentful/src/normalize.js b/packages/gatsby-source-contentful/src/normalize.js index 58160e3201d24..fd5a352aa8a6b 100644 --- a/packages/gatsby-source-contentful/src/normalize.js +++ b/packages/gatsby-source-contentful/src/normalize.js @@ -342,9 +342,14 @@ exports.createContentTypeNodes = ({ foreignReferences.forEach(foreignReference => { const existingReference = entryItemFields[foreignReference.name] if (existingReference) { - entryItemFields[foreignReference.name].push( - mId(foreignReference.id) - ) + // If the existing reference is a string, we're dealing with a + // many-to-one reference which has already been recorded, so we can + // skip it. However, if it is an array, add it: + if (Array.isArray(existingReference)) { + entryItemFields[foreignReference.name].push( + mId(foreignReference.id) + ) + } } else { // If there is one foreign reference, there can be many. // Best to be safe and put it in an array to start with.