Compare commits

..

7 Commits

Author SHA1 Message Date
filtered
ee2c4cf4df Fix direct call into litegraph internals instead of lib entrypoint 2025-09-16 21:17:23 +10:00
filtered
5dd47af3b0 Fix type only imports - erase completely 2025-09-16 21:16:49 +10:00
filtered
7461c91185 Fix import - loading module at runtime solely to get type 2025-09-16 20:48:14 +10:00
filtered
e2e8ff6c3b Auto fix & format all files 2025-09-16 20:27:44 +10:00
filtered
b25690d435 Enable verbatim module syntax 2025-09-16 20:27:44 +10:00
filtered
9da2ccdb5b Add script dependencies 2025-09-16 20:27:44 +10:00
filtered
be48709c27 Add modified script for vue files
Vibe coded from fix-verbatim-module-syntax
2025-09-16 20:27:44 +10:00
360 changed files with 2425 additions and 6404 deletions

View File

@@ -88,8 +88,6 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'
- name: Build types
run: pnpm build:types
@@ -133,7 +131,7 @@ jobs:
- name: Publish package
if: steps.check_npm.outputs.exists == 'false'
run: pnpm publish --access public --tag "${{ inputs.dist_tag }}" --no-git-checks
run: pnpm publish --access public --tag "${{ inputs.dist_tag }}"
working-directory: dist
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

4
.gitignore vendored
View File

