Skip to content

Commit

Permalink
fix(gatsby-source-drupal): handle edge case with deleting nodes (#33143)
Browse files Browse the repository at this point in the history
* fix(gatsby-source-drupal): handle edge case with deleting nodes

In this case, when trying to deleting a node's references nodes, we were crashing if the referenced
node had already been deleted.

* also cleanup referencedNodesLookup
  • Loading branch information
KyleAMathews committed Sep 10, 2021
1 parent eb552d1 commit 2f2880e
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 32 deletions.
@@ -1,11 +1,21 @@
{
"timestamp": 1593545807,
"entities": [
{
"action": "delete",
"id": "article-71",
"type": "node--article"
},
{
"action": "delete",
"id": "file-4",
"type": "file--file"
},
{
"action": "delete",
"id": "does-not-exist",
"type": "file--file"
},
{
"jsonapi": {
"version": "1.0",
Expand Down
32 changes: 32 additions & 0 deletions packages/gatsby-source-drupal/src/__tests__/fixtures/article.json
Expand Up @@ -73,6 +73,38 @@
"data": null
}
}
},
{
"type": "node--article",
"id": "article-71",
"attributes": {
"id": 223,
"uuid": "article-71",
"title": "Article #71",
"body": "Proin pulvinar hendrerit magna nec maximus. Donec rhoncus libero ac nisi porttitor pulvinar. Quisque semper ultricies nulla sit amet vestibulum. Ut vel libero erat. Ut ultrices eleifend scelerisque. Nam non massa sit amet magna molestie tempus vel non neque. Praesent ac est congue, euismod mi ut, tristique mi. Etiam dapibus feugiat lectus, vel condimentum nisl maximus et. Praesent et placerat magna. Sed nec risus non ipsum venenatis placerat. Vestibulum vitae felis eget nunc mattis congue. Morbi volutpat odio purus. Donec placerat massa sed neque molestie, sed finibus nibh scelerisque. In faucibus ante tortor, in efficitur lectus feugiat vitae. Aliquam sodales mollis consectetur."
},
"relationships": {
"field_secondary_image": {
"data": [
{
"type": "file--file",
"id": "file-4"
}
]
},
"field_secondary_multiple_image": {
"data": [
{
"type": "file--file",
"id": "file-3"
},
{
"type": "file--file",
"id": "file-4"
}
]
}
}
}
],
"links": {
Expand Down
72 changes: 40 additions & 32 deletions packages/gatsby-source-drupal/src/utils.js
Expand Up @@ -136,50 +136,58 @@ const handleDeletedNode = async ({
return deletedNode
}

// Remove the deleted node from backRefsNamesLookup
// Remove the deleted node from backRefsNamesLookup and referencedNodesLookup
backRefsNamesLookup.delete(deletedNode)
referencedNodesLookup.delete(deletedNode)

// Remove relationships from other nodes and re-create them.
Object.keys(deletedNode.relationships).forEach(key => {
let ids = deletedNode.relationships[key]
ids = [].concat(ids)
ids.forEach(id => {
const node = getNode(id)
let referencedNodes = referencedNodesLookup.get(node)
if (referencedNodes?.includes(deletedNode.id)) {
// Loop over relationships and cleanup references.
Object.entries(node.relationships).forEach(([key, value]) => {
// If a string ref matches, delete it.
if (_.isString(value) && value === deletedNode.id) {
delete node.relationships[key]
}

// If it's an array, filter, then check if the array is empty and then delete
// if so
if (_.isArray(value)) {
value = value.filter(v => v !== deletedNode.id)

if (value.length === 0) {

// The referenced node might have already been deleted.
if (node) {
let referencedNodes = referencedNodesLookup.get(node)
if (referencedNodes?.includes(deletedNode.id)) {
// Loop over relationships and cleanup references.
Object.entries(node.relationships).forEach(([key, value]) => {
// If a string ref matches, delete it.
if (_.isString(value) && value === deletedNode.id) {
delete node.relationships[key]
} else {
node.relationships[key] = value
}
}
})

// Remove deleted node from array of referencedNodes
referencedNodes = referencedNodes.filter(nId => nId !== deletedNode.id)
referencedNodesLookup.set(node, referencedNodes)
}
// Recreate the referenced node with its now cleaned-up relationships.
if (node.internal.owner) {
delete node.internal.owner
}
if (node.fields) {
delete node.fields
// If it's an array, filter, then check if the array is empty and then delete
// if so
if (_.isArray(value)) {
value = value.filter(v => v !== deletedNode.id)

if (value.length === 0) {
delete node.relationships[key]
} else {
node.relationships[key] = value
}
}
})

// Remove deleted node from array of referencedNodes
referencedNodes = referencedNodes.filter(
nId => nId !== deletedNode.id
)
referencedNodesLookup.set(node, referencedNodes)
}

// Recreate the referenced node with its now cleaned-up relationships.
if (node.internal.owner) {
delete node.internal.owner
}
if (node.fields) {
delete node.fields
}
node.internal.contentDigest = createContentDigest(node)
actions.createNode(node)
}
node.internal.contentDigest = createContentDigest(node)
actions.createNode(node)
})
})

Expand Down

0 comments on commit 2f2880e

Please sign in to comment.