Skip to content

Commit 9cf4c05

Browse files
authored
fix(gatsby-source-drupal): Ensure all new nodes are created before creating relationships (#33864)
* fix(gatsby-source-drupal): Ensure all new nodes are created before creating relationships * fixes * Add support for webhook bodies as well
1 parent 3644acf commit 9cf4c05

File tree

5 files changed

+214
-0
lines changed

5 files changed

+214
-0
lines changed

packages/gatsby-source-drupal/src/__tests__/fixtures/1593545806.json

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,69 @@
9898
}
9999
}
100100
}
101+
},
102+
{
103+
"jsonapi": {
104+
"version": "1.0",
105+
"meta": {
106+
"links": {
107+
"self": {
108+
"href": "http://jsonapi.org/format/1.0/"
109+
}
110+
}
111+
}
112+
},
113+
"data": {
114+
"type": "node--article",
115+
"id": "article-10",
116+
"attributes": {
117+
"id": 100,
118+
"uuid": "article-10",
119+
"title": "Article #10",
120+
"body": "Aliquam non varius libero, sit amet consequat ex. Aenean porta turpis quis vulputate blandit. Suspendisse in porta erat. Sed sit amet scelerisque turpis, at rutrum mauris. Sed tempor eleifend lobortis. Proin maximus, massa sed dignissim sollicitudin, quam risus mattis justo, sit amet aliquam odio ligula quis urna. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut mollis leo nisi, at interdum urna fermentum ut. Fusce id suscipit neque, eu fermentum lacus. Donec egestas laoreet felis ac luctus. Vestibulum molestie mattis ante, a vulputate nunc ullamcorper at. Ut hendrerit ipsum eget gravida ultricies."
121+
},
122+
"relationships": {
123+
"field_tags": {
124+
"data": [
125+
{
126+
"type": "taxonomy_term--tags",
127+
"id": "tag-10"
128+
}
129+
]
130+
}
131+
}
132+
}
133+
},
134+
{
135+
"jsonapi": {
136+
"version": "1.0",
137+
"meta": {
138+
"links": {
139+
"self": {
140+
"href": "http://jsonapi.org/format/1.0/"
141+
}
142+
}
143+
}
144+
},
145+
"data": {
146+
"type": "taxonomy_term--tags",
147+
"id": "tag-10",
148+
"attributes": {
149+
"id": 110,
150+
"uuid": "tag-10",
151+
"langcode": "en",
152+
"name": "Tag #10",
153+
"description": null,
154+
"weight": 0,
155+
"changed": 1523031646,
156+
"default_langcode": true,
157+
"path": {
158+
"alias": null,
159+
"pid": null,
160+
"langcode": "en"
161+
}
162+
}
163+
}
101164
}
102165
]
103166
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"action": "update",
3+
"data": [
4+
{
5+
"type": "node--article",
6+
"id": "article-10",
7+
"attributes": {
8+
"id": 100,
9+
"uuid": "article-10",
10+
"title": "Article #10",
11+
"body": "Aliquam non varius libero, sit amet consequat ex. Aenean porta turpis quis vulputate blandit. Suspendisse in porta erat. Sed sit amet scelerisque turpis, at rutrum mauris. Sed tempor eleifend lobortis. Proin maximus, massa sed dignissim sollicitudin, quam risus mattis justo, sit amet aliquam odio ligula quis urna. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut mollis leo nisi, at interdum urna fermentum ut. Fusce id suscipit neque, eu fermentum lacus. Donec egestas laoreet felis ac luctus. Vestibulum molestie mattis ante, a vulputate nunc ullamcorper at. Ut hendrerit ipsum eget gravida ultricies."
12+
},
13+
"relationships": {
14+
"field_tags": {
15+
"data": [
16+
{
17+
"type": "taxonomy_term--tags",
18+
"id": "tag-10"
19+
}
20+
]
21+
}
22+
}
23+
},
24+
{
25+
"type": "taxonomy_term--tags",
26+
"id": "tag-10",
27+
"attributes": {
28+
"id": 110,
29+
"uuid": "tag-10",
30+
"langcode": "en",
31+
"name": "Tag #10",
32+
"description": null,
33+
"weight": 0,
34+
"changed": 1523031646,
35+
"default_langcode": true,
36+
"path": {
37+
"alias": null,
38+
"pid": null,
39+
"langcode": "en"
40+
}
41+
}
42+
}
43+
]
44+
}
45+

packages/gatsby-source-drupal/src/__tests__/index.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,26 @@ describe(`gatsby-source-drupal`, () => {
355355
})
356356
})
357357
})
358+
describe(`multiple entities in webhook body`, () => {
359+
let resp
360+
beforeAll(async () => {
361+
const webhookBody = require(`./fixtures/webhook-body-multiple-nodes.json`)
362+
await sourceNodes(
363+
{
364+
...args,
365+
webhookBody,
366+
},
367+
{ baseUrl }
368+
)
369+
})
370+
371+
it(`Relationships`, async () => {
372+
expect(
373+
nodes[createNodeId(`und.article-10`)].relationships.field_tags___NODE
374+
.length
375+
).toBe(1)
376+
})
377+
})
358378

