Skip to content

Commit 54be998

Browse files
feat(ui): add 'replace' and 'merge' strategies for upsertMetadata
1 parent 0d3af08 commit 54be998

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

invokeai/frontend/web/src/features/nodes/util/graph/generation/Graph.test.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -579,12 +579,20 @@ describe('Graph', () => {
579579
const metadata = g.getMetadataNode();
580580
expect(metadata).toHaveProperty('test');
581581
});
582-
it('should update metadata on the metadata node', () => {
582+
it("should overwrite metadata on the metadata node if the strategy is 'replace'", () => {
583583
const g = new Graph();
584-
g.upsertMetadata({ test: 'test' });
585-
g.upsertMetadata({ test: 'test2' });
584+
g.upsertMetadata({ test: { foo: 'test' } }, 'replace');
585+
g.upsertMetadata({ test: { bar: 'test2' } }, 'replace');
586+
const metadata = g.getMetadataNode();
587+
expect(metadata.test).toEqual({ bar: 'test2' });
588+
});
589+
it("should merge keys if the strategy is 'merge'", () => {
590+
const g = new Graph();
591+
g.upsertMetadata({ test: { foo: 'test' }, arr: [1] }, 'merge');
592+
g.upsertMetadata({ test: { bar: 'test2' }, arr: [2] }, 'merge');
586593
const metadata = g.getMetadataNode();
587-
expect(metadata.test).toBe('test2');
594+
expect(metadata.test).toEqual({ foo: 'test', bar: 'test2' });
595+
expect(metadata.arr).toEqual([1, 2]);
588596
});
589597
});
590598

invokeai/frontend/web/src/features/nodes/util/graph/generation/Graph.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { objectEquals } from '@observ33r/object-equals';
2+
import { mergeWith } from 'es-toolkit';
23
import { forEach, groupBy, unset, values } from 'es-toolkit/compat';
34
import { getPrefixedId } from 'features/controlLayers/konva/util';
45
import { type ModelIdentifierField, zModelIdentifierField } from 'features/nodes/types/common';
@@ -387,11 +388,25 @@ export class Graph {
387388
* Add metadata to the graph. If the metadata node does not exist, it is created. If the specific metadata key exists,
388389
* it is overwritten.
389390
* @param metadata The metadata to add.
391+
* @param strategy The strategy to use when adding metadata. If 'replace', any existing key is replaced. If 'add',
392+
* the metadata is deeply merged with the existing metadata. Arrays will be concatenated.
390393
* @returns The metadata node.
391394
*/
392-
upsertMetadata(metadata: Partial<S['CoreMetadataInvocation']>): S['CoreMetadataInvocation'] {
395+
upsertMetadata(
396+
metadata: Partial<S['CoreMetadataInvocation']>,
397+
strategy: 'replace' | 'merge' = 'replace'
398+
): S['CoreMetadataInvocation'] {
393399
const node = this.getMetadataNode();
394-
Object.assign(node, metadata);
400+
if (strategy === 'replace') {
401+
Object.assign(node, metadata);
402+
} else {
403+
// strategy === 'merge'
404+
mergeWith(node, metadata, (objValue, srcValue) => {
405+
if (Array.isArray(objValue)) {
406+
return objValue.concat(srcValue);
407+
}
408+
});
409+
}
395410
return node;
396411
}
397412

0 commit comments

Comments
 (0)