mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-10 15:40:24 +00:00
# Documentation Audit and Corrections
## Summary
- Fixed incorrect test directory reference in AGENTS.md (`tests-ui/` →
removed)
- Updated outdated timestamps in composables and stores READMEs
- Fixed critical workflow name error in create-frontend-release command
- Removed misleading i18n workflow warnings from release documentation
## Changes Made
### AGENTS.md
- **Line 24**: Removed non-existent `tests-ui/` directory from test file
locations
- Unit/component tests are located in `src/**/*.test.ts` only
- **Line 267**: Removed `tests-ui` from repository navigation guidance
### src/composables/README.md
- **Line 88**: Updated timestamp from "2025-01-30" to "2026-01-30" to
reflect current state
### src/stores/README.md
- **Line 105**: Updated timestamp from "2025-09-01" to "2026-01-29" to
reflect last modification date
### .claude/commands/create-frontend-release.md
- **Line 394**: Fixed critical workflow name error
- Changed `version-bump.yaml` → `release-version-bump.yaml`
- This was causing command failures as the workflow file doesn't exist
- **Lines 446-450**: Removed outdated warning about `update-locales`
workflow adding `[skip ci]`
- No such workflow exists in the repository
- Current i18n workflows are: `i18n-update-core.yaml`,
`i18n-update-custom-nodes.yaml`, `i18n-update-nodes.yaml`
- None of these add `[skip ci]` to commits
- **Lines 464-465**: Removed duplicate critical warning about
non-existent `update-locales` workflow
## Review Notes
### Documentation Accuracy Verification Process
Conducted comprehensive fact-checking of all documentation against the
current codebase:
1. **Configuration Files**: Verified all referenced config files exist
(vite.config.mts, playwright.config.ts, eslint.config.ts, .oxfmtrc.json,
.oxlintrc.json)
2. **Package Scripts**: Validated all npm/pnpm commands referenced in
documentation
3. **Directory Structure**: Confirmed project structure matches
documented layout
4. **Extension Documentation**: Verified TypeScript interface paths and
external resource links
5. **Testing Documentation**: Confirmed test file patterns and framework
references
6. **Command Documentation**: Validated workflow names and GitHub CLI
commands
### Known Documentation Gaps (Not Addressed)
These items were identified but not changed as they represent
aspirational guidance or current migration paths:
1. **docs/guidance/vue-components.md**: Documents Vue 3.5 prop
destructuring pattern (`const { prop } = defineProps<>()`) while
codebase still uses `withDefaults()` in many files
- This is intentional - guidance shows preferred pattern for new code
2. **docs/guidance/playwright.md**: Advises against `waitForTimeout` but
4 test files still use it
- Existing violations are technical debt
3. **AGENTS.md Line 163**: States "Avoid new usage of PrimeVue
components" but some components still use PrimeVue
- Guidance is for new code; existing usage being gradually migrated
4. **docs/guidance/typescript.md**: Discourages `as any` but 11
instances exist in codebase
- Known technical debt
### Additional Findings
- All README files in key directories (composables, stores, services,
extensions, testing) are accurate and comprehensive
- External documentation links (Vue, Tailwind, VueUse, etc.) are valid
- Code examples in documentation are syntactically correct
- i18n structure and paths are correctly documented
## Verification Commands
To verify the fixes:
```bash
# Verify tests-ui directory doesn't exist
ls tests-ui 2>&1 | grep "No such file"
# Verify correct workflow file exists
ls .github/workflows/release-version-bump.yaml
# Verify no workflows add [skip ci]
grep -r "skip ci" .github/workflows/*.yaml || echo "None found (expected)"
# Verify test files are in src/
find src -name "*.test.ts" | wc -l # Should show many test files
```
---------
Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
391 lines
18 KiB
Markdown
391 lines
18 KiB
Markdown
# Stores
|
|
|
|
This directory contains Pinia stores for the ComfyUI frontend application. Stores provide centralized state management for the application.
|
|
|
|
## Table of Contents
|
|
|
|
- [Overview](#overview)
|
|
- [Store Architecture](#store-architecture)
|
|
- [Core Stores](#core-stores)
|
|
- [Store Development Guidelines](#store-development-guidelines)
|
|
- [Common Patterns](#common-patterns)
|
|
- [Testing Stores](#testing-stores)
|
|
|
|
## Overview
|
|
|
|
Stores in ComfyUI use [Pinia](https://pinia.vuejs.org/), Vue's official state management library. Each store is responsible for managing a specific domain of the application state, such as user data, workflow information, graph state, and UI configuration.
|
|
|
|
Stores provide a way to maintain global application state that can be accessed from any component, regardless of where those components are in the component hierarchy. This solves the problem of "prop drilling" (passing data down through multiple levels of components) and allows components that aren't directly related to share and modify the same state.
|
|
|
|
For example, without global state:
|
|
|
|
```
|
|
App
|
|
│
|
|
┌──────────┴──────────┐
|
|
│ │
|
|
HeaderBar Canvas
|
|
│ │
|
|
│ │
|
|
UserMenu NodeProperties
|
|
```
|
|
|
|
In this structure, if the `UserMenu` component needs to update something that affects `NodeProperties`, the data would need to be passed up to `App` and then down again, through all intermediate components.
|
|
|
|
With Pinia stores, components can directly access and update the shared state:
|
|
|
|
```
|
|
┌─────────────────┐
|
|
│ │
|
|
│ Pinia Stores │
|
|
│ │
|
|
└───────┬─────────┘
|
|
│
|
|
│ Accessed by
|
|
▼
|
|
┌──────────────────────────┐
|
|
│ │
|
|
│ Components │
|
|
│ │
|
|
└──────────────────────────┘
|
|
```
|
|
|
|
## Store Architecture
|
|
|
|
The store architecture in ComfyUI follows these principles:
|
|
|
|
1. **Domain-driven**: Each store focuses on a specific domain of the application
|
|
2. **Single source of truth**: Stores serve as the definitive source for specific data
|
|
3. **Composition**: Stores can interact with other stores when needed
|
|
4. **Actions for logic**: Business logic is encapsulated in store actions
|
|
5. **Getters for derived state**: Computed values are exposed via getters
|
|
|
|
The following diagram illustrates the store architecture and data flow:
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ Vue Components │
|
|
│ │
|
|
│ ┌───────────────┐ ┌───────────────┐ │
|
|
│ │ Component A │ │ Component B │ │
|
|
│ └───────┬───────┘ └───────┬───────┘ │
|
|
│ │ │ │
|
|
└───────────┼────────────────────────────┼────────────────┘
|
|
│ │
|
|
│ ┌───────────────┐ │
|
|
└────►│ Composables │◄─────┘
|
|
└───────┬───────┘
|
|
│
|
|
┌─────────────────────────┼─────────────────────────────┐
|
|
│ Pinia Stores │ │
|
|
│ │ │
|
|
│ ┌───────────────────▼───────────────────────┐ │
|
|
│ │ Actions │ │
|
|
│ └───────────────────┬───────────────────────┘ │
|
|
│ │ │
|
|
│ ┌───────────────────▼───────────────────────┐ │
|
|
│ │ State │ │
|
|
│ └───────────────────┬───────────────────────┘ │
|
|
│ │ │
|
|
│ ┌───────────────────▼───────────────────────┐ │
|
|
│ │ Getters │ │
|
|
│ └───────────────────┬───────────────────────┘ │
|
|
│ │ │
|
|
└─────────────────────────┼─────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ External Services │
|
|
│ (API, localStorage, WebSocket, etc.) │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Core Stores
|
|
|
|
The following table lists ALL 46 store instances in the system as of 2026-01-29:
|
|
|
|
### Main Stores
|
|
|
|
| File | Store | Description | Category |
|
|
| ---------------------------- | ----------------------------- | ------------------------------------------------------- | ---------- |
|
|
| aboutPanelStore.ts | useAboutPanelStore | Manages the About panel state and badges | UI |
|
|
| apiKeyAuthStore.ts | useApiKeyAuthStore | Handles API key authentication | Auth |
|
|
| comfyManagerStore.ts | useComfyManagerStore | Manages ComfyUI application state | Core |
|
|
| comfyRegistryStore.ts | useComfyRegistryStore | Handles extensions registry | Registry |
|
|
| commandStore.ts | useCommandStore | Manages commands and command execution | Core |
|
|
| dialogStore.ts | useDialogStore | Controls dialog/modal display and state | UI |
|
|
| domWidgetStore.ts | useDomWidgetStore | Manages DOM widget state | Widgets |
|
|
| electronDownloadStore.ts | useElectronDownloadStore | Handles Electron-specific download operations | Platform |
|
|
| executionStore.ts | useExecutionStore | Tracks workflow execution state | Execution |
|
|
| extensionStore.ts | useExtensionStore | Manages extension registration and state | Extensions |
|
|
| firebaseAuthStore.ts | useFirebaseAuthStore | Handles Firebase authentication | Auth |
|
|
| graphStore.ts | useTitleEditorStore | Manages title editing for nodes and groups | UI |
|
|
| graphStore.ts | useCanvasStore | Manages the graph canvas state and interactions | Core |
|
|
| helpCenterStore.ts | useHelpCenterStore | Manages help center visibility and state | UI |
|
|
| imagePreviewStore.ts | useNodeOutputStore | Manages node outputs and execution results | Media |
|
|
| maintenanceTaskStore.ts | useMaintenanceTaskStore | Handles system maintenance tasks | System |
|
|
| menuItemStore.ts | useMenuItemStore | Handles menu items and their state | UI |
|
|
| modelStore.ts | useModelStore | Manages AI models information | Models |
|
|
| modelToNodeStore.ts | useModelToNodeStore | Maps models to compatible nodes | Models |
|
|
| nodeBookmarkStore.ts | useNodeBookmarkStore | Manages node bookmarks and favorites | Nodes |
|
|
| nodeDefStore.ts | useNodeDefStore | Manages node definitions and schemas | Nodes |
|
|
| nodeDefStore.ts | useNodeFrequencyStore | Tracks node usage frequency | Nodes |
|
|
| queueStore.ts | useQueueStore | Manages execution queue and task history | Execution |
|
|
| queueStore.ts | useQueuePendingTaskCountStore | Tracks pending task counts | Execution |
|
|
| queueStore.ts | useQueueSettingsStore | Manages queue execution settings | Execution |
|
|
| releaseStore.ts | useReleaseStore | Manages application release information | System |
|
|
| serverConfigStore.ts | useServerConfigStore | Handles server configuration | Config |
|
|
| settingStore.ts | useSettingStore | Manages application settings | Config |
|
|
| subgraphNavigationStore.ts | useSubgraphNavigationStore | Handles subgraph navigation state | Navigation |
|
|
| systemStatsStore.ts | useSystemStatsStore | Tracks system performance statistics | System |
|
|
| toastStore.ts | useToastStore | Manages toast notifications | UI |
|
|
| userFileStore.ts | useUserFileStore | Manages user file operations | Files |
|
|
| userStore.ts | useUserStore | Manages user data and preferences | User |
|
|
| versionCompatibilityStore.ts | useVersionCompatibilityStore | Manages frontend/backend version compatibility warnings | Core |
|
|
| widgetStore.ts | useWidgetStore | Manages widget configurations | Widgets |
|
|
| workflowStore.ts | useWorkflowStore | Handles workflow data and operations | Workflows |
|
|
| workflowStore.ts | useWorkflowBookmarkStore | Manages workflow bookmarks and favorites | Workflows |
|
|
| workflowTemplatesStore.ts | useWorkflowTemplatesStore | Manages workflow templates | Workflows |
|
|
| workspaceStore.ts | useWorkspaceStore | Manages overall workspace state | Workspace |
|
|
|
|
### Workspace Stores
|
|
|
|
Located in `stores/workspace/`:
|
|
|
|
| File | Store | Description | Category |
|
|
| -------------------- | -------------------- | ------------------------------------------- | -------- |
|
|
| bottomPanelStore.ts | useBottomPanelStore | Controls bottom panel visibility and state | UI |
|
|
| colorPaletteStore.ts | useColorPaletteStore | Manages color palette configurations | UI |
|
|
| nodeHelpStore.ts | useNodeHelpStore | Handles node help and documentation display | UI |
|
|
| searchBoxStore.ts | useSearchBoxStore | Manages search box functionality | UI |
|
|
| sidebarTabStore.ts | useSidebarTabStore | Controls sidebar tab states and navigation | UI |
|
|
|
|
## Store Development Guidelines
|
|
|
|
When developing or modifying stores, follow these best practices:
|
|
|
|
1. **Define clear purpose**: Each store should have a specific responsibility
|
|
2. **Use actions for async operations**: Encapsulate asynchronous logic in actions
|
|
3. **Keep stores focused**: Each store should manage related state
|
|
4. **Document public API**: Add comments for state properties, actions, and getters
|
|
5. **Use getters for derived state**: Compute derived values using getters
|
|
6. **Test store functionality**: Write unit tests for stores
|
|
|
|
### Store Template
|
|
|
|
Here's a template for creating a new Pinia store, following the setup style used in ComfyUI:
|
|
|
|
```typescript
|
|
import { defineStore } from 'pinia'
|
|
import { computed, ref } from 'vue'
|
|
|
|
export const useExampleStore = defineStore('example', () => {
|
|
// State
|
|
const items = ref([])
|
|
const isLoading = ref(false)
|
|
const error = ref(null)
|
|
|
|
// Getters
|
|
const itemCount = computed(() => items.value.length)
|
|
const hasError = computed(() => error.value !== null)
|
|
|
|
// Actions
|
|
function addItem(item) {
|
|
items.value.push(item)
|
|
}
|
|
|
|
async function fetchItems() {
|
|
isLoading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
const response = await fetch('/api/items')
|
|
const data = await response.json()
|
|
items.value = data
|
|
} catch (err) {
|
|
error.value = err.message
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
// Expose state, getters, and actions
|
|
return {
|
|
// State
|
|
items,
|
|
isLoading,
|
|
error,
|
|
|
|
// Getters
|
|
itemCount,
|
|
hasError,
|
|
|
|
// Actions
|
|
addItem,
|
|
fetchItems
|
|
}
|
|
})
|
|
```
|
|
|
|
## Common Patterns
|
|
|
|
Stores in ComfyUI frequently use these patterns:
|
|
|
|
### API Integration
|
|
|
|
```typescript
|
|
import { defineStore } from 'pinia'
|
|
import { ref } from 'vue'
|
|
import { api } from '@/scripts/api'
|
|
|
|
export const useDataStore = defineStore('data', () => {
|
|
const data = ref([])
|
|
const loading = ref(false)
|
|
const error = ref(null)
|
|
|
|
async function fetchData() {
|
|
loading.value = true
|
|
try {
|
|
const result = await api.getExtensions()
|
|
data.value = result
|
|
} catch (err) {
|
|
error.value = err.message
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
return {
|
|
data,
|
|
loading,
|
|
error,
|
|
fetchData
|
|
}
|
|
})
|
|
```
|
|
|
|
### Store Composition
|
|
|
|
```typescript
|
|
import { defineStore, storeToRefs } from 'pinia'
|
|
import { computed, ref, watch } from 'vue'
|
|
import { useOtherStore } from './otherStore'
|
|
|
|
export const useComposedStore = defineStore('composed', () => {
|
|
const otherStore = useOtherStore()
|
|
const { someData } = storeToRefs(otherStore)
|
|
|
|
// Local state
|
|
const localState = ref(0)
|
|
|
|
// Computed value based on other store
|
|
const derivedValue = computed(() => {
|
|
return computeFromOtherData(someData.value, localState.value)
|
|
})
|
|
|
|
// Action that uses another store
|
|
async function complexAction() {
|
|
await otherStore.someAction()
|
|
localState.value += 1
|
|
}
|
|
|
|
return {
|
|
localState,
|
|
derivedValue,
|
|
complexAction
|
|
}
|
|
})
|
|
```
|
|
|
|
### Persistent State
|
|
|
|
```typescript
|
|
import { defineStore } from 'pinia'
|
|
import { ref, watch } from 'vue'
|
|
|
|
export const usePreferencesStore = defineStore('preferences', () => {
|
|
// Load from localStorage if available
|
|
const theme = ref(localStorage.getItem('theme') || 'light')
|
|
const fontSize = ref(parseInt(localStorage.getItem('fontSize') || '14'))
|
|
|
|
// Save to localStorage when changed
|
|
watch(theme, (newTheme) => {
|
|
localStorage.setItem('theme', newTheme)
|
|
})
|
|
|
|
watch(fontSize, (newSize) => {
|
|
localStorage.setItem('fontSize', newSize.toString())
|
|
})
|
|
|
|
function setTheme(newTheme) {
|
|
theme.value = newTheme
|
|
}
|
|
|
|
return {
|
|
theme,
|
|
fontSize,
|
|
setTheme
|
|
}
|
|
})
|
|
```
|
|
|
|
## Testing Stores
|
|
|
|
Stores should be tested to ensure they behave as expected. Here's an example of how to test a store:
|
|
|
|
```typescript
|
|
import { createPinia, setActivePinia } from 'pinia'
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { nextTick } from 'vue'
|
|
|
|
import { api } from '@/scripts/api'
|
|
import { useExampleStore } from '@/stores/exampleStore'
|
|
|
|
// Mock API dependencies
|
|
vi.mock('@/scripts/api', () => ({
|
|
api: {
|
|
getData: vi.fn()
|
|
}
|
|
}))
|
|
|
|
describe('useExampleStore', () => {
|
|
let store: ReturnType<typeof useExampleStore>
|
|
|
|
beforeEach(() => {
|
|
// Create a fresh pinia instance and make it active
|
|
setActivePinia(createPinia())
|
|
store = useExampleStore()
|
|
|
|
// Clear all mocks
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
it('should initialize with default state', () => {
|
|
expect(store.items).toEqual([])
|
|
expect(store.isLoading).toBe(false)
|
|
expect(store.error).toBeNull()
|
|
})
|
|
|
|
it('should add an item', () => {
|
|
store.addItem('test')
|
|
expect(store.items).toEqual(['test'])
|
|
expect(store.itemCount).toBe(1)
|
|
})
|
|
|
|
it('should fetch items', async () => {
|
|
// Setup mock response
|
|
vi.mocked(api.getData).mockResolvedValue(['item1', 'item2'])
|
|
|
|
// Call the action
|
|
await store.fetchItems()
|
|
|
|
// Verify state changes
|
|
expect(store.isLoading).toBe(false)
|
|
expect(store.items).toEqual(['item1', 'item2'])
|
|
expect(store.error).toBeNull()
|
|
})
|
|
})
|
|
```
|
|
|
|
For more information on Pinia, refer to the [Pinia documentation](https://pinia.vuejs.org/introduction.html).
|