359379
describe(`Insert content`, () => {
360380
it(`Node doesn't exist before webhook`, () => {
@@ -567,6 +587,10 @@ describe(`gatsby-source-drupal`, () => {
567587
nodes[createNodeId(`und.article-2`)].relationships
568588
.field_tertiary_image___NODE_image___NODE
569589
).toBe(undefined)
590+
expect(
591+
nodes[createNodeId(`und.article-10`)].relationships.field_tags___NODE
592+
.length
593+
).toBe(1)
570594
})
571595

572596
it(`Back references`, () => {

packages/gatsby-source-drupal/src/gatsby-node.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const {
1616
storeRefsLookups,
1717
handleReferences,
1818
handleWebhookUpdate,
19+
createNodeIfItDoesNotExist,
1920
handleDeletedNode,
2021
} = require(`./utils`)
2122

@@ -234,6 +235,17 @@ ${JSON.stringify(webhookBody, null, 4)}`
234235
nodesToUpdate = [data]
235236
}
236237

238+
for (const nodeToUpdate of nodesToUpdate) {
239+
await createNodeIfItDoesNotExist({
240+
nodeToUpdate,
241+
actions,
242+
createNodeId,
243+
createContentDigest,
244+
getNode,
245+
reporter,
246+
})
247+
}
248+
237249
for (const nodeToUpdate of nodesToUpdate) {
238250
await handleWebhookUpdate(
239251
{
@@ -345,6 +357,31 @@ ${JSON.stringify(webhookBody, null, 4)}`
345357

346358
// Process sync data from Drupal.
347359
const nodesToSync = res.body.entities
360+
361+
// First create all nodes that we haven't seen before. That
362+
// way we can create relationships correctly next as the nodes
363+
// will exist in Gatsby.
364+
for (const nodeSyncData of nodesToSync) {
365+
if (nodeSyncData.action === `delete`) {
366+
continue
367+
}
368+
369+
let nodesToUpdate = nodeSyncData.data
370+
if (!Array.isArray(nodeSyncData.data)) {
371+
nodesToUpdate = [nodeSyncData.data]
372+
}
373+
for (const nodeToUpdate of nodesToUpdate) {
374+
createNodeIfItDoesNotExist({
375+
nodeToUpdate,
376+
actions,
377+
createNodeId,
378+
createContentDigest,
379+
getNode,
380+
reporter,
381+
})
382+
}
383+
}
384+
348385
for (const nodeSyncData of nodesToSync) {
349386
if (nodeSyncData.action === `delete`) {
350387
handleDeletedNode({

packages/gatsby-source-drupal/src/utils.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,50 @@ const handleDeletedNode = async ({
240240
return deletedNode
241241
}
242242

243+
function createNodeIfItDoesNotExist({
244+
nodeToUpdate,
245+
actions,
246+
createNodeId,
247+
createContentDigest,
248+
getNode,
249+
reporter,
250+
}) {
251+
if (!nodeToUpdate) {
252+
reporter.warn(
253+
`The updated node was empty. The fact you're seeing this warning means there's probably a bug in how we're creating and processing updates from Drupal.
254+
255+
${JSON.stringify(nodeToUpdate, null, 4)}
256+
`
257+
)
258+
259+
return
260+
}
261+
262+
const { createNode } = actions
263+
const newNodeId = createNodeId(
264+
createNodeIdWithVersion(
265+
nodeToUpdate.id,
266+
nodeToUpdate.type,
267+
getOptions().languageConfig ? nodeToUpdate.langcode : `und`,
268+
nodeToUpdate.meta?.target_version,
269+
getOptions().entityReferenceRevisions
270+
)
271+
)
272+
273+
const oldNode = getNode(newNodeId)
274+
// Node doesn't yet exist so we'll create it now.
275+
if (!oldNode) {
276+
const newNode = nodeFromData(
277+
nodeToUpdate,
278+
createNodeId,
279+
getOptions().entityReferenceRevisions
280+
)
281+
282+
newNode.internal.contentDigest = createContentDigest(newNode)
283+
createNode(newNode)
284+
}
285+
}
286+
243287
const handleWebhookUpdate = async (
244288
{
245289
nodeToUpdate,
@@ -409,3 +453,4 @@ function drupalCreateNodeManifest({
409453

410454
exports.handleWebhookUpdate = handleWebhookUpdate
411455
exports.handleDeletedNode = handleDeletedNode
456+
exports.createNodeIfItDoesNotExist = createNodeIfItDoesNotExist

0 commit comments

Comments
 (0)