feat: add WidgetValueStore for centralized widget values

Amp-Thread-ID: https://ampcode.com/threads/T-019c2554-9721-705e-82f9-7742306a49cc
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Alexander Brown
2026-02-03 13:11:36 -08:00
parent e26283e754
commit 80a5108269
2 changed files with 95 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
import { createTestingPinia } from '@pinia/testing'
import { setActivePinia } from 'pinia'
import { beforeEach, describe, expect, it } from 'vitest'
import { useWidgetValueStore } from './widgetValueStore'
describe('useWidgetValueStore', () => {
beforeEach(() => {
setActivePinia(createTestingPinia({ stubActions: false }))
})
it('stores and retrieves values', () => {
const store = useWidgetValueStore()
store.set('node-1', 'seed', 12345)
expect(store.get('node-1', 'seed')).toBe(12345)
})
it('returns undefined for missing values', () => {
const store = useWidgetValueStore()
expect(store.get('missing', 'widget')).toBeUndefined()
})
it('removes single widget value', () => {
const store = useWidgetValueStore()
store.set('node-1', 'seed', 100)
store.remove('node-1', 'seed')
expect(store.get('node-1', 'seed')).toBeUndefined()
})
it('removes all widgets for a node', () => {
const store = useWidgetValueStore()
store.set('node-1', 'seed', 1)
store.set('node-1', 'steps', 20)
store.set('node-2', 'seed', 2)
store.removeNode('node-1')
expect(store.get('node-1', 'seed')).toBeUndefined()
expect(store.get('node-1', 'steps')).toBeUndefined()
expect(store.get('node-2', 'seed')).toBe(2)
})
it('overwrites existing values', () => {
const store = useWidgetValueStore()
store.set('node-1', 'seed', 100)
store.set('node-1', 'seed', 200)
expect(store.get('node-1', 'seed')).toBe(200)
})
it('stores different value types', () => {
const store = useWidgetValueStore()
store.set('node-1', 'text', 'hello')
store.set('node-1', 'number', 42)
store.set('node-1', 'boolean', true)
store.set('node-1', 'array', [1, 2, 3])
expect(store.get('node-1', 'text')).toBe('hello')
expect(store.get('node-1', 'number')).toBe(42)
expect(store.get('node-1', 'boolean')).toBe(true)
expect(store.get('node-1', 'array')).toEqual([1, 2, 3])
})
})

View File

@@ -0,0 +1,33 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import type { NodeId } from '@/lib/litegraph/src/LGraphNode'
type WidgetKey = `${NodeId}:${string}`
export const useWidgetValueStore = defineStore('widgetValue', () => {
const values = ref(new Map<WidgetKey, unknown>())
function get(nodeId: NodeId, widgetName: string): unknown {
return values.value.get(`${nodeId}:${widgetName}`)
}
function set(nodeId: NodeId, widgetName: string, value: unknown): void {
values.value.set(`${nodeId}:${widgetName}`, value)
}
function remove(nodeId: NodeId, widgetName: string): void {
values.value.delete(`${nodeId}:${widgetName}`)
}
function removeNode(nodeId: NodeId): void {
const prefix = `${nodeId}:`
for (const key of values.value.keys()) {
if (key.startsWith(prefix)) {
values.value.delete(key)
}
}
}
return { values, get, set, remove, removeNode }
})