Skip to content

Commit 7f493de

Browse files
committed
fix(graph-view): match string and object link endpoints in applyMutation
While Activity hides the tool, mutations still update graph.data but force-graph never rewrites link endpoints from ids to node objects. Filters that only read endpoint.id left those string links in place, so later updates/disappears could leave stale or duplicate edges.
1 parent 4831228 commit 7f493de

2 files changed

Lines changed: 29 additions & 2 deletions

File tree

‎plugins/sanity-plugin-graph-view/src/tool/GraphView.test.tsx‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,4 +334,26 @@ describe('applyMutation', () => {
334334
expect(next).toBe(state)
335335
expect(docNode).toBeUndefined()
336336
})
337+
338+
// While Activity hides the tool, force-graph never rewrites string endpoints to node objects.
339+
// Mutations still chain through applyMutation, so filters must match both shapes.
340+
test('replaces string-endpoint links when references change before force-graph rewrites them', () => {
341+
const state = {documents: [author, post], graph: new GraphData([author, post])}
342+
expect(state.graph.data.links).toEqual([{source: 'b', target: 'a'}])
343+
344+
const other = {...stamps, _id: 'c', _type: 'author', title: 'C'} as SanityDocument
345+
const withOther = applyMutation(state, mutation('appear', 'c', other)).next
346+
const doc = {...stamps, _id: 'b', _type: 'post', title: 'B', author: {_ref: 'c'}}
347+
const {next} = applyMutation(withOther, mutation('update', 'b', doc))
348+
349+
expect(next.graph.data.links).toEqual([{source: 'b', target: 'c'}])
350+
})
351+
352+
test('removes string-endpoint links when a document disappears before force-graph rewrites them', () => {
353+
const state = {documents: [author, post], graph: new GraphData([author, post])}
354+
const {next} = applyMutation(state, mutation('disappear', 'b'))
355+
356+
expect(next.graph.data.links).toEqual([])
357+
expect(next.graph.data.nodes.map((n: {id: string}) => n.id)).toEqual(['a'])
358+
})
337359
})

‎plugins/sanity-plugin-graph-view/src/tool/GraphView.tsx‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ function stripDraftId(id: string) {
7979
return id.replace(/^drafts\./, '')
8080
}
8181

82+
/** force-graph replaces string endpoints with node objects; mutations while hidden leave strings. */
83+
function linkEndpointId(endpoint: string | {id: string}): string {
84+
return typeof endpoint === 'object' ? endpoint.id : endpoint
85+
}
86+
8287
function deduplicateDrafts(docs: SanityDocument[]) {
8388
const deduped: Record<string, SanityDocument> = {}
8489
for (const doc of docs) {
@@ -219,7 +224,7 @@ export function applyMutation(
219224
let graphChanged = !dequal(oldRefs, newRefs)
220225
if (graphChanged) {
221226
newGraph.data.links = newGraph.data.links
222-
.filter((l: any) => l.source.id !== doc._id)
227+
.filter((l: any) => linkEndpointId(l.source) !== doc._id)
223228
.concat(newRefs.map((ref) => ({source: doc._id, target: ref})))
224229
}
225230

@@ -242,7 +247,7 @@ export function applyMutation(
242247

243248
const newGraph = graph.clone()
244249
newGraph.data.links = newGraph.data.links.filter(
245-
(l: any) => l.source.id !== docId && l.target.id !== docId,
250+
(l: any) => linkEndpointId(l.source) !== docId && linkEndpointId(l.target) !== docId,
246251
)
247252
newGraph.data.nodes = newGraph.data.nodes.filter((n: any) => n.id !== docId)
248253

0 commit comments

Comments
 (0)