@@ -78,8 +78,8 @@ vite.config.mts.timestamp-*.mjs
*storybook.log
storybook-static
# MCP Servers
.playwright-mcp/*
.nx/cache
.nx/workspace-data

View File

@@ -15,32 +15,21 @@ const config: StorybookConfig = {
async viteFinal(config) {
// Use dynamic import to avoid CJS deprecation warning
const { mergeConfig } = await import('vite')
const { default: tailwindcss } = await import('@tailwindcss/vite')
// Filter out any plugins that might generate import maps
if (config.plugins) {
config.plugins = config.plugins
// Type guard: ensure we have valid plugin objects with names
.filter(
(plugin): plugin is NonNullable<typeof plugin> & { name: string } => {
return (
plugin !== null &&
plugin !== undefined &&
typeof plugin === 'object' &&
'name' in plugin &&
typeof plugin.name === 'string'
)
}
)
// Business logic: filter out import-map plugins
.filter((plugin) => !plugin.name.includes('import-map'))
config.plugins = config.plugins.filter((plugin: any) => {
if (plugin && plugin.name && plugin.name.includes('import-map')) {
return false
}
return true
})
}
return mergeConfig(config, {
// Replace plugins entirely to avoid inheritance issues
plugins: [
// Only include plugins we explicitly need for Storybook
tailwindcss(),
Icons({
compiler: 'vue3',
customCollections: {

View File

@@ -1,7 +1,7 @@
import { definePreset } from '@primevue/themes'
import Aura from '@primevue/themes/aura'
import { setup } from '@storybook/vue3'
import type { Preview, StoryContext, StoryFn } from '@storybook/vue3-vite'
import type { Preview } from '@storybook/vue3-vite'
import { createPinia } from 'pinia'
import 'primeicons/primeicons.css'
import PrimeVue from 'primevue/config'
@@ -9,9 +9,11 @@ import ConfirmationService from 'primevue/confirmationservice'
import ToastService from 'primevue/toastservice'
import Tooltip from 'primevue/tooltip'
import '@/assets/css/style.css'
import { i18n } from '@/i18n'
import '@/lib/litegraph/public/css/litegraph.css'
import '../src/assets/css/style.css'
import { i18n } from '../src/i18n'
import '../src/lib/litegraph/public/css/litegraph.css'
import { useWidgetStore } from '../src/stores/widgetStore'
import { useColorPaletteStore } from '../src/stores/workspace/colorPaletteStore'
const ComfyUIPreset = definePreset(Aura, {
semantic: {
@@ -23,11 +25,13 @@ const ComfyUIPreset = definePreset(Aura, {
// Setup Vue app for Storybook
setup((app) => {
app.directive('tooltip', Tooltip)
// Create Pinia instance
const pinia = createPinia()
app.use(pinia)
// Initialize stores
useColorPaletteStore(pinia)
useWidgetStore(pinia)
app.use(i18n)
app.use(PrimeVue, {
theme: {
@@ -46,8 +50,8 @@ setup((app) => {
app.use(ToastService)
})
// Theme and dialog decorator
export const withTheme = (Story: StoryFn, context: StoryContext) => {
// Dark theme decorator
export const withTheme = (Story: any, context: any) => {
const theme = context.globals.theme || 'light'
// Apply theme class to document root
@@ -59,7 +63,7 @@ export const withTheme = (Story: StoryFn, context: StoryContext) => {
document.body.classList.remove('dark-theme')
}
return Story(context.args, context)
return Story()
}
const preview: Preview = {

View File

@@ -1,5 +1,4 @@
import type { Page } from '@playwright/test'
import { test as base } from '@playwright/test'
import { Page, test as base } from '@playwright/test'
export class UserSelectPage {
constructor(

View File

@@ -1,4 +1,4 @@
import type { Locator, Page } from '@playwright/test'
import { Locator, Page } from '@playwright/test'
export class ComfyNodeSearchFilterSelectionPanel {
constructor(public readonly page: Page) {}

View File

@@ -1,6 +1,6 @@
import type { Page } from '@playwright/test'
import { Page } from '@playwright/test'
import type { ComfyPage } from '../ComfyPage'
import { ComfyPage } from '../ComfyPage'
export class SettingDialog {
constructor(

View File

@@ -1,4 +1,4 @@
import type { Locator, Page } from '@playwright/test'
import { Locator, Page } from '@playwright/test'
class SidebarTab {
constructor(

View File

@@ -1,5 +1,4 @@
import type { Locator, Page } from '@playwright/test'
import { expect } from '@playwright/test'
import { Locator, Page, expect } from '@playwright/test'
export class Topbar {
private readonly menuLocator: Locator

View File

@@ -12,10 +12,9 @@ export const webSocketFixture = base.extend<{
// so we can look it up to trigger messages
const store: Record<string, WebSocket> = ((window as any).__ws__ = {})
window.WebSocket = class extends window.WebSocket {
constructor(
...rest: ConstructorParameters<typeof window.WebSocket>
) {
super(...rest)
constructor() {
// @ts-expect-error
super(...arguments)
store[this.url] = this
}
}

View File

@@ -1,4 +1,4 @@
import type { FullConfig } from '@playwright/test'
import { FullConfig } from '@playwright/test'
import dotenv from 'dotenv'
import { backupPath } from './utils/backupUtils'

View File

@@ -1,4 +1,4 @@
import type { FullConfig } from '@playwright/test'
import { FullConfig } from '@playwright/test'
import dotenv from 'dotenv'
import { restorePath } from './utils/backupUtils'

View File

@@ -1,4 +1,4 @@
import type { Locator, Page } from '@playwright/test'
import { Locator, Page } from '@playwright/test'
export class ManageGroupNode {
footer: Locator

View File

@@ -1,7 +1,7 @@
import type { Locator, Page } from '@playwright/test'
import { Locator, Page } from '@playwright/test'
import path from 'path'
import type {
import {
TemplateInfo,
WorkflowTemplates
} from '../../src/platform/workflow/templates/types/template'

View File

@@ -29,9 +29,9 @@ test.describe('Actionbar', () => {
// Intercept the prompt queue endpoint
let promptNumber = 0
await comfyPage.page.route('**/api/prompt', async (route, req) => {
comfyPage.page.route('**/api/prompt', async (route, req) => {
await new Promise((r) => setTimeout(r, 100))
await route.fulfill({
route.fulfill({
status: 200,
body: JSON.stringify({
prompt_id: promptNumber,

View File

@@ -1,5 +1,5 @@
import type { ComfyPage } from '../fixtures/ComfyPage'
import {
ComfyPage,
comfyExpect as expect,
comfyPageFixture as test
} from '../fixtures/ComfyPage'

View File

@@ -1,5 +1,4 @@
import type { Page } from '@playwright/test'
import { expect } from '@playwright/test'
import { Page, expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'

View File

@@ -1,5 +1,4 @@
import type { Locator } from '@playwright/test'
import { expect } from '@playwright/test'
import { Locator, expect } from '@playwright/test'
import type { Keybinding } from '../../src/schemas/keyBindingSchema'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import type { SettingParams } from '../../src/platform/settings/types'
import { SettingParams } from '../../src/platform/settings/types'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
test.describe('Topbar commands', () => {

View File

@@ -1,7 +1,6 @@
import { expect } from '@playwright/test'
import type { ComfyPage } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { ComfyPage, comfyPageFixture as test } from '../fixtures/ComfyPage'
import type { NodeReference } from '../fixtures/utils/litegraphUtils'
test.describe('Group Node', () => {

View File

@@ -1,13 +1,12 @@
import type { Locator } from '@playwright/test'
import { expect } from '@playwright/test'
import type { Position } from '@vueuse/core'
import { Locator, expect } from '@playwright/test'
import { Position } from '@vueuse/core'
import {
type ComfyPage,
comfyPageFixture as test,
testComfySnapToGridGridSize
} from '../fixtures/ComfyPage'
import type { NodeReference } from '../fixtures/utils/litegraphUtils'
import { type NodeReference } from '../fixtures/utils/litegraphUtils'
test.describe('Item Interaction', () => {
test('Can select/delete all items', async ({ comfyPage }) => {
@@ -1013,8 +1012,6 @@ test.describe('Canvas Navigation', () => {
test('Shift + mouse wheel should pan canvas horizontally', async ({
comfyPage
}) => {
await comfyPage.setSetting('Comfy.Canvas.MouseWheelScroll', 'panning')
await comfyPage.page.click('canvas')
await comfyPage.nextFrame()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 98 KiB

View File

@@ -1,7 +1,6 @@
import { expect } from '@playwright/test'
import type { ComfyPage } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { ComfyPage, comfyPageFixture as test } from '../fixtures/ComfyPage'
test.describe('Remote COMBO Widget', () => {
const mockOptions = ['d', 'c', 'b', 'a']

View File

@@ -160,9 +160,7 @@ test.describe.skip('Queue sidebar', () => {
comfyPage
}) => {
await comfyPage.nextFrame()
await expect(
comfyPage.menu.queueTab.getGalleryImage(firstImage)
).toBeVisible()
expect(comfyPage.menu.queueTab.getGalleryImage(firstImage)).toBeVisible()
})
test('maintains active gallery item when new tasks are added', async ({
@@ -176,9 +174,7 @@ test.describe.skip('Queue sidebar', () => {
const newTask = comfyPage.menu.queueTab.tasks.getByAltText(newImage)
await newTask.waitFor({ state: 'visible' })
// The active gallery item should still be the initial image
await expect(
comfyPage.menu.queueTab.getGalleryImage(firstImage)
).toBeVisible()
expect(comfyPage.menu.queueTab.getGalleryImage(firstImage)).toBeVisible()
})
test.describe('Gallery navigation', () => {
@@ -200,9 +196,7 @@ test.describe.skip('Queue sidebar', () => {
delay: 256
})
await comfyPage.nextFrame()
await expect(
comfyPage.menu.queueTab.getGalleryImage(end)
).toBeVisible()
expect(comfyPage.menu.queueTab.getGalleryImage(end)).toBeVisible()
})
})
})

View File

@@ -1,5 +1,4 @@
import type { Page } from '@playwright/test'
import { expect } from '@playwright/test'
import { Page, expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import type { SystemStats } from '../../src/schemas/apiSchema'
import { SystemStats } from '../../src/schemas/apiSchema'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
test.describe('Version Mismatch Warnings', () => {

View File

@@ -1,5 +1,5 @@
import path from 'path'
import { Plugin } from 'vite'
import { type Plugin } from 'vite'
interface ShimResult {
code: string

View File

@@ -1,7 +1,7 @@
import glob from 'fast-glob'
import fs from 'fs-extra'
import { dirname, join } from 'node:path'
import { HtmlTagDescriptor, Plugin, normalizePath } from 'vite'
import { type HtmlTagDescriptor, type Plugin, normalizePath } from 'vite'
interface ImportMapSource {
name: string

View File

@@ -5,14 +5,13 @@ import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
import storybook from 'eslint-plugin-storybook'
import unusedImports from 'eslint-plugin-unused-imports'
import pluginVue from 'eslint-plugin-vue'
import { defineConfig } from 'eslint/config'
import globals from 'globals'
import tseslint from 'typescript-eslint'
import vueParser from 'vue-eslint-parser'
const extraFileExtensions = ['.vue']
export default defineConfig([
export default [
{
files: ['src/**/*.{js,mjs,cjs,ts,vue}']
},
{
ignores: [
'src/scripts/*',
@@ -25,49 +24,35 @@ export default defineConfig([
]
},
{
files: ['./**/*.{ts,mts}'],
languageOptions: {
globals: {
...globals.browser,
__COMFYUI_FRONTEND_VERSION__: 'readonly'
},
parser: tseslint.parser,
parserOptions: {
parser: tseslint.parser,
projectService: true,
tsConfigRootDir: import.meta.dirname,
project: ['./tsconfig.json', './tsconfig.eslint.json'],
ecmaVersion: 2020,
sourceType: 'module',
extraFileExtensions
}
}
},
{
files: ['./**/*.vue'],
languageOptions: {
globals: {
...globals.browser,
__COMFYUI_FRONTEND_VERSION__: 'readonly'
},
parser: vueParser,
parserOptions: {
parser: tseslint.parser,
projectService: true,
tsConfigRootDir: import.meta.dirname,
ecmaVersion: 2020,
sourceType: 'module',
extraFileExtensions
extraFileExtensions: ['.vue']
}
}
},
pluginJs.configs.recommended,
tseslint.configs.recommended,
pluginVue.configs['flat/recommended'],
...tseslint.configs.recommended,
...pluginVue.configs['flat/recommended'],
eslintPluginPrettierRecommended,
storybook.configs['flat/recommended'],
{
files: ['src/**/*.vue'],
languageOptions: {
parserOptions: {
parser: tseslint.parser
}
}
},
{
plugins: {
'unused-imports': unusedImports,
// @ts-expect-error Bad types in the plugin
'@intlify/vue-i18n': pluginI18n
},
rules: {
@@ -75,8 +60,6 @@ export default defineConfig([
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/prefer-as-const': 'off',
'@typescript-eslint/consistent-type-imports': 'error',
'@typescript-eslint/no-import-type-side-effects': 'error',
'unused-imports/no-unused-imports': 'error',
'vue/no-v-html': 'off',
// Enforce dark-theme: instead of dark: prefix
@@ -84,7 +67,6 @@ export default defineConfig([
'vue/multi-word-component-names': 'off', // TODO: fix
'vue/no-template-shadow': 'off', // TODO: fix
'vue/one-component-per-file': 'off', // TODO: fix
'vue/require-default-prop': 'off', // TODO: fix -- this one is very worthwhile
// Restrict deprecated PrimeVue components
'no-restricted-imports': [
'error',
@@ -154,13 +136,5 @@ export default defineConfig([
]
}
},
{
files: ['tests-ui/**/*'],
rules: {
'@typescript-eslint/consistent-type-imports': [
'error',
{ disallowTypeAnnotations: false }
]
}
}
])
...storybook.configs['flat/recommended']
]

View File

@@ -25,9 +25,7 @@ const config: KnipConfig = {
'src/types/generatedManagerTypes.ts',
'src/types/comfyRegistryTypes.ts',
// Used by a custom node (that should move off of this)
'src/scripts/ui/components/splitButton.ts',
// Staged for for use with subgraph widget promotion
'src/lib/litegraph/src/widgets/DisconnectedWidget.ts'
'src/scripts/ui/components/splitButton.ts'
],
compilers: {
// https://github.com/webpro-nl/knip/issues/1008#issuecomment-3207756199

View File

@@ -3,13 +3,13 @@ export default {
'./**/*.{ts,tsx,vue,mts}': (stagedFiles) => [
...formatAndEslint(stagedFiles),
'pnpm typecheck'
'vue-tsc --noEmit'
]
}
function formatAndEslint(fileNames) {
return [
`pnpm exec eslint --cache --fix ${fileNames.join(' ')}`,
`pnpm exec prettier --cache --write ${fileNames.join(' ')}`
`eslint --fix ${fileNames.join(' ')}`,
`prettier --write ${fileNames.join(' ')}`
]
}

View File

@@ -1,7 +1,7 @@
{
"name": "@comfyorg/comfyui-frontend",
"private": true,
"version": "1.28.0",
"version": "1.27.4",
"type": "module",
"repository": "https://github.com/Comfy-Org/ComfyUI_frontend",
"homepage": "https://comfy.org",
@@ -14,9 +14,9 @@
"build:types": "nx build --config vite.types.config.mts && node scripts/prepare-types.js",
"zipdist": "node scripts/zipdist.js",
"typecheck": "vue-tsc --noEmit",
"format": "prettier --write './**/*.{js,ts,tsx,vue,mts}' --cache --list-different",
"format": "prettier --write './**/*.{js,ts,tsx,vue,mts}' --cache",
"format:check": "prettier --check './**/*.{js,ts,tsx,vue,mts}' --cache",
"format:no-cache": "prettier --write './**/*.{js,ts,tsx,vue,mts}' --list-different",
"format:no-cache": "prettier --write './**/*.{js,ts,tsx,vue,mts}'",
"format:check:no-cache": "prettier --check './**/*.{js,ts,tsx,vue,mts}'",
"test:browser": "npx nx e2e",
"test:unit": "nx run test tests-ui/tests",
@@ -38,10 +38,10 @@
"build-storybook": "storybook build"
},
"devDependencies": {
"@eslint/js": "^9.35.0",
"@eslint/js": "^9.8.0",
"@iconify-json/lucide": "^1.2.66",
"@iconify/tailwind": "^1.2.0",
"@intlify/eslint-plugin-vue-i18n": "^4.1.0",
"@intlify/eslint-plugin-vue-i18n": "^3.2.0",
"@lobehub/i18n-cli": "^1.25.1",
"@nx/eslint": "21.4.1",
"@nx/playwright": "21.4.1",
@@ -64,11 +64,11 @@
"@vitest/ui": "^3.0.0",
"@vue/test-utils": "^2.4.6",
"eslint": "^9.34.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-storybook": "^9.1.6",
"eslint-plugin-unused-imports": "^4.2.0",
"eslint-plugin-vue": "^10.4.0",
"eslint-config-prettier": "^10.1.2",
"eslint-plugin-prettier": "^5.2.6",
"eslint-plugin-storybook": "^9.1.1",
"eslint-plugin-unused-imports": "^4.1.4",
"eslint-plugin-vue": "^9.27.0",
"fs-extra": "^11.2.0",
"globals": "^15.9.0",
"happy-dom": "^15.11.0",
@@ -76,33 +76,34 @@
"jiti": "2.4.2",
"jsdom": "^26.1.0",
"knip": "^5.62.0",
"kolorist": "^1.8.0",
"lint-staged": "^15.2.7",
"magic-string": "^0.30.19",
"nx": "21.4.1",
"prettier": "^3.3.2",
"storybook": "^9.1.6",
"storybook": "^9.1.1",
"tailwindcss": "^4.1.12",
"tailwindcss-primeui": "^0.6.1",
"tsx": "^4.15.6",
"tw-animate-css": "^1.3.8",
"typescript": "^5.4.5",
"typescript-eslint": "^8.44.0",
"typescript-eslint": "^8.42.0",
"unplugin-icons": "^0.22.0",
"unplugin-vue-components": "^0.28.0",
"uuid": "^11.1.0",
"vite": "^5.4.19",
"vite-plugin-dts": "^4.5.4",
"vite-plugin-dts": "^4.3.0",
"vite-plugin-html": "^3.2.2",
"vite-plugin-vue-devtools": "^7.7.6",
"vitest": "^3.2.4",
"vue-eslint-parser": "^10.2.0",
"vue-tsc": "^3.0.7",
"vue-tsc": "^2.1.10",
"zip-dir": "^2.0.0",
"zod-to-json-schema": "^3.24.1"
},
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"@atlaskit/pragmatic-drag-and-drop": "^1.3.1",
"@comfyorg/comfyui-electron-types": "0.4.73-0",
"@comfyorg/comfyui-electron-types": "^0.4.72",
"@iconify/json": "^2.2.380",
"@primeuix/forms": "0.0.2",
"@primeuix/styled": "0.3.2",

1068
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,6 @@ import * as fs from 'fs'
import { comfyPageFixture as test } from '../browser_tests/fixtures/ComfyPage'
import { CORE_MENU_COMMANDS } from '../src/constants/coreMenuCommands'
import { DESKTOP_DIALOGS } from '../src/constants/desktopDialogs'
import { SERVER_CONFIG_ITEMS } from '../src/constants/serverConfig'
import type { FormItem, SettingParams } from '../src/platform/settings/types'
import type { ComfyCommandImpl } from '../src/stores/commandStore'
@@ -132,23 +131,6 @@ test('collect-i18n-general', async ({ comfyPage }) => {
])
)
// Desktop Dialogs
const allDesktopDialogsLocale = Object.fromEntries(
Object.values(DESKTOP_DIALOGS).map((dialog) => [
normalizeI18nKey(dialog.id),
{
title: dialog.title,
message: dialog.message,
buttons: Object.fromEntries(
dialog.buttons.map((button) => [
normalizeI18nKey(button.label),
button.label
])
)
}
])
)
fs.writeFileSync(
localePath,
JSON.stringify(
@@ -162,8 +144,7 @@ test('collect-i18n-general', async ({ comfyPage }) => {
...allSettingCategoriesLocale
},
serverConfigItems: allServerConfigsLocale,
serverConfigCategories: allServerConfigCategoriesLocale,
desktopDialogs: allDesktopDialogsLocale
serverConfigCategories: allServerConfigCategoriesLocale
},
null,
2

View File

@@ -0,0 +1,282 @@
#!/usr/bin/env tsx
import glob from 'fast-glob'
import { cyan, green, magenta, red, yellow } from 'kolorist'
import MagicString from 'magic-string'
import { spawn } from 'node:child_process'
import fs from 'node:fs'
import path from 'node:path'
interface ImportError {
file: string
line: number
column: number
importName: string
isVue: boolean
}
interface FileToFix {
ms: MagicString
imports: Array<{
name: string
line: number
column: number
}>
isVue: boolean
}
const parseVueTscOutput = (output: string): ImportError[] => {
const errors: ImportError[] = []
const lines = output.split('\n')
// Pattern for verbatim module syntax errors
// Example: src/components/actionbar/ComfyActionbar.vue(25,10): error TS1484: 'Ref' is a type...
const errorPattern =
/^(.+?)\((\d+),(\d+)\): error TS(1484|1205): '([^']+)' is a type/
for (const line of lines) {
const match = errorPattern.exec(line)
if (match) {
const [, filePath, lineNum, colNum, , importName] = match
errors.push({
file: path.resolve(filePath),
line: parseInt(lineNum, 10),
column: parseInt(colNum, 10),
importName,
isVue: filePath.endsWith('.vue')
})
}
}
return errors
}
const runVueTsc = (tsconfigPath: string): Promise<string> => {
return new Promise((resolve, reject) => {
const vueTscPath = path.join(
process.cwd(),
'node_modules',
'.bin',
'vue-tsc'
)
const child = spawn(vueTscPath, ['--noEmit', '-p', tsconfigPath], {
cwd: process.cwd(),
shell: true
})
let output = ''
let errorOutput = ''
child.stdout.on('data', (data) => {
output += data.toString()
})
child.stderr.on('data', (data) => {
errorOutput += data.toString()
})
child.on('close', (code) => {
// vue-tsc returns non-zero when there are type errors, which is expected
// We want the error output which contains the diagnostics
resolve(errorOutput || output)
})
child.on('error', (err) => {
reject(err)
})
})
}
const findImportInLine = (line: string, importName: string): number => {
// Look for the import name in various import patterns
const patterns = [
// import { Name } from
new RegExp(`\\b${importName}\\b(?=[^']*['"])`),
// import Name from (default import)
new RegExp(`import\\s+${importName}\\s+from`),
// import { Something as Name } from
new RegExp(`as\\s+${importName}\\b`),
// export { Name } from
new RegExp(`export\\s*\\{[^}]*\\b${importName}\\b`)
]
for (const pattern of patterns) {
const match = pattern.exec(line)
if (match) {
return match.index!
}
}
// Fallback: simple indexOf
return line.indexOf(importName)
}
const fixImports = async (
errors: ImportError[]
): Promise<Map<string, FileToFix>> => {
const fileMap = new Map<string, FileToFix>()
for (const error of errors) {
if (!fileMap.has(error.file)) {
const content = fs.readFileSync(error.file, 'utf-8')
fileMap.set(error.file, {
ms: new MagicString(content),
imports: [],
isVue: error.isVue
})
}
const file = fileMap.get(error.file)!
file.imports.push({
name: error.importName,
line: error.line,
column: error.column
})
}
// Apply fixes
for (const [filePath, fileData] of fileMap) {
const lines = fileData.ms.original.split('\n')
for (const imp of fileData.imports) {
const lineIndex = imp.line - 1
if (lineIndex >= 0 && lineIndex < lines.length) {
const line = lines[lineIndex]
// Find the actual position of the import name in the line
const nameIndex = findImportInLine(line, imp.name)
if (nameIndex >= 0) {
// Calculate the absolute position in the file
let absolutePos = 0
for (let i = 0; i < lineIndex; i++) {
absolutePos += lines[i].length + 1 // +1 for newline
}
absolutePos += nameIndex
// Check if 'type' isn't already there
const beforeText = fileData.ms.original.slice(
Math.max(0, absolutePos - 5),
absolutePos
)
if (!beforeText.includes('type ')) {
fileData.ms.appendLeft(absolutePos, 'type ')
}
}
}
}
}
return fileMap
}
const main = async () => {
const args = process.argv.slice(2)
const isDry = args.includes('--dry')
const helpRequested = args.includes('--help') || args.includes('-h')
if (helpRequested) {
console.log(cyan('🔧 Fix Vue Verbatim Module Syntax'))
console.log()
console.log(
'Usage: npx tsx scripts/fix-vue-verbatim-module-syntax.ts [options] [tsconfig]'
)
console.log()
console.log('Options:')
console.log(
' --dry Run in dry mode (show what would be fixed without modifying files)'
)
console.log(' --help Show this help message')
console.log()
console.log('Examples:')
console.log(' npx tsx scripts/fix-vue-verbatim-module-syntax.ts')
console.log(' npx tsx scripts/fix-vue-verbatim-module-syntax.ts --dry')
console.log(
' npx tsx scripts/fix-vue-verbatim-module-syntax.ts tsconfig.app.json'
)
return
}
// Find tsconfig path argument
let tsconfigPath = 'tsconfig.json'
for (const arg of args) {
if (!arg.startsWith('--') && arg.endsWith('.json')) {
tsconfigPath = arg
break
}
}
console.log(
cyan(
'🔧 Fixing verbatim module syntax errors in TypeScript and Vue files...'
)
)
console.log(magenta(`Using: ${tsconfigPath}`))
if (isDry) {
console.log(yellow('Dry run mode - no files will be modified'))
}
console.log()
try {
// Run vue-tsc to get all errors
console.log(cyan('Running vue-tsc to detect errors...'))
const output = await runVueTsc(tsconfigPath)
// Parse the errors
const errors = parseVueTscOutput(output)
if (errors.length === 0) {
console.log(green('✨ No verbatim module syntax errors found!'))
return
}
console.log(
yellow(`Found ${errors.length} import(s) that need 'type' modifier`)
)
console.log()
// Fix the imports
const fixes = await fixImports(errors)
const cwd = process.cwd()
for (const [filePath, fileData] of fixes) {
if (!isDry) {
fs.writeFileSync(filePath, fileData.ms.toString())
}
const fileType = fileData.isVue ? '(Vue)' : '(TS)'
console.log(cyan(`${path.relative(cwd, filePath)} ${fileType}`))
const importNames = fileData.imports.map((imp) => imp.name)
console.log(
' ',
isDry ? 'Would add type to:' : 'Adding type to:',
importNames.map((name) => magenta(name)).join(', ')
)
console.log()
}
const fileCount = fixes.size
const importCount = Array.from(fixes.values()).reduce(
(sum, f) => sum + f.imports.length,
0
)
console.log(
green(
`${isDry ? 'Would fix' : 'Fixed'} ${importCount} import${importCount === 1 ? '' : 's'} in ${fileCount} file${fileCount === 1 ? '' : 's'}`
)
)
} catch (error) {
console.error(red('Error:'), error instanceof Error ? error.message : error)
process.exit(1)
}
}
// Run if executed directly
main().catch((error) => {
console.error(red('Unhandled error:'), error)
process.exit(1)
})
export { main as fixVerbatimModuleSyntax }

View File

@@ -1,17 +0,0 @@
/* Inter Font Family */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-latin-normal.woff2') format('woff2');
font-weight: 100 900;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-latin-italic.woff2') format('woff2');
font-weight: 100 900;
font-style: italic;
font-display: swap;
}

View File

@@ -1,6 +1,5 @@
@layer theme, base, primevue, components, utilities;
@import './fonts.css';
@import 'tailwindcss/theme' layer(theme);
@import 'tailwindcss/utilities' layer(utilities);
@import 'tw-animate-css';
@@ -53,20 +52,15 @@
--text-xxs: 0.625rem;
--text-xxs--line-height: calc(1 / 0.625);
/* Font Families */
--font-inter: 'Inter', sans-serif;
/* Palette Colors */
--color-charcoal-100: #55565e;
--color-charcoal-200: #494a50;
--color-charcoal-300: #3c3d42;
--color-charcoal-400: #313235;
--color-charcoal-500: #2d2e32;
--color-charcoal-600: #262729;
--color-charcoal-700: #202121;
--color-charcoal-800: #171718;
--color-neutral-550: #636363;
--color-charcoal-100: #171718;
--color-charcoal-200: #202121;
--color-charcoal-300: #262729;
--color-charcoal-400: #2d2e32;
--color-charcoal-500: #313235;
--color-charcoal-600: #3c3d42;
--color-charcoal-700: #494a50;
--color-charcoal-800: #55565e;
--color-stone-100: #444444;
--color-stone-200: #828282;
@@ -105,16 +99,12 @@
--color-danger-100: #c02323;
--color-danger-200: #d62952;
--color-coral-red-600: #973a40;
--color-coral-red-500: #c53f49;
--color-coral-red-400: #dd424e;
--color-bypass: #6a246a;
--color-bypass: #6A246A;
--color-error: #962a2a;
--color-blue-selection: rgb(from var(--color-blue-100) r g b / 0.3);
--color-node-hover-100: rgb(from var(--color-charcoal-100) r g b/ 0.15);
--color-node-hover-200: rgb(from var(--color-charcoal-100) r g b/ 0.1);
--color-blue-selection: rgb( from var(--color-blue-100) r g b / 0.3);
--color-node-hover-100: rgb( from var(--color-charcoal-800) r g b/ 0.15);
--color-node-hover-200: rgb(from var(--color-charcoal-800) r g b/ 0.1);
--color-modal-tag: rgb(from var(--color-gray-400) r g b/ 0.4);
/* PrimeVue pulled colors */
@@ -127,10 +117,10 @@
}
@theme inline {
--color-node-component-surface: var(--color-charcoal-600);
--color-node-component-surface: var(--color-charcoal-300);
--color-node-component-surface-highlight: var(--color-slate-100);
--color-node-component-surface-hovered: var(--color-charcoal-400);
--color-node-component-surface-selected: var(--color-charcoal-200);
--color-node-component-surface-hovered: var(--color-charcoal-500);
--color-node-component-surface-selected: var(--color-charcoal-700);
--color-node-stroke: var(--color-stone-100);
}
@@ -142,7 +132,7 @@
@utility scrollbar-hide {
scrollbar-width: none;
&::-webkit-scrollbar {
&::-webkit-scrollbar {
width: 1px;
}
&::-webkit-scrollbar-thumb {

View File

@@ -21,8 +21,7 @@
<script setup lang="ts">
import Button from 'primevue/button'
import type { CSSProperties } from 'vue'
import { computed, watchEffect } from 'vue'
import { type CSSProperties, computed, watchEffect } from 'vue'
import { useSettingStore } from '@/platform/settings/settingStore'
import { app } from '@/scripts/app'

View File

@@ -22,8 +22,15 @@ import {
} from '@vueuse/core'
import { clamp } from 'es-toolkit/compat'
import Panel from 'primevue/panel'
import type { Ref } from 'vue'
import { computed, inject, nextTick, onMounted, ref, watch } from 'vue'
import {
type Ref,
computed,
inject,
nextTick,
onMounted,
ref,
watch
} from 'vue'
import { useSettingStore } from '@/platform/settings/settingStore'

View File

@@ -26,8 +26,7 @@
import { useElementHover, useEventListener } from '@vueuse/core'
import type { IDisposable } from '@xterm/xterm'
import Button from 'primevue/button'
import type { Ref } from 'vue'
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { type Ref, computed, onMounted, onUnmounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useTerminal } from '@/composables/bottomPanelTabs/useTerminal'
@@ -47,7 +46,7 @@ const hasSelection = ref(false)
const isHovered = useElementHover(rootEl)
const terminalData = useTerminal(terminalEl)
emit('created', terminalData, ref(rootEl))
emit('created', terminalData, rootEl)
const { terminal } = terminalData
let selectionDisposable: IDisposable | undefined

View File

@@ -3,9 +3,8 @@
</template>
<script setup lang="ts">
import type { IDisposable } from '@xterm/xterm'
import type { Ref } from 'vue'
import { onMounted, onUnmounted } from 'vue'
import { type IDisposable } from '@xterm/xterm'
import { type Ref, onMounted, onUnmounted } from 'vue'
import type { useTerminal } from '@/composables/bottomPanelTabs/useTerminal'
import { electronAPI } from '@/utils/envUtil'

View File

@@ -15,11 +15,14 @@
import { until } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import ProgressSpinner from 'primevue/progressspinner'
import type { Ref } from 'vue'
import { onMounted, onUnmounted, ref } from 'vue'
import { type Ref, onMounted, onUnmounted, ref } from 'vue'
import type { useTerminal } from '@/composables/bottomPanelTabs/useTerminal'
import type { LogEntry, LogsWsMessage, TerminalSize } from '@/schemas/apiSchema'
import {
type LogEntry,
type LogsWsMessage,
type TerminalSize
} from '@/schemas/apiSchema'
import { api } from '@/scripts/api'
import { useExecutionStore } from '@/stores/executionStore'

View File

@@ -47,8 +47,7 @@
<script setup lang="ts">
import InputText from 'primevue/inputtext'
import type { MenuState } from 'primevue/menu'
import Menu from 'primevue/menu'
import Menu, { type MenuState } from 'primevue/menu'
import type { MenuItem } from 'primevue/menuitem'
import Tag from 'primevue/tag'
import { computed, nextTick, ref } from 'vue'

View File

@@ -7,7 +7,7 @@
<InputText
v-else
ref="inputRef"
v-model:model-value="inputValue"
v-model:modelValue="inputValue"
v-focus
type="text"
size="small"

View File

@@ -17,7 +17,7 @@
<script setup lang="ts">
import { onBeforeUnmount } from 'vue'
import type { CustomExtension, VueExtension } from '@/types/extensionTypes'
import { type CustomExtension, type VueExtension } from '@/types/extensionTypes'
const props = defineProps<{
extension: VueExtension | CustomExtension

View File

@@ -21,7 +21,7 @@
<component
:is="markRaw(getFormComponent(props.item))"
:id="props.id"
v-model:model-value="formValue"
v-model:modelValue="formValue"
:aria-labelledby="`${props.id}-label`"
v-bind="getFormAttrs(props.item)"
/>
@@ -44,7 +44,7 @@ import FormRadioGroup from '@/components/common/FormRadioGroup.vue'
import InputKnob from '@/components/common/InputKnob.vue'
import InputSlider from '@/components/common/InputSlider.vue'
import UrlInput from '@/components/common/UrlInput.vue'
import type { FormItem } from '@/platform/settings/types'
import { type FormItem } from '@/platform/settings/types'
const formValue = defineModel<any>('formValue')
const props = defineProps<{

View File

@@ -10,7 +10,7 @@
class="absolute inset-0"
/>
<img
v-if="cachedSrc"
v-show="isImageLoaded"
ref="imageRef"
:src="cachedSrc"
:alt="alt"
@@ -77,8 +77,8 @@ const shouldLoad = computed(() => isIntersecting.value)
watch(
shouldLoad,
async (shouldLoadVal) => {
if (shouldLoadVal && src && !cachedSrc.value && !hasError.value) {
async (shouldLoad) => {
if (shouldLoad && src && !cachedSrc.value && !hasError.value) {
try {
const cachedMedia = await getCachedMedia(src)
if (cachedMedia.error) {
@@ -93,7 +93,7 @@ watch(
console.warn('Failed to load cached media:', error)
cachedSrc.value = src
}
} else if (!shouldLoadVal) {
} else if (!shouldLoad) {
if (cachedSrc.value?.startsWith('blob:')) {
releaseUrl(src)
}

View File

@@ -32,7 +32,7 @@
import Button from 'primevue/button'
import ProgressSpinner from 'primevue/progressspinner'
import type { PrimeVueSeverity } from '@/types/primeVueTypes'
import { type PrimeVueSeverity } from '@/types/primeVueTypes'
const {
disabled,

View File

@@ -1,7 +1,7 @@
<template>
<Tree
v-model:expanded-keys="expandedKeys"
v-model:selection-keys="selectionKeys"
v-model:expandedKeys="expandedKeys"
v-model:selectionKeys="selectionKeys"
class="tree-explorer py-0 px-2 2xl:px-4"
:class="props.class"
:value="renderedRoot.children"

View File

@@ -9,8 +9,10 @@ import { createI18n } from 'vue-i18n'
import EditableText from '@/components/common/EditableText.vue'
import TreeExplorerTreeNode from '@/components/common/TreeExplorerTreeNode.vue'
import type { RenderedTreeExplorerNode } from '@/types/treeExplorerTypes'
import { InjectKeyHandleEditLabelFunction } from '@/types/treeExplorerTypes'
import {
InjectKeyHandleEditLabelFunction,
type RenderedTreeExplorerNode
} from '@/types/treeExplorerTypes'
// Create a mock i18n instance
const i18n = createI18n({

View File

@@ -1,5 +1,4 @@
import type { VueWrapper } from '@vue/test-utils'
import { mount } from '@vue/test-utils'
import { VueWrapper, mount } from '@vue/test-utils'
import { createPinia } from 'pinia'
import Button from 'primevue/button'
import PrimeVue from 'primevue/config'

View File

@@ -148,7 +148,7 @@ import { useI18n } from 'vue-i18n'
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
import { COMFY_PLATFORM_BASE_URL } from '@/config/comfyApi'
import type { SignInData, SignUpData } from '@/schemas/signInSchema'
import { type SignInData, type SignUpData } from '@/schemas/signInSchema'
import { isInChina } from '@/utils/networkUtil'
import ApiKeyForm from './signin/ApiKeyForm.vue'

View File

@@ -17,8 +17,7 @@
</template>
<script setup lang="ts">
import type { FormSubmitEvent } from '@primevue/forms'
import { Form } from '@primevue/forms'
import { Form, type FormSubmitEvent } from '@primevue/forms'
import { zodResolver } from '@primevue/forms/resolvers/zod'
import Button from 'primevue/button'
import { ref } from 'vue'

View File

@@ -16,7 +16,7 @@
<div class="flex flex-1 relative overflow-hidden">
<ManagerNavSidebar
v-if="isSideNavOpen"
v-model:selected-tab="selectedTab"
v-model:selectedTab="selectedTab"
:tabs="tabs"
/>
<div
@@ -57,9 +57,9 @@
</IconButton>
</div>
<RegistrySearchBar
v-model:search-query="searchQuery"
v-model:search-mode="searchMode"
v-model:sort-field="sortField"
v-model:searchQuery="searchQuery"
v-model:searchMode="searchMode"
v-model:sortField="sortField"
:search-results="searchResults"
:suggestions="suggestions"
:is-missing-tab="isMissingTab"
@@ -160,7 +160,7 @@ import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import { useComfyRegistryStore } from '@/stores/comfyRegistryStore'
import type { TabItem } from '@/types/comfyManagerTypes'
import { ManagerTab } from '@/types/comfyManagerTypes'
import type { components } from '@/types/comfyRegistryTypes'
import { type components } from '@/types/comfyRegistryTypes'
const { initialTab } = defineProps<{
initialTab?: ManagerTab

View File

@@ -169,9 +169,9 @@ import { useI18n } from 'vue-i18n'
import ContentDivider from '@/components/common/ContentDivider.vue'
import { useConflictDetection } from '@/composables/useConflictDetection'
import type {
ConflictDetail,
ConflictDetectionResult
import {
type ConflictDetail,
type ConflictDetectionResult
} from '@/types/conflictDetectionTypes'
import { getConflictMessage } from '@/utils/conflictMessageUtil'

View File

@@ -19,7 +19,7 @@
import Message from 'primevue/message'
import { computed, inject } from 'vue'
import type { components } from '@/types/comfyRegistryTypes'
import { type components } from '@/types/comfyRegistryTypes'
import { ImportFailedKey } from '@/types/importFailedTypes'
type PackVersionStatus = components['schemas']['NodeVersionStatus']

View File

@@ -1,5 +1,4 @@
import type { VueWrapper } from '@vue/test-utils'
import { mount } from '@vue/test-utils'
import { VueWrapper, mount } from '@vue/test-utils'
import { createPinia } from 'pinia'
import PrimeVue from 'primevue/config'
import Tooltip from 'primevue/tooltip'

View File

@@ -1,5 +1,4 @@
import type { VueWrapper } from '@vue/test-utils'
import { mount } from '@vue/test-utils'
import { VueWrapper, mount } from '@vue/test-utils'
import { createPinia } from 'pinia'
import Button from 'primevue/button'
import PrimeVue from 'primevue/config'

View File

@@ -93,8 +93,8 @@ import VerifiedIcon from '@/components/icons/VerifiedIcon.vue'
import { useConflictDetection } from '@/composables/useConflictDetection'
import { useComfyRegistryService } from '@/services/comfyRegistryService'
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import type { components } from '@/types/comfyRegistryTypes'
import type { components as ManagerComponents } from '@/types/generatedManagerTypes'
import { type components } from '@/types/comfyRegistryTypes'
import { type components as ManagerComponents } from '@/types/generatedManagerTypes'
import { getJoinedConflictMessages } from '@/utils/conflictMessageUtil'
import { isSemVer } from '@/utils/formatUtil'

View File

@@ -1,5 +1,4 @@
import type { VueWrapper } from '@vue/test-utils'
import { mount } from '@vue/test-utils'
import { VueWrapper, mount } from '@vue/test-utils'
import { createPinia } from 'pinia'
import PrimeVue from 'primevue/config'
import ToggleSwitch from 'primevue/toggleswitch'

View File

@@ -39,7 +39,7 @@ import { useDialogService } from '@/services/dialogService'
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import { useConflictDetectionStore } from '@/stores/conflictDetectionStore'
import type { components } from '@/types/comfyRegistryTypes'
import type { components as ManagerComponents } from '@/types/generatedManagerTypes'
import { type components as ManagerComponents } from '@/types/generatedManagerTypes'
const TOGGLE_DEBOUNCE_MS = 256

View File

@@ -31,11 +31,13 @@ import { useConflictDetection } from '@/composables/useConflictDetection'
import { t } from '@/i18n'
import { useDialogService } from '@/services/dialogService'
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import type { ButtonSize } from '@/types/buttonTypes'
import { type ButtonSize } from '@/types/buttonTypes'
import type { components } from '@/types/comfyRegistryTypes'
import type { ConflictDetectionResult } from '@/types/conflictDetectionTypes'
import type { ConflictDetail } from '@/types/conflictDetectionTypes'
import type { components as ManagerComponents } from '@/types/generatedManagerTypes'
import {
type ConflictDetail,
type ConflictDetectionResult
} from '@/types/conflictDetectionTypes'
import { type components as ManagerComponents } from '@/types/generatedManagerTypes'
type NodePack = components['schemas']['Node']

View File

@@ -17,9 +17,9 @@
<script setup lang="ts">
import IconTextButton from '@/components/button/IconTextButton.vue'
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import type { ButtonSize } from '@/types/buttonTypes'
import { type ButtonSize } from '@/types/buttonTypes'
import type { components } from '@/types/comfyRegistryTypes'
import type { components as ManagerComponents } from '@/types/generatedManagerTypes'
import { type components as ManagerComponents } from '@/types/generatedManagerTypes'
type NodePack = components['schemas']['Node']

View File

@@ -75,7 +75,7 @@ import { useImportFailedDetection } from '@/composables/useImportFailedDetection
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import { useConflictDetectionStore } from '@/stores/conflictDetectionStore'
import { IsInstallingKey } from '@/types/comfyManagerTypes'
import type { components } from '@/types/comfyRegistryTypes'
import { type components } from '@/types/comfyRegistryTypes'
import type { ConflictDetectionResult } from '@/types/conflictDetectionTypes'
import { ImportFailedKey } from '@/types/importFailedTypes'

View File

@@ -50,7 +50,7 @@ import PackUninstallButton from '@/components/dialog/content/manager/button/Pack
import PackIcon from '@/components/dialog/content/manager/packIcon/PackIcon.vue'
import { useConflictDetection } from '@/composables/useConflictDetection'
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import type { components } from '@/types/comfyRegistryTypes'
import { type components } from '@/types/comfyRegistryTypes'
import type { ConflictDetail } from '@/types/conflictDetectionTypes'
import { ImportFailedKey } from '@/types/importFailedTypes'

View File

@@ -67,7 +67,7 @@ import { usePacksSelection } from '@/composables/nodePack/usePacksSelection'
import { usePacksStatus } from '@/composables/nodePack/usePacksStatus'
import { useConflictDetection } from '@/composables/useConflictDetection'
import { useComfyRegistryStore } from '@/stores/comfyRegistryStore'
import type { components } from '@/types/comfyRegistryTypes'
import { type components } from '@/types/comfyRegistryTypes'
import type { ConflictDetail } from '@/types/conflictDetectionTypes'
import { ImportFailedKey } from '@/types/importFailedTypes'

View File

@@ -48,7 +48,7 @@ import { computed, inject, ref, watchEffect } from 'vue'
import DescriptionTabPanel from '@/components/dialog/content/manager/infoPanel/tabs/DescriptionTabPanel.vue'
import NodesTabPanel from '@/components/dialog/content/manager/infoPanel/tabs/NodesTabPanel.vue'
import WarningTabPanel from '@/components/dialog/content/manager/infoPanel/tabs/WarningTabPanel.vue'
import type { components } from '@/types/comfyRegistryTypes'
import { type components } from '@/types/comfyRegistryTypes'
import type { ConflictDetectionResult } from '@/types/conflictDetectionTypes'
import { ImportFailedKey } from '@/types/importFailedTypes'

View File

@@ -8,7 +8,7 @@
</template>
<script setup lang="ts">
const { value = 'N/A', label } = defineProps<{
const { value = 'N/A', label = 'N/A' } = defineProps<{
label: string
value?: string | number
}>()

View File

@@ -29,7 +29,7 @@ import { useI18n } from 'vue-i18n'
import InfoTextSection, {
type TextSection
} from '@/components/dialog/content/manager/infoPanel/InfoTextSection.vue'
import type { components } from '@/types/comfyRegistryTypes'
import { type components } from '@/types/comfyRegistryTypes'
import { isValidUrl } from '@/utils/formatUtil'
const { t } = useI18n()

View File

@@ -34,7 +34,7 @@ import { computed, ref, shallowRef, useId } from 'vue'
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
import NodePreview from '@/components/node/NodePreview.vue'
import { useComfyRegistryStore } from '@/stores/comfyRegistryStore'
import type { components, operations } from '@/types/comfyRegistryTypes'
import { type components, type operations } from '@/types/comfyRegistryTypes'
import { registryToFrontendV2NodeDef } from '@/utils/mapperUtil'
type ListComfyNodesResponse =

View File

@@ -29,8 +29,8 @@ import { computed } from 'vue'
import { useImportFailedDetection } from '@/composables/useImportFailedDetection'
import { t } from '@/i18n'
import type { components } from '@/types/comfyRegistryTypes'
import type { ConflictDetectionResult } from '@/types/conflictDetectionTypes'
import { type components } from '@/types/comfyRegistryTypes'
import { type ConflictDetectionResult } from '@/types/conflictDetectionTypes'
import { getConflictMessage } from '@/utils/conflictMessageUtil'
const { nodePack, conflictResult } = defineProps<{

View File

@@ -37,7 +37,7 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import type { components } from '@/types/comfyRegistryTypes'
import { type components } from '@/types/comfyRegistryTypes'
const DEFAULT_BANNER = '/assets/images/fallback-gradient-avatar.svg'

View File

@@ -37,7 +37,7 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import type { components } from '@/types/comfyRegistryTypes'
import { type components } from '@/types/comfyRegistryTypes'
const DEFAULT_BANNER = '/assets/images/fallback-gradient-avatar.svg'

View File

@@ -19,7 +19,7 @@
<script setup lang="ts">
import PackIcon from '@/components/dialog/content/manager/packIcon/PackIcon.vue'
import type { components } from '@/types/comfyRegistryTypes'
import { type components } from '@/types/comfyRegistryTypes'
const {
nodePacks,

View File

@@ -41,12 +41,12 @@
<div class="flex mt-3 text-sm">
<div class="flex gap-6 ml-1">
<SearchFilterDropdown
v-model:model-value="searchMode"
v-model:modelValue="searchMode"
:options="filterOptions"
:label="$t('g.filter')"
/>
<SearchFilterDropdown
v-model:model-value="sortField"
v-model:modelValue="sortField"
:options="availableSortOptions"
:label="$t('g.sort')"
/>
@@ -62,8 +62,9 @@
<script setup lang="ts">
import { stubTrue } from 'es-toolkit/compat'
import type { AutoCompleteOptionSelectEvent } from 'primevue/autocomplete'
import AutoComplete from 'primevue/autocomplete'
import AutoComplete, {
type AutoCompleteOptionSelectEvent
} from 'primevue/autocomplete'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
@@ -76,7 +77,7 @@ import {
type SearchOption,
SortableAlgoliaField
} from '@/types/comfyManagerTypes'
import type { components } from '@/types/comfyRegistryTypes'
import { type components } from '@/types/comfyRegistryTypes'
import type {
QuerySuggestion,
SearchMode,

View File

@@ -1,5 +1,4 @@
import type { VueWrapper } from '@vue/test-utils'
import { mount } from '@vue/test-utils'
import { VueWrapper, mount } from '@vue/test-utils'
import { createPinia } from 'pinia'
import PrimeVue from 'primevue/config'
import { describe, expect, it } from 'vitest'

View File

@@ -96,8 +96,8 @@ import Message from 'primevue/message'
import ProgressSpinner from 'primevue/progressspinner'
import { computed, ref } from 'vue'
import type { AuditLog } from '@/services/customerEventsService'
import {
type AuditLog,
EventType,
useCustomerEventsService
} from '@/services/customerEventsService'

View File

@@ -13,7 +13,7 @@
import Tag from 'primevue/tag'
import { computed } from 'vue'
import type { KeyComboImpl } from '@/stores/keybindingStore'
import { KeyComboImpl } from '@/stores/keybindingStore'
const { keyCombo, isModified = false } = defineProps<{
keyCombo: KeyComboImpl

View File

@@ -79,8 +79,7 @@
</template>
<script setup lang="ts">
import type { FormSubmitEvent } from '@primevue/forms'
import { Form } from '@primevue/forms'
import { Form, type FormSubmitEvent } from '@primevue/forms'
import { zodResolver } from '@primevue/forms/resolvers/zod'
import Button from 'primevue/button'
import InputText from 'primevue/inputtext'

View File

@@ -1,6 +1,5 @@
import { Form } from '@primevue/forms'
import type { VueWrapper } from '@vue/test-utils'
import { mount } from '@vue/test-utils'
import { VueWrapper, mount } from '@vue/test-utils'
import Button from 'primevue/button'
import PrimeVue from 'primevue/config'
import InputText from 'primevue/inputtext'

View File

@@ -71,8 +71,7 @@
</template>
<script setup lang="ts">
import type { FormSubmitEvent } from '@primevue/forms'
import { Form } from '@primevue/forms'
import { Form, type FormSubmitEvent } from '@primevue/forms'
import { zodResolver } from '@primevue/forms/resolvers/zod'
import Button from 'primevue/button'
import InputText from 'primevue/inputtext'

View File

@@ -59,8 +59,7 @@
</template>
<script setup lang="ts">
import type { FormSubmitEvent } from '@primevue/forms'
import { Form, FormField } from '@primevue/forms'
import { Form, FormField, type FormSubmitEvent } from '@primevue/forms'
import { zodResolver } from '@primevue/forms/resolvers/zod'
import Button from 'primevue/button'
import Checkbox from 'primevue/checkbox'

View File

@@ -4,7 +4,7 @@
class="px-4 py-2 flex items-center"
>
<TabMenu
v-model:active-index="activeTabIndex"
v-model:activeIndex="activeTabIndex"
:model="tabs"
class="w-full border-none"
:pt="{

View File

@@ -34,7 +34,7 @@ const updateWidgets = () => {
const widget = widgetState.widget
// Early exit for non-visible widgets
if (!widget.isVisible() || !widgetState.active) {
if (!widget.isVisible()) {
widgetState.visible = false
continue
}

View File

@@ -96,6 +96,7 @@ import NodeSearchboxPopover from '@/components/searchbox/NodeSearchBoxPopover.vu
import SideToolbar from '@/components/sidebar/SideToolbar.vue'
import SecondRowWorkflowTabs from '@/components/topbar/SecondRowWorkflowTabs.vue'
import { useChainCallback } from '@/composables/functional/useChainCallback'
import { useCanvasInteractions } from '@/composables/graph/useCanvasInteractions'
import { useViewportCulling } from '@/composables/graph/useViewportCulling'
import { useVueNodeLifecycle } from '@/composables/graph/useVueNodeLifecycle'
import { useNodeBadge } from '@/composables/node/useNodeBadge'
@@ -117,7 +118,6 @@ import { useWorkflowAutoSave } from '@/platform/workflow/persistence/composables
import { useWorkflowPersistence } from '@/platform/workflow/persistence/composables/useWorkflowPersistence'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { SelectedNodeIdsKey } from '@/renderer/core/canvas/injectionKeys'
import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions'
import TransformPane from '@/renderer/core/layout/transform/TransformPane.vue'
import MiniMap from '@/renderer/extensions/minimap/MiniMap.vue'
import VueGraphNode from '@/renderer/extensions/vueNodes/components/LGraphNode.vue'

View File

@@ -124,11 +124,11 @@ import ButtonGroup from 'primevue/buttongroup'
import { computed, onBeforeUnmount, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { useCanvasInteractions } from '@/composables/graph/useCanvasInteractions'
import { useZoomControls } from '@/composables/useZoomControls'
import { LiteGraph } from '@/lib/litegraph/src/litegraph'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions'
import { useMinimap } from '@/renderer/extensions/minimap/composables/useMinimap'
import { useCommandStore } from '@/stores/commandStore'
import { useWorkspaceStore } from '@/stores/workspaceStore'

View File

@@ -5,12 +5,12 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
import { createI18n } from 'vue-i18n'
import SelectionToolbox from '@/components/graph/SelectionToolbox.vue'
import { useCanvasInteractions } from '@/composables/graph/useCanvasInteractions'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions'
import { useExtensionService } from '@/services/extensionService'
// Mock the composables and services
vi.mock('@/renderer/core/canvas/useCanvasInteractions', () => ({
vi.mock('@/composables/graph/useCanvasInteractions', () => ({
useCanvasInteractions: vi.fn(() => ({
handleWheel: vi.fn()
}))

View File

@@ -60,9 +60,9 @@ import MaskEditorButton from '@/components/graph/selectionToolbox/MaskEditorButt
import RefreshSelectionButton from '@/components/graph/selectionToolbox/RefreshSelectionButton.vue'
import PublishSubgraphButton from '@/components/graph/selectionToolbox/SaveToSubgraphLibrary.vue'
import { useSelectionToolboxPosition } from '@/composables/canvas/useSelectionToolboxPosition'
import { useCanvasInteractions } from '@/composables/graph/useCanvasInteractions'
import { useSelectionState } from '@/composables/graph/useSelectionState'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions'
import { useMinimap } from '@/renderer/extensions/minimap/composables/useMinimap'
import { useExtensionService } from '@/services/extensionService'
import { type ComfyCommandImpl, useCommandStore } from '@/stores/commandStore'

View File

@@ -135,8 +135,7 @@
</template>
<script setup lang="ts">
import type { InputNumberInputEvent } from 'primevue'
import { Button, InputNumber } from 'primevue'
import { Button, InputNumber, type InputNumberInputEvent } from 'primevue'
import { computed, nextTick, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'

View File

@@ -7,7 +7,7 @@
severity="secondary"
text
data-testid="bypass-button"
class="hover:dark-theme:bg-charcoal-600 hover:bg-[#E7E6E6]"
class="hover:dark-theme:bg-charcoal-300 hover:bg-[#E7E6E6]"
@click="toggleBypass"
>
<template #icon>

View File

@@ -50,8 +50,7 @@
<script setup lang="ts">
import Button from 'primevue/button'
import SelectButton from 'primevue/selectbutton'
import type { Raw } from 'vue'
import { computed, ref, watch } from 'vue'
import { type Raw, computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import type {

View File

@@ -20,7 +20,7 @@ import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { useSelectionState } from '@/composables/graph/useSelectionState'
import type { Positionable } from '@/lib/litegraph/src/interfaces'
import { type Positionable } from '@/lib/litegraph/src/interfaces'
import { useCommandStore } from '@/stores/commandStore'
const { t } = useI18n()

View File

@@ -17,8 +17,7 @@
import Button from 'primevue/button'
import { st } from '@/i18n'
import type { ComfyCommand } from '@/stores/commandStore'
import { useCommandStore } from '@/stores/commandStore'
import { type ComfyCommand, useCommandStore } from '@/stores/commandStore'
import { normalizeI18nKey } from '@/utils/formatUtil'
defineProps<{

View File

@@ -48,9 +48,9 @@
import Popover from 'primevue/popover'
import { computed, ref } from 'vue'
import type {
MenuOption,
SubMenuOption
import {
type MenuOption,
type SubMenuOption
} from '@/composables/graph/useMoreOptionsMenu'
import { useNodeCustomization } from '@/composables/graph/useNodeCustomization'

View File

@@ -56,10 +56,10 @@ import { computed, nextTick, ref, watch } from 'vue'
import CopyButton from '@/components/graph/widgets/chatHistory/CopyButton.vue'
import ResponseBlurb from '@/components/graph/widgets/chatHistory/ResponseBlurb.vue'
import type { ComponentWidget } from '@/scripts/domWidget'
import { type ComponentWidget } from '@/scripts/domWidget'
import { linkifyHtml, nl2br } from '@/utils/formatUtil'
const { widget, history } = defineProps<{
const { widget, history = '[]' } = defineProps<{
widget?: ComponentWidget<string>
history: string
}>()

View File

@@ -19,15 +19,21 @@
<script setup lang="ts">
import { useElementBounding, useEventListener } from '@vueuse/core'
import type { CSSProperties } from 'vue'
import { computed, nextTick, onMounted, ref, watch } from 'vue'
import {
type CSSProperties,
computed,
nextTick,
onMounted,
ref,
watch
} from 'vue'
import { useAbsolutePosition } from '@/composables/element/useAbsolutePosition'
import { useDomClipping } from '@/composables/element/useDomClipping'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { isComponentWidget, isDOMWidget } from '@/scripts/domWidget'
import type { DomWidgetState } from '@/stores/domWidgetStore'
import { type DomWidgetState } from '@/stores/domWidgetStore'
const { widgetState } = defineProps<{
widgetState: DomWidgetState

Some files were not shown because too many files have changed in this diff Show More