Devex: Linter updates (#7309)

## Summary

Updates for the linter/formatter deps, turning on some more rules.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7309-WIP-Linter-updates-2c56d73d36508101b3ece6bcaf7e5212)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
This commit is contained in:
Alexander Brown
2025-12-10 11:08:47 -08:00
committed by GitHub
parent b52b2bbc30
commit 72b5444d5a
62 changed files with 1331 additions and 766 deletions

View File

@@ -13,14 +13,37 @@
"src/types/generatedManagerTypes.ts", "src/types/generatedManagerTypes.ts",
"src/types/vue-shim.d.ts" "src/types/vue-shim.d.ts"
], ],
"plugins": [
"eslint",
"import",
"oxc",
"typescript",
"unicorn",
"vitest",
"vue"
],
"rules": { "rules": {
"no-async-promise-executor": "off", "no-async-promise-executor": "off",
"no-control-regex": "off", "no-control-regex": "off",
"no-eval": "off", "no-eval": "off",
"no-redeclare": "error",
"no-self-assign": "allow", "no-self-assign": "allow",
"no-unused-expressions": "off", "no-unused-expressions": "off",
"no-unused-private-class-members": "off", "no-unused-private-class-members": "off",
"no-useless-rename": "off", "no-useless-rename": "off",
"import/default": "error",
"import/export": "error",
"import/namespace": "error",
"import/no-duplicates": "error",
"import/consistent-type-specifier-style": [
"error",
"prefer-top-level"
],
"jest/expect-expect": "off",
"jest/no-conditional-expect": "off",
"jest/no-disabled-tests": "off",
"jest/no-standalone-expect": "off",
"jest/valid-title": "off",
"typescript/no-this-alias": "off", "typescript/no-this-alias": "off",
"typescript/no-unnecessary-parameter-property-assignment": "off", "typescript/no-unnecessary-parameter-property-assignment": "off",
"typescript/no-unsafe-declaration-merging": "off", "typescript/no-unsafe-declaration-merging": "off",
@@ -39,6 +62,7 @@
"typescript/restrict-template-expressions": "off", "typescript/restrict-template-expressions": "off",
"typescript/unbound-method": "off", "typescript/unbound-method": "off",
"typescript/no-floating-promises": "error", "typescript/no-floating-promises": "error",
"vue/no-import-compiler-macros": "error" "vue/no-import-compiler-macros": "error",
"vue/no-dupe-keys": "error"
} }
} }

View File

@@ -12,6 +12,9 @@
"declaration-property-value-no-unknown": [ "declaration-property-value-no-unknown": [
true, true,
{ {
"typesSyntax": {
"radial-gradient()": "| <any-value>"
},
"ignoreProperties": { "ignoreProperties": {
"speak": ["none"], "speak": ["none"],
"app-region": ["drag", "no-drag"], "app-region": ["drag", "no-drag"],
@@ -56,10 +59,7 @@
"function-no-unknown": [ "function-no-unknown": [
true, true,
{ {
"ignoreFunctions": [ "ignoreFunctions": ["theme", "v-bind"]
"theme",
"v-bind"
]
} }
] ]
}, },

View File

@@ -135,7 +135,6 @@ export default defineConfig([
allowInterfaces: 'always' allowInterfaces: 'always'
} }
], ],
'import-x/consistent-type-specifier-style': ['error', 'prefer-top-level'],
'import-x/no-useless-path-segments': 'error', 'import-x/no-useless-path-segments': 'error',
'import-x/no-relative-packages': 'error', 'import-x/no-relative-packages': 'error',
'unused-imports/no-unused-imports': 'error', 'unused-imports/no-unused-imports': 'error',
@@ -146,14 +145,13 @@ export default defineConfig([
'vue/multi-word-component-names': 'off', // TODO: fix 'vue/multi-word-component-names': 'off', // TODO: fix
'vue/no-template-shadow': 'off', // TODO: fix 'vue/no-template-shadow': 'off', // TODO: fix
'vue/match-component-import-name': 'error', 'vue/match-component-import-name': 'error',
/* Toggle on to do additional until we can clean up existing violations.
'vue/no-unused-emit-declarations': 'error',
'vue/no-unused-properties': 'error', 'vue/no-unused-properties': 'error',
'vue/no-unused-refs': 'error', 'vue/no-unused-refs': 'error',
'vue/no-use-v-else-with-v-for': 'error', 'vue/no-useless-mustaches': 'error',
'vue/no-useless-v-bind': 'error', 'vue/no-useless-v-bind': 'error',
// */ 'vue/no-unused-emit-declarations': 'error',
'vue/one-component-per-file': 'off', // TODO: fix 'vue/no-use-v-else-with-v-for': 'error',
'vue/one-component-per-file': 'error',
'vue/require-default-prop': 'off', // TODO: fix -- this one is very worthwhile 'vue/require-default-prop': 'off', // TODO: fix -- this one is very worthwhile
// Restrict deprecated PrimeVue components // Restrict deprecated PrimeVue components
'no-restricted-imports': [ 'no-restricted-imports': [
@@ -297,5 +295,14 @@ export default defineConfig([
// Turn off ESLint rules that are already handled by oxlint // Turn off ESLint rules that are already handled by oxlint
...oxlint.buildFromOxlintConfigFile( ...oxlint.buildFromOxlintConfigFile(
path.resolve(import.meta.dirname, '.oxlintrc.json') path.resolve(import.meta.dirname, '.oxlintrc.json')
) ),
{
rules: {
'import-x/default': 'off',
'import-x/export': 'off',
'import-x/namespace': 'off',
'import-x/no-duplicates': 'off',
'import-x/consistent-type-specifier-style': 'off'
}
}
]) ])

1648
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@ packages:
catalog: catalog:
'@alloc/quick-lru': ^5.2.0 '@alloc/quick-lru': ^5.2.0
'@comfyorg/comfyui-electron-types': 0.5.5 '@comfyorg/comfyui-electron-types': 0.5.5
'@eslint/js': ^9.35.0 '@eslint/js': ^9.39.1
'@iconify-json/lucide': ^1.1.178 '@iconify-json/lucide': ^1.1.178
'@iconify/json': ^2.2.380 '@iconify/json': ^2.2.380
'@iconify/tailwind': ^1.1.3 '@iconify/tailwind': ^1.1.3
@@ -17,7 +17,7 @@ catalog:
'@nx/vite': 21.4.1 '@nx/vite': 21.4.1
'@pinia/testing': ^0.1.5 '@pinia/testing': ^0.1.5
'@playwright/test': ^1.52.0 '@playwright/test': ^1.52.0
'@prettier/plugin-oxc': ^0.0.4 '@prettier/plugin-oxc': ^0.1.3
'@primeuix/forms': 0.0.2 '@primeuix/forms': 0.0.2
'@primeuix/styled': 0.3.2 '@primeuix/styled': 0.3.2
'@primeuix/utils': ^0.3.2 '@primeuix/utils': ^0.3.2
@@ -48,15 +48,15 @@ catalog:
axios: ^1.8.2 axios: ^1.8.2
cross-env: ^10.1.0 cross-env: ^10.1.0
dotenv: ^16.4.5 dotenv: ^16.4.5
eslint: ^9.34.0 eslint: ^9.39.1
eslint-config-prettier: ^10.1.8 eslint-config-prettier: ^10.1.8
eslint-import-resolver-typescript: ^4.4.4 eslint-import-resolver-typescript: ^4.4.4
eslint-plugin-import-x: ^4.16.1 eslint-plugin-import-x: ^4.16.1
eslint-plugin-oxlint: 1.25.0 eslint-plugin-oxlint: 1.25.0
eslint-plugin-prettier: ^5.5.4 eslint-plugin-prettier: ^5.5.4
eslint-plugin-storybook: ^9.1.6 eslint-plugin-storybook: ^9.1.16
eslint-plugin-unused-imports: ^4.2.0 eslint-plugin-unused-imports: ^4.3.0
eslint-plugin-vue: ^10.4.0 eslint-plugin-vue: ^10.6.2
firebase: ^11.6.0 firebase: ^11.6.0
globals: ^15.9.0 globals: ^15.9.0
happy-dom: ^15.11.0 happy-dom: ^15.11.0
@@ -64,29 +64,29 @@ catalog:
jiti: 2.4.2 jiti: 2.4.2
jsdom: ^26.1.0 jsdom: ^26.1.0
knip: ^5.62.0 knip: ^5.62.0
lint-staged: ^15.2.7 lint-staged: ^15.5.2
markdown-table: ^3.0.4 markdown-table: ^3.0.4
mixpanel-browser: ^2.71.0 mixpanel-browser: ^2.71.0
nx: 21.4.1 nx: 21.4.1
oxlint: ^1.25.0 oxlint: ^1.32.0
oxlint-tsgolint: ^0.4.0 oxlint-tsgolint: ^0.8.4
picocolors: ^1.1.1 picocolors: ^1.1.1
pinia: ^2.1.7 pinia: ^2.1.7
postcss-html: ^1.8.0 postcss-html: ^1.8.0
prettier: ^3.6.2 prettier: ^3.7.4
pretty-bytes: ^7.1.0 pretty-bytes: ^7.1.0
primeicons: ^7.0.0 primeicons: ^7.0.0
primevue: ^4.2.5 primevue: ^4.2.5
rollup-plugin-visualizer: ^6.0.4 rollup-plugin-visualizer: ^6.0.4
storybook: ^9.1.6 storybook: ^9.1.16
stylelint: ^16.24.0 stylelint: ^16.26.1
tailwindcss: ^4.1.12 tailwindcss: ^4.1.12
tailwindcss-primeui: ^0.6.1 tailwindcss-primeui: ^0.6.1
tsx: ^4.15.6 tsx: ^4.15.6
tw-animate-css: ^1.3.8 tw-animate-css: ^1.3.8
typegpu: ^0.8.2 typegpu: ^0.8.2
typescript: ^5.9.2 typescript: ^5.9.3
typescript-eslint: ^8.44.0 typescript-eslint: ^8.49.0
unplugin-icons: ^0.22.0 unplugin-icons: ^0.22.0
unplugin-typegpu: 0.8.0 unplugin-typegpu: 0.8.0
unplugin-vue-components: ^0.28.0 unplugin-vue-components: ^0.28.0
@@ -100,7 +100,7 @@ catalog:
vue-eslint-parser: ^10.2.0 vue-eslint-parser: ^10.2.0
vue-i18n: ^9.14.3 vue-i18n: ^9.14.3
vue-router: ^4.4.3 vue-router: ^4.4.3
vue-tsc: ^3.0.7 vue-tsc: ^3.1.8
vuefire: ^3.2.1 vuefire: ^3.2.1
yjs: ^13.6.27 yjs: ^13.6.27
zod: ^3.23.8 zod: ^3.23.8

View File

@@ -55,7 +55,6 @@ import { normalizeI18nKey } from '@/utils/formatUtil'
const { t } = useI18n() const { t } = useI18n()
const { subcategories } = defineProps<{ const { subcategories } = defineProps<{
commands: ComfyCommandImpl[]
subcategories: Record<string, ComfyCommandImpl[]> subcategories: Record<string, ComfyCommandImpl[]>
}>() }>()

View File

@@ -21,7 +21,7 @@
class="icon-[lucide--triangle-alert] text-warning-background" class="icon-[lucide--triangle-alert] text-warning-background"
/> />
<span class="p-breadcrumb-item-label px-2">{{ item.label }}</span> <span class="p-breadcrumb-item-label px-2">{{ item.label }}</span>
<Tag v-if="item.isBlueprint" :value="'Blueprint'" severity="primary" /> <Tag v-if="item.isBlueprint" value="Blueprint" severity="primary" />
<i v-if="isActive" class="pi pi-angle-down text-[10px]"></i> <i v-if="isActive" class="pi pi-angle-down text-[10px]"></i>
</a> </a>
<Menu <Menu

View File

@@ -41,7 +41,7 @@ const {
inputAttrs?: Record<string, string> inputAttrs?: Record<string, string>
}>() }>()
const emit = defineEmits(['update:modelValue', 'edit', 'cancel']) const emit = defineEmits(['edit', 'cancel'])
const inputValue = ref<string>(modelValue) const inputValue = ref<string>(modelValue)
const inputRef = ref<InstanceType<typeof InputText> | undefined>() const inputRef = ref<InstanceType<typeof InputText> | undefined>()
const isCanceling = ref(false) const isCanceling = ref(false)

View File

@@ -11,7 +11,6 @@ import InputText from 'primevue/inputtext'
const modelValue = defineModel<string>('modelValue') const modelValue = defineModel<string>('modelValue')
defineProps<{ defineProps<{
defaultValue?: string
label?: string label?: string
}>() }>()

View File

@@ -5,7 +5,7 @@
icon="pi pi-exclamation-circle" icon="pi pi-exclamation-circle"
:title="title" :title="title"
:message="error.exceptionMessage" :message="error.exceptionMessage"
:text-class="'break-words max-w-[60vw]'" text-class="break-words max-w-[60vw]"
/> />
<template v-if="error.extensionFile"> <template v-if="error.extensionFile">
<span>{{ t('errorDialog.extensionFileHint') }}:</span> <span>{{ t('errorDialog.extensionFileHint') }}:</span>

View File

@@ -465,9 +465,8 @@ onMounted(async () => {
await workflowPersistence.loadTemplateFromUrlIfPresent() await workflowPersistence.loadTemplateFromUrlIfPresent()
// Initialize release store to fetch releases from comfy-api (fire-and-forget) // Initialize release store to fetch releases from comfy-api (fire-and-forget)
const { useReleaseStore } = await import( const { useReleaseStore } =
'@/platform/updates/common/releaseStore' await import('@/platform/updates/common/releaseStore')
)
const releaseStore = useReleaseStore() const releaseStore = useReleaseStore()
void releaseStore.initialize() void releaseStore.initialize()

View File

@@ -37,7 +37,6 @@
</Button> </Button>
<Button <Button
ref="zoomButton"
v-tooltip.top="t('zoomControls.label')" v-tooltip.top="t('zoomControls.label')"
severity="secondary" severity="secondary"
:label="t('zoomControls.label')" :label="t('zoomControls.label')"
@@ -56,7 +55,6 @@
<div class="h-[27px] w-[1px] self-center bg-node-divider" /> <div class="h-[27px] w-[1px] self-center bg-node-divider" />
<Button <Button
ref="minimapButton"
v-tooltip.top="minimapTooltip" v-tooltip.top="minimapTooltip"
severity="secondary" severity="secondary"
:aria-label="minimapTooltip" :aria-label="minimapTooltip"

View File

@@ -2,7 +2,7 @@
<div> <div>
<Popover <Popover
ref="popover" ref="popover"
:append-to="'body'" append-to="body"
:auto-z-index="true" :auto-z-index="true"
:base-z-index="1000" :base-z-index="1000"
:dismissable="true" :dismissable="true"

View File

@@ -21,7 +21,6 @@ import { linkifyHtml, nl2br } from '@/utils/formatUtil'
const modelValue = defineModel<string>({ required: true }) const modelValue = defineModel<string>({ required: true })
const props = defineProps<{ const props = defineProps<{
widget?: object
nodeId: NodeId nodeId: NodeId
}>() }>()

View File

@@ -35,7 +35,6 @@
<div v-show="activeCategory" class="rounded-lg bg-smoke-700/30"> <div v-show="activeCategory" class="rounded-lg bg-smoke-700/30">
<SceneControls <SceneControls
v-if="showSceneControls" v-if="showSceneControls"
ref="sceneControlsRef"
v-model:show-grid="sceneConfig!.showGrid" v-model:show-grid="sceneConfig!.showGrid"
v-model:background-color="sceneConfig!.backgroundColor" v-model:background-color="sceneConfig!.backgroundColor"
v-model:background-image="sceneConfig!.backgroundImage" v-model:background-image="sceneConfig!.backgroundImage"
@@ -46,28 +45,24 @@
<ModelControls <ModelControls
v-if="showModelControls" v-if="showModelControls"
ref="modelControlsRef"
v-model:material-mode="modelConfig!.materialMode" v-model:material-mode="modelConfig!.materialMode"
v-model:up-direction="modelConfig!.upDirection" v-model:up-direction="modelConfig!.upDirection"
/> />
<CameraControls <CameraControls
v-if="showCameraControls" v-if="showCameraControls"
ref="cameraControlsRef"
v-model:camera-type="cameraConfig!.cameraType" v-model:camera-type="cameraConfig!.cameraType"
v-model:fov="cameraConfig!.fov" v-model:fov="cameraConfig!.fov"
/> />
<LightControls <LightControls
v-if="showLightControls" v-if="showLightControls"
ref="lightControlsRef"
v-model:light-intensity="lightConfig!.intensity" v-model:light-intensity="lightConfig!.intensity"
v-model:material-mode="modelConfig!.materialMode" v-model:material-mode="modelConfig!.materialMode"
/> />
<ExportControls <ExportControls
v-if="showExportControls" v-if="showExportControls"
ref="exportControlsRef"
@export-model="handleExportModel" @export-model="handleExportModel"
/> />
</div> </div>

View File

@@ -9,8 +9,7 @@
<span class="inline-flex items-center gap-2"> <span class="inline-flex items-center gap-2">
<span v-if="props.mode === 'allFailed'" class="inline-flex items-center"> <span v-if="props.mode === 'allFailed'" class="inline-flex items-center">
<i <i
class="ml-1 icon-[lucide--circle-alert] block size-4 leading-none" class="ml-1 icon-[lucide--circle-alert] block size-4 leading-none text-destructive-background"
:class="'text-destructive-background'"
/> />
</span> </span>

View File

@@ -64,8 +64,7 @@ export const RunningWithCurrent: Story = {
state: 'running', state: 'running',
title: 'Generating image', title: 'Generating image',
progressTotalPercent: 66, progressTotalPercent: 66,
progressCurrentPercent: 10, progressCurrentPercent: 10
runningNodeName: 'KSampler'
} }
} }

View File

@@ -225,7 +225,6 @@ const props = withDefaults(
showMenu?: boolean showMenu?: boolean
progressTotalPercent?: number progressTotalPercent?: number
progressCurrentPercent?: number progressCurrentPercent?: number
runningNodeName?: string
activeDetailsId?: string | null activeDetailsId?: string | null
}>(), }>(),
{ {

View File

@@ -7,7 +7,6 @@ import type { ClassValue } from '@/utils/tailwindUtil'
const props = defineProps<{ const props = defineProps<{
nodeTitle: string nodeTitle: string
widgetName: string widgetName: string
isShown?: boolean
isDraggable?: boolean isDraggable?: boolean
isPhysical?: boolean isPhysical?: boolean
class?: ClassValue class?: ClassValue

View File

@@ -49,7 +49,7 @@
auto-option-focus auto-option-focus
force-selection force-selection
multiple multiple
:option-label="'display_name'" option-label="display_name"
@complete="search($event.query)" @complete="search($event.query)"
@option-select="onAddNode($event.value)" @option-select="onAddNode($event.value)"
@focused-option-changed="setHoverSuggestion($event)" @focused-option-changed="setHoverSuggestion($event)"

View File

@@ -59,7 +59,6 @@ interface WorkflowOption {
} }
const props = defineProps<{ const props = defineProps<{
class?: string
workflowOption: WorkflowOption workflowOption: WorkflowOption
}>() }>()

View File

@@ -14,6 +14,7 @@ import type { HTMLAttributes } from 'vue'
import { cn } from '@/utils/tailwindUtil' import { cn } from '@/utils/tailwindUtil'
const props = defineProps< const props = defineProps<
// eslint-disable-next-line vue/no-unused-properties
SliderRootProps & { class?: HTMLAttributes['class'] } SliderRootProps & { class?: HTMLAttributes['class'] }
>() >()

View File

@@ -249,9 +249,7 @@ const link_bounding = new Rectangle()
* This class is in charge of rendering one graph inside a canvas. And provides all the interaction required. * This class is in charge of rendering one graph inside a canvas. And provides all the interaction required.
* Valid callbacks are: onNodeSelected, onNodeDeselected, onShowNodePanel, onNodeDblClicked * Valid callbacks are: onNodeSelected, onNodeDeselected, onShowNodePanel, onNodeDblClicked
*/ */
export class LGraphCanvas export class LGraphCanvas implements CustomEventDispatcher<LGraphCanvasEventMap> {
implements CustomEventDispatcher<LGraphCanvasEventMap>
{
static DEFAULT_BACKGROUND_IMAGE = static DEFAULT_BACKGROUND_IMAGE =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQBJREFUeNrs1rEKwjAUhlETUkj3vP9rdmr1Ysammk2w5wdxuLgcMHyptfawuZX4pJSWZTnfnu/lnIe/jNNxHHGNn//HNbbv+4dr6V+11uF527arU7+u63qfa/bnmh8sWLBgwYJlqRf8MEptXPBXJXa37BSl3ixYsGDBMliwFLyCV/DeLIMFCxYsWLBMwSt4Be/NggXLYMGCBUvBK3iNruC9WbBgwYJlsGApeAWv4L1ZBgsWLFiwYJmCV/AK3psFC5bBggULloJX8BpdwXuzYMGCBctgwVLwCl7Be7MMFixYsGDBsu8FH1FaSmExVfAxBa/gvVmwYMGCZbBg/W4vAQYA5tRF9QYlv/QAAAAASUVORK5CYII=' 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQBJREFUeNrs1rEKwjAUhlETUkj3vP9rdmr1Ysammk2w5wdxuLgcMHyptfawuZX4pJSWZTnfnu/lnIe/jNNxHHGNn//HNbbv+4dr6V+11uF527arU7+u63qfa/bnmh8sWLBgwYJlqRf8MEptXPBXJXa37BSl3ixYsGDBMliwFLyCV/DeLIMFCxYsWLBMwSt4Be/NggXLYMGCBUvBK3iNruC9WbBgwYJlsGApeAWv4L1ZBgsWLFiwYJmCV/AK3psFC5bBggULloJX8BpdwXuzYMGCBctgwVLwCl7Be7MMFixYsGDBsu8FH1FaSmExVfAxBa/gvVmwYMGCZbBg/W4vAQYA5tRF9QYlv/QAAAAASUVORK5CYII='

View File

@@ -2,9 +2,9 @@
* Temporary workaround until downstream consumers migrate to Map. * Temporary workaround until downstream consumers migrate to Map.
* A brittle wrapper with many flaws, but should be fine for simple maps using int indexes. * A brittle wrapper with many flaws, but should be fine for simple maps using int indexes.
*/ */
export class MapProxyHandler<V> export class MapProxyHandler<V> implements ProxyHandler<
implements ProxyHandler<Map<number | string, V>> Map<number | string, V>
{ > {
getOwnPropertyDescriptor( getOwnPropertyDescriptor(
target: Map<number | string, V>, target: Map<number | string, V>,
p: string | symbol p: string | symbol

View File

@@ -81,9 +81,9 @@ export interface CustomEventDispatcher<
* ``` * ```
*/ */
export class CustomEventTarget< export class CustomEventTarget<
EventMap extends Record<Keys, unknown>, EventMap extends Record<Keys, unknown>,
Keys extends keyof EventMap & string = keyof EventMap & string Keys extends keyof EventMap & string = keyof EventMap & string
> >
extends EventTarget extends EventTarget
implements ICustomEventTarget<EventMap, Keys> implements ICustomEventTarget<EventMap, Keys>
{ {

View File

@@ -380,8 +380,10 @@ interface IContextMenuBase {
} }
/** ContextMenu */ /** ContextMenu */
export interface IContextMenuOptions<TValue = unknown, TExtra = unknown> export interface IContextMenuOptions<
extends IContextMenuBase { TValue = unknown,
TExtra = unknown
> extends IContextMenuBase {
ignore_item_callbacks?: boolean ignore_item_callbacks?: boolean
parentMenu?: ContextMenu<TValue> parentMenu?: ContextMenu<TValue>
event?: MouseEvent event?: MouseEvent
@@ -426,13 +428,15 @@ export interface IContextMenuValue<
): void | boolean | Promise<void | boolean> ): void | boolean | Promise<void | boolean>
} }
interface IContextMenuSubmenu<TValue = unknown> interface IContextMenuSubmenu<
extends IContextMenuOptions<TValue> { TValue = unknown
> extends IContextMenuOptions<TValue> {
options: ConstructorParameters<typeof ContextMenu<TValue>>[0] options: ConstructorParameters<typeof ContextMenu<TValue>>[0]
} }
export interface ContextMenuDivElement<TValue = unknown> export interface ContextMenuDivElement<
extends HTMLDivElement { TValue = unknown
> extends HTMLDivElement {
value?: string | IContextMenuValue<TValue> value?: string | IContextMenuValue<TValue>
onclick_callback?: never onclick_callback?: never
} }

View File

@@ -30,8 +30,8 @@ import type { SubgraphInput } from './SubgraphInput'
import type { SubgraphOutput } from './SubgraphOutput' import type { SubgraphOutput } from './SubgraphOutput'
export abstract class SubgraphIONodeBase< export abstract class SubgraphIONodeBase<
TSlot extends SubgraphInput | SubgraphOutput TSlot extends SubgraphInput | SubgraphOutput
> >
implements Positionable, Hoverable, Serialisable<ExportedSubgraphIONode> implements Positionable, Hoverable, Serialisable<ExportedSubgraphIONode>
{ {
static margin = 10 static margin = 10

View File

@@ -46,9 +46,7 @@ export interface CanvasPointerEvent extends PointerEvent, CanvasMouseEvent {}
/** MouseEvent with canvasX/Y and deltaX/Y properties */ /** MouseEvent with canvasX/Y and deltaX/Y properties */
interface CanvasMouseEvent interface CanvasMouseEvent
extends MouseEvent, extends MouseEvent, Readonly<CanvasPointerExtensions>, LegacyMouseEvent {}
Readonly<CanvasPointerExtensions>,
LegacyMouseEvent {}
export type CanvasEventDetail = export type CanvasEventDetail =
| GenericEventDetail | GenericEventDetail

View File

@@ -94,27 +94,32 @@ export interface INumericWidget extends IBaseWidget<number, 'number'> {
value: number value: number
} }
export interface ISliderWidget export interface ISliderWidget extends IBaseWidget<
extends IBaseWidget<number, 'slider', IWidgetSliderOptions> { number,
'slider',
IWidgetSliderOptions
> {
type: 'slider' type: 'slider'
value: number value: number
marker?: number marker?: number
} }
export interface IKnobWidget export interface IKnobWidget extends IBaseWidget<
extends IBaseWidget<number, 'knob', IWidgetKnobOptions> { number,
'knob',
IWidgetKnobOptions
> {
type: 'knob' type: 'knob'
value: number value: number
options: IWidgetKnobOptions options: IWidgetKnobOptions
} }
/** Avoids the type issues with the legacy IComboWidget type */ /** Avoids the type issues with the legacy IComboWidget type */
export interface IStringComboWidget export interface IStringComboWidget extends IBaseWidget<
extends IBaseWidget< string,
string, 'combo',
'combo', RequiredProps<IWidgetOptions<string[]>, 'values'>
RequiredProps<IWidgetOptions<string[]>, 'values'> > {
> {
type: 'combo' type: 'combo'
value: string value: string
} }
@@ -125,25 +130,29 @@ type ComboWidgetValues =
| ((widget?: IComboWidget, node?: LGraphNode) => string[]) | ((widget?: IComboWidget, node?: LGraphNode) => string[])
/** A combo-box widget (dropdown, select, etc) */ /** A combo-box widget (dropdown, select, etc) */
export interface IComboWidget export interface IComboWidget extends IBaseWidget<
extends IBaseWidget< string | number,
string | number, 'combo',
'combo', RequiredProps<IWidgetOptions<ComboWidgetValues>, 'values'>
RequiredProps<IWidgetOptions<ComboWidgetValues>, 'values'> > {
> {
type: 'combo' type: 'combo'
value: string | number value: string | number
} }
/** A widget with a string value */ /** A widget with a string value */
export interface IStringWidget export interface IStringWidget extends IBaseWidget<
extends IBaseWidget<string, 'string' | 'text', IWidgetOptions<string[]>> { string,
'string' | 'text',
IWidgetOptions<string[]>
> {
type: 'string' | 'text' type: 'string' | 'text'
value: string value: string
} }
export interface IButtonWidget export interface IButtonWidget extends IBaseWidget<
extends IBaseWidget<string | undefined, 'button'> { string | undefined,
'button'
> {
type: 'button' type: 'button'
value: string | undefined value: string | undefined
clicked: boolean clicked: boolean
@@ -181,15 +190,19 @@ interface IImageWidget extends IBaseWidget<string, 'image'> {
} }
/** Tree select widget for hierarchical selection */ /** Tree select widget for hierarchical selection */
export interface ITreeSelectWidget export interface ITreeSelectWidget extends IBaseWidget<
extends IBaseWidget<string | string[], 'treeselect'> { string | string[],
'treeselect'
> {
type: 'treeselect' type: 'treeselect'
value: string | string[] value: string | string[]
} }
/** Multi-select widget for selecting multiple options */ /** Multi-select widget for selecting multiple options */
export interface IMultiSelectWidget export interface IMultiSelectWidget extends IBaseWidget<
extends IBaseWidget<string[], 'multiselect'> { string[],
'multiselect'
> {
type: 'multiselect' type: 'multiselect'
value: string[] value: string[]
} }
@@ -207,19 +220,20 @@ export interface IGalleriaWidget extends IBaseWidget<string[], 'galleria'> {
} }
/** Image comparison widget for comparing two images side by side */ /** Image comparison widget for comparing two images side by side */
export interface IImageCompareWidget export interface IImageCompareWidget extends IBaseWidget<
extends IBaseWidget<string[], 'imagecompare'> { string[],
'imagecompare'
> {
type: 'imagecompare' type: 'imagecompare'
value: string[] value: string[]
} }
/** Select button widget for selecting from a group of buttons */ /** Select button widget for selecting from a group of buttons */
export interface ISelectButtonWidget export interface ISelectButtonWidget extends IBaseWidget<
extends IBaseWidget< string,
string, 'selectbutton',
'selectbutton', RequiredProps<IWidgetOptions<string[]>, 'values'>
RequiredProps<IWidgetOptions<string[]>, 'values'> > {
> {
type: 'selectbutton' type: 'selectbutton'
value: string value: string
} }
@@ -230,8 +244,11 @@ export interface ITextareaWidget extends IBaseWidget<string, 'textarea'> {
value: string value: string
} }
export interface IAssetWidget export interface IAssetWidget extends IBaseWidget<
extends IBaseWidget<string, 'asset', IWidgetOptions<string[]>> { string,
'asset',
IWidgetOptions<string[]>
> {
type: 'asset' type: 'asset'
value: string value: string
} }

View File

@@ -33,9 +33,9 @@ export interface WidgetEventOptions {
canvas: LGraphCanvas canvas: LGraphCanvas
} }
export abstract class BaseWidget<TWidget extends IBaseWidget = IBaseWidget> export abstract class BaseWidget<
implements IBaseWidget TWidget extends IBaseWidget = IBaseWidget
{ > implements IBaseWidget {
/** From node edge to widget edge */ /** From node edge to widget edge */
static margin = 15 static margin = 15
/** From widget edge to tip of arrow button */ /** From widget edge to tip of arrow button */

View File

@@ -27,9 +27,8 @@ import { i18n } from './i18n'
import { isCloud } from '@/platform/distribution/types' import { isCloud } from '@/platform/distribution/types'
if (isCloud) { if (isCloud) {
const { loadRemoteConfig } = await import( const { loadRemoteConfig } =
'@/platform/remoteConfig/remoteConfig' await import('@/platform/remoteConfig/remoteConfig')
)
await loadRemoteConfig() await loadRemoteConfig()
} }

View File

@@ -85,7 +85,6 @@ import { OnCloseKey } from '@/types/widgetTypes'
const props = defineProps<{ const props = defineProps<{
nodeType?: string nodeType?: string
inputName?: string
onSelect?: (asset: AssetItem) => void onSelect?: (asset: AssetItem) => void
onClose?: () => void onClose?: () => void
showLeftPanel?: boolean showLeftPanel?: boolean

View File

@@ -44,7 +44,6 @@ TODO: Extract checkbox pattern into reusable Checkbox component
<script setup lang="ts"> <script setup lang="ts">
const { mediaTypeFilters } = defineProps<{ const { mediaTypeFilters } = defineProps<{
mediaTypeFilters: string[] mediaTypeFilters: string[]
close: () => void
}>() }>()
const emit = defineEmits<{ const emit = defineEmits<{

View File

@@ -6,7 +6,7 @@
<Popover <Popover
ref="popover" ref="popover"
:append-to="'body'" append-to="body"
:auto-z-index="true" :auto-z-index="true"
:base-z-index="1000" :base-z-index="1000"
:dismissable="true" :dismissable="true"

View File

@@ -16,12 +16,11 @@ import { computed } from 'vue'
import { formatSize, getFilenameDetails } from '@/utils/formatUtil' import { formatSize, getFilenameDetails } from '@/utils/formatUtil'
import type { AssetContext, AssetMeta } from '../schemas/mediaAssetSchema' import type { AssetMeta } from '../schemas/mediaAssetSchema'
import MediaTitle from './MediaTitle.vue' import MediaTitle from './MediaTitle.vue'
const { asset } = defineProps<{ const { asset } = defineProps<{
asset: AssetMeta asset: AssetMeta
context: AssetContext
}>() }>()
const fileName = computed(() => { const fileName = computed(() => {

View File

@@ -14,12 +14,11 @@ import { computed } from 'vue'
import { getFilenameDetails } from '@/utils/formatUtil' import { getFilenameDetails } from '@/utils/formatUtil'
import type { AssetContext, AssetMeta } from '../schemas/mediaAssetSchema' import type { AssetMeta } from '../schemas/mediaAssetSchema'
import MediaTitle from './MediaTitle.vue' import MediaTitle from './MediaTitle.vue'
const { asset } = defineProps<{ const { asset } = defineProps<{
asset: AssetMeta asset: AssetMeta
context: AssetContext
}>() }>()
const fileName = computed(() => { const fileName = computed(() => {

View File

@@ -13,12 +13,11 @@ import { computed } from 'vue'
import { formatSize, getFilenameDetails } from '@/utils/formatUtil' import { formatSize, getFilenameDetails } from '@/utils/formatUtil'
import type { AssetContext, AssetMeta } from '../schemas/mediaAssetSchema' import type { AssetMeta } from '../schemas/mediaAssetSchema'
import MediaTitle from './MediaTitle.vue' import MediaTitle from './MediaTitle.vue'
const { asset } = defineProps<{ const { asset } = defineProps<{
asset: AssetMeta asset: AssetMeta
context: AssetContext
}>() }>()
const fileName = computed(() => { const fileName = computed(() => {

View File

@@ -5,7 +5,6 @@
@mouseleave="isHovered = false" @mouseleave="isHovered = false"
> >
<video <video
ref="videoRef"
:controls="shouldShowControls" :controls="shouldShowControls"
preload="metadata" preload="metadata"
autoplay autoplay
@@ -27,20 +26,17 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue' import { computed, onMounted, ref, watch } from 'vue'
import type { AssetContext, AssetMeta } from '../schemas/mediaAssetSchema' import type { AssetMeta } from '../schemas/mediaAssetSchema'
const { asset } = defineProps<{ const { asset } = defineProps<{
asset: AssetMeta asset: AssetMeta
context: AssetContext
}>() }>()
const emit = defineEmits<{ const emit = defineEmits<{
play: [assetId: string]
videoPlayingStateChanged: [isPlaying: boolean] videoPlayingStateChanged: [isPlaying: boolean]
videoControlsChanged: [showControls: boolean] videoControlsChanged: [showControls: boolean]
}>() }>()
const videoRef = ref<HTMLVideoElement>()
const isHovered = ref(false) const isHovered = ref(false)
const isPlaying = ref(false) const isPlaying = ref(false)

View File

@@ -14,9 +14,8 @@ export const cloudOnboardingRoutes: RouteRecordRaw[] = [
beforeEnter: async (to, _from, next) => { beforeEnter: async (to, _from, next) => {
// Only redirect if not explicitly switching accounts // Only redirect if not explicitly switching accounts
if (!to.query.switchAccount) { if (!to.query.switchAccount) {
const { useCurrentUser } = await import( const { useCurrentUser } =
'@/composables/auth/useCurrentUser' await import('@/composables/auth/useCurrentUser')
)
const { isLoggedIn } = useCurrentUser() const { isLoggedIn } = useCurrentUser()
if (isLoggedIn.value) { if (isLoggedIn.value) {

View File

@@ -28,9 +28,7 @@ export const useSubscriptionDialog = () => {
key: DIALOG_KEY, key: DIALOG_KEY,
component: defineAsyncComponent( component: defineAsyncComponent(
() => () =>
import( import('@/platform/cloud/subscription/components/SubscriptionRequiredDialogContent.vue')
'@/platform/cloud/subscription/components/SubscriptionRequiredDialogContent.vue'
)
), ),
props: { props: {
onClose: hide onClose: hide

View File

@@ -100,9 +100,7 @@ export function useSettingUI(
}, },
component: defineAsyncComponent( component: defineAsyncComponent(
() => () =>
import( import('@/platform/cloud/subscription/components/SubscriptionPanel.vue')
'@/platform/cloud/subscription/components/SubscriptionPanel.vue'
)
) )
} }

View File

@@ -181,7 +181,6 @@ import NodeWidgets from './NodeWidgets.vue'
interface LGraphNodeProps { interface LGraphNodeProps {
nodeData: VueNodeData nodeData: VueNodeData
error?: string | null error?: string | null
zoomLevel?: number
} }
const { nodeData, error = null } = defineProps<LGraphNodeProps>() const { nodeData, error = null } = defineProps<LGraphNodeProps>()

View File

@@ -1,3 +1,4 @@
/* eslint-disable vue/one-component-per-file */
import { mount } from '@vue/test-utils' import { mount } from '@vue/test-utils'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import { describe, expect, it } from 'vitest' import { describe, expect, it } from 'vitest'

View File

@@ -9,7 +9,6 @@ import type { SimplifiedWidget } from '@/types/simplifiedWidget'
const props = defineProps<{ const props = defineProps<{
widget: SimplifiedWidget<void> widget: SimplifiedWidget<void>
nodeId: string nodeId: string
readonly?: boolean
}>() }>()
const domEl = ref<HTMLElement>() const domEl = ref<HTMLElement>()

View File

@@ -14,7 +14,6 @@ import type { SimplifiedWidget } from '@/types/simplifiedWidget'
const props = defineProps<{ const props = defineProps<{
widget: SimplifiedWidget<void> widget: SimplifiedWidget<void>
readonly?: boolean
}>() }>()
const canvasEl = ref() const canvasEl = ref()

View File

@@ -92,7 +92,6 @@ import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
import { useToastStore } from '@/platform/updates/common/toastStore' import { useToastStore } from '@/platform/updates/common/toastStore'
import { app } from '@/scripts/app' import { app } from '@/scripts/app'
import { useAudioService } from '@/services/audioService' import { useAudioService } from '@/services/audioService'
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
import { useAudioPlayback } from '../composables/audio/useAudioPlayback' import { useAudioPlayback } from '../composables/audio/useAudioPlayback'
import { useAudioRecorder } from '../composables/audio/useAudioRecorder' import { useAudioRecorder } from '../composables/audio/useAudioRecorder'
@@ -100,7 +99,6 @@ import { useAudioWaveform } from '../composables/audio/useAudioWaveform'
import { formatTime } from '../utils/audioUtils' import { formatTime } from '../utils/audioUtils'
const props = defineProps<{ const props = defineProps<{
widget: SimplifiedWidget<string | number | undefined>
readonly?: boolean readonly?: boolean
nodeId: string nodeId: string
}>() }>()

View File

@@ -82,7 +82,6 @@
<!-- Options Button --> <!-- Options Button -->
<div <div
v-if="showOptionsButton" v-if="showOptionsButton"
ref="optionsButtonRef"
role="button" role="button"
:tabindex="0" :tabindex="0"
:aria-label="$t('g.moreOptions')" :aria-label="$t('g.moreOptions')"
@@ -155,10 +154,8 @@ const { t } = useI18n()
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
readonly?: boolean
hideWhenEmpty?: boolean hideWhenEmpty?: boolean
showOptionsButton?: boolean showOptionsButton?: boolean
modelValue?: string
nodeId?: string nodeId?: string
audioUrl?: string audioUrl?: string
}>(), }>(),
@@ -170,7 +167,6 @@ const props = withDefaults(
// Refs // Refs
const audioRef = ref<HTMLAudioElement>() const audioRef = ref<HTMLAudioElement>()
const optionsMenu = ref() const optionsMenu = ref()
const optionsButtonRef = ref<HTMLElement>()
const isPlaying = ref(false) const isPlaying = ref(false)
const isMuted = ref(false) const isMuted = ref(false)
const volume = ref(1) const volume = ref(1)

View File

@@ -9,7 +9,6 @@ import type { DropdownItem, SelectedKey } from './types'
interface Props { interface Props {
isOpen?: boolean isOpen?: boolean
placeholder?: string placeholder?: string
files: File[]
items: DropdownItem[] items: DropdownItem[]
selected: Set<SelectedKey> selected: Set<SelectedKey>
maxSelectable: number maxSelectable: number

View File

@@ -169,9 +169,8 @@ if (isCloud) {
// For root path, check actual user status to handle waitlisted users // For root path, check actual user status to handle waitlisted users
if (!isElectron() && isLoggedIn && to.path === '/') { if (!isElectron() && isLoggedIn && to.path === '/') {
// Import auth functions dynamically to avoid circular dependency // Import auth functions dynamically to avoid circular dependency
const { getSurveyCompletedStatus } = await import( const { getSurveyCompletedStatus } =
'@/platform/cloud/onboarding/auth' await import('@/platform/cloud/onboarding/auth')
)
try { try {
// Check user's actual status // Check user's actual status
const surveyCompleted = await getSurveyCompletedStatus() const surveyCompleted = await getSurveyCompletedStatus()

View File

@@ -15,8 +15,9 @@ import type { InputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'
import { useDomWidgetStore } from '@/stores/domWidgetStore' import { useDomWidgetStore } from '@/stores/domWidgetStore'
import { generateUUID } from '@/utils/formatUtil' import { generateUUID } from '@/utils/formatUtil'
export interface BaseDOMWidget<V extends object | string = object | string> export interface BaseDOMWidget<
extends IBaseWidget<V, string, DOMWidgetOptions<V>> { V extends object | string = object | string
> extends IBaseWidget<V, string, DOMWidgetOptions<V>> {
// ICustomWidget properties // ICustomWidget properties
type: string type: string
options: DOMWidgetOptions<V> options: DOMWidgetOptions<V>
@@ -37,8 +38,10 @@ export interface BaseDOMWidget<V extends object | string = object | string>
/** /**
* A DOM widget that wraps a custom HTML element as a litegraph widget. * A DOM widget that wraps a custom HTML element as a litegraph widget.
*/ */
export interface DOMWidget<T extends HTMLElement, V extends object | string> export interface DOMWidget<
extends BaseDOMWidget<V> { T extends HTMLElement,
V extends object | string
> extends BaseDOMWidget<V> {
element: T element: T
/** /**
* @deprecated Legacy property used by some extensions for customtext * @deprecated Legacy property used by some extensions for customtext
@@ -78,8 +81,9 @@ export interface ComponentWidget<
readonly props?: P readonly props?: P
} }
export interface DOMWidgetOptions<V extends object | string> export interface DOMWidgetOptions<
extends IWidgetOptions { V extends object | string
> extends IWidgetOptions {
/** /**
* Whether to render a placeholder rectangle when zoomed out. * Whether to render a placeholder rectangle when zoomed out.
*/ */
@@ -286,9 +290,9 @@ export class DOMWidgetImpl<T extends HTMLElement, V extends object | string>
} }
export class ComponentWidgetImpl< export class ComponentWidgetImpl<
V extends object | string, V extends object | string,
P extends ComponentWidgetCustomProps = ComponentWidgetCustomProps P extends ComponentWidgetCustomProps = ComponentWidgetCustomProps
> >
extends BaseDOMWidgetImpl<V> extends BaseDOMWidgetImpl<V>
implements ComponentWidget<V, P> implements ComponentWidget<V, P>
{ {

View File

@@ -535,9 +535,8 @@ export const useDialogService = () => {
return return
} }
const { useSubscriptionDialog } = await import( const { useSubscriptionDialog } =
'@/platform/cloud/subscription/composables/useSubscriptionDialog' await import('@/platform/cloud/subscription/composables/useSubscriptionDialog')
)
const { show } = useSubscriptionDialog() const { show } = useSubscriptionDialog()
show() show()
} }

View File

@@ -5,8 +5,10 @@ import { computed, ref } from 'vue'
import { electronAPI, isElectron } from '@/utils/envUtil' import { electronAPI, isElectron } from '@/utils/envUtil'
export interface ElectronDownload export interface ElectronDownload extends Pick<
extends Pick<DownloadState, 'url' | 'filename'> { DownloadState,
'url' | 'filename'
> {
progress?: number progress?: number
savePath?: string savePath?: string
status?: DownloadStatus status?: DownloadStatus

View File

@@ -549,9 +549,8 @@ export function useConflictDetection() {
async function initializeConflictDetection(): Promise<void> { async function initializeConflictDetection(): Promise<void> {
try { try {
// Check if manager is new Manager before proceeding // Check if manager is new Manager before proceeding
const { useManagerState } = await import( const { useManagerState } =
'@/workbench/extensions/manager/composables/useManagerState' await import('@/workbench/extensions/manager/composables/useManagerState')
)
const managerState = useManagerState() const managerState = useManagerState()
if (!managerState.isNewManagerUI.value) { if (!managerState.isNewManagerUI.value) {

View File

@@ -61,13 +61,6 @@ describe('EssentialsPanel', () => {
const shortcutsList = wrapper.findComponent(ShortcutsList) const shortcutsList = wrapper.findComponent(ShortcutsList)
expect(shortcutsList.exists()).toBe(true) expect(shortcutsList.exists()).toBe(true)
// Should pass only essentials commands
const commands = shortcutsList.props('commands')
expect(commands).toHaveLength(3)
commands.forEach((cmd: ComfyCommandImpl) => {
expect(cmd.category).toBe('essentials')
})
}) })
it('should categorize commands into subcategories', () => { it('should categorize commands into subcategories', () => {

View File

@@ -18,9 +18,8 @@ describe('useConflictAcknowledgment', () => {
describe('initial state loading', () => { describe('initial state loading', () => {
it('should load empty state when localStorage is empty', async () => { it('should load empty state when localStorage is empty', async () => {
vi.resetModules() vi.resetModules()
const { useConflictAcknowledgment } = await import( const { useConflictAcknowledgment } =
'@/workbench/extensions/manager/composables/useConflictAcknowledgment' await import('@/workbench/extensions/manager/composables/useConflictAcknowledgment')
)
const { acknowledgmentState } = useConflictAcknowledgment() const { acknowledgmentState } = useConflictAcknowledgment()
expect(acknowledgmentState.value).toEqual({ expect(acknowledgmentState.value).toEqual({
@@ -44,9 +43,8 @@ describe('useConflictAcknowledgment', () => {
// Need to import the module after localStorage is set // Need to import the module after localStorage is set
vi.resetModules() vi.resetModules()
const { useConflictAcknowledgment } = await import( const { useConflictAcknowledgment } =
'@/workbench/extensions/manager/composables/useConflictAcknowledgment' await import('@/workbench/extensions/manager/composables/useConflictAcknowledgment')
)
const { acknowledgmentState } = useConflictAcknowledgment() const { acknowledgmentState } = useConflictAcknowledgment()
expect(acknowledgmentState.value).toEqual({ expect(acknowledgmentState.value).toEqual({
@@ -60,9 +58,8 @@ describe('useConflictAcknowledgment', () => {
describe('dismissal functions', () => { describe('dismissal functions', () => {
it('should mark conflicts as seen with unified function', async () => { it('should mark conflicts as seen with unified function', async () => {
vi.resetModules() vi.resetModules()
const { useConflictAcknowledgment } = await import( const { useConflictAcknowledgment } =
'@/workbench/extensions/manager/composables/useConflictAcknowledgment' await import('@/workbench/extensions/manager/composables/useConflictAcknowledgment')
)
const { markConflictsAsSeen, acknowledgmentState } = const { markConflictsAsSeen, acknowledgmentState } =
useConflictAcknowledgment() useConflictAcknowledgment()
@@ -73,9 +70,8 @@ describe('useConflictAcknowledgment', () => {
it('should dismiss red dot notification', async () => { it('should dismiss red dot notification', async () => {
vi.resetModules() vi.resetModules()
const { useConflictAcknowledgment } = await import( const { useConflictAcknowledgment } =
'@/workbench/extensions/manager/composables/useConflictAcknowledgment' await import('@/workbench/extensions/manager/composables/useConflictAcknowledgment')
)
const { dismissRedDotNotification, acknowledgmentState } = const { dismissRedDotNotification, acknowledgmentState } =
useConflictAcknowledgment() useConflictAcknowledgment()
@@ -86,9 +82,8 @@ describe('useConflictAcknowledgment', () => {
it('should dismiss warning banner', async () => { it('should dismiss warning banner', async () => {
vi.resetModules() vi.resetModules()
const { useConflictAcknowledgment } = await import( const { useConflictAcknowledgment } =
'@/workbench/extensions/manager/composables/useConflictAcknowledgment' await import('@/workbench/extensions/manager/composables/useConflictAcknowledgment')
)
const { dismissWarningBanner, acknowledgmentState } = const { dismissWarningBanner, acknowledgmentState } =
useConflictAcknowledgment() useConflictAcknowledgment()
@@ -99,9 +94,8 @@ describe('useConflictAcknowledgment', () => {
it('should mark all conflicts as seen', async () => { it('should mark all conflicts as seen', async () => {
vi.resetModules() vi.resetModules()
const { useConflictAcknowledgment } = await import( const { useConflictAcknowledgment } =
'@/workbench/extensions/manager/composables/useConflictAcknowledgment' await import('@/workbench/extensions/manager/composables/useConflictAcknowledgment')
)
const { markConflictsAsSeen, acknowledgmentState } = const { markConflictsAsSeen, acknowledgmentState } =
useConflictAcknowledgment() useConflictAcknowledgment()
@@ -117,9 +111,8 @@ describe('useConflictAcknowledgment', () => {
it('should calculate shouldShowConflictModal correctly', async () => { it('should calculate shouldShowConflictModal correctly', async () => {
// Need fresh module import to ensure clean state // Need fresh module import to ensure clean state
vi.resetModules() vi.resetModules()
const { useConflictAcknowledgment } = await import( const { useConflictAcknowledgment } =
'@/workbench/extensions/manager/composables/useConflictAcknowledgment' await import('@/workbench/extensions/manager/composables/useConflictAcknowledgment')
)
const { shouldShowConflictModal, markConflictsAsSeen } = const { shouldShowConflictModal, markConflictsAsSeen } =
useConflictAcknowledgment() useConflictAcknowledgment()
@@ -131,9 +124,8 @@ describe('useConflictAcknowledgment', () => {
it('should calculate shouldShowRedDot correctly based on conflicts', async () => { it('should calculate shouldShowRedDot correctly based on conflicts', async () => {
vi.resetModules() vi.resetModules()
const { useConflictAcknowledgment } = await import( const { useConflictAcknowledgment } =
'@/workbench/extensions/manager/composables/useConflictAcknowledgment' await import('@/workbench/extensions/manager/composables/useConflictAcknowledgment')
)
const { shouldShowRedDot, dismissRedDotNotification } = const { shouldShowRedDot, dismissRedDotNotification } =
useConflictAcknowledgment() useConflictAcknowledgment()
@@ -146,9 +138,8 @@ describe('useConflictAcknowledgment', () => {
it('should calculate shouldShowManagerBanner correctly', async () => { it('should calculate shouldShowManagerBanner correctly', async () => {
vi.resetModules() vi.resetModules()
const { useConflictAcknowledgment } = await import( const { useConflictAcknowledgment } =
'@/workbench/extensions/manager/composables/useConflictAcknowledgment' await import('@/workbench/extensions/manager/composables/useConflictAcknowledgment')
)
const { shouldShowManagerBanner, dismissWarningBanner } = const { shouldShowManagerBanner, dismissWarningBanner } =
useConflictAcknowledgment() useConflictAcknowledgment()
@@ -164,9 +155,8 @@ describe('useConflictAcknowledgment', () => {
it('should persist to localStorage automatically', async () => { it('should persist to localStorage automatically', async () => {
// Need fresh module import to ensure clean state // Need fresh module import to ensure clean state
vi.resetModules() vi.resetModules()
const { useConflictAcknowledgment } = await import( const { useConflictAcknowledgment } =
'@/workbench/extensions/manager/composables/useConflictAcknowledgment' await import('@/workbench/extensions/manager/composables/useConflictAcknowledgment')
)
const { markConflictsAsSeen, dismissWarningBanner } = const { markConflictsAsSeen, dismissWarningBanner } =
useConflictAcknowledgment() useConflictAcknowledgment()

View File

@@ -153,9 +153,8 @@ vi.mock('@/platform/workflow/management/stores/workflowStore', () => ({
})) }))
})) }))
const { useMinimap } = await import( const { useMinimap } =
'@/renderer/extensions/minimap/composables/useMinimap' await import('@/renderer/extensions/minimap/composables/useMinimap')
)
const { api } = await import('@/scripts/api') const { api } = await import('@/scripts/api')
describe('useMinimap', () => { describe('useMinimap', () => {

View File

@@ -29,9 +29,8 @@ vi.mock('@/platform/telemetry', () => ({
})) }))
})) }))
const { useTemplateFiltering } = await import( const { useTemplateFiltering } =
'@/composables/useTemplateFiltering' await import('@/composables/useTemplateFiltering')
)
describe('useTemplateFiltering', () => { describe('useTemplateFiltering', () => {
beforeEach(() => { beforeEach(() => {

View File

@@ -103,9 +103,8 @@ describe('useMinimapRenderer', () => {
}) })
it('should only render when redraw is needed', async () => { it('should only render when redraw is needed', async () => {
const { renderMinimapToCanvas } = await import( const { renderMinimapToCanvas } =
'@/renderer/extensions/minimap/minimapCanvasRenderer' await import('@/renderer/extensions/minimap/minimapCanvasRenderer')
)
const canvasRef = ref(mockCanvas) const canvasRef = ref(mockCanvas)
const graphRef = ref(mockGraph as any) const graphRef = ref(mockGraph as any)
const boundsRef = ref({ minX: 0, minY: 0, width: 100, height: 100 }) const boundsRef = ref({ minX: 0, minY: 0, width: 100, height: 100 })

View File

@@ -66,9 +66,8 @@ describe('useMinimapViewport', () => {
}) })
it('should calculate graph bounds from nodes', async () => { it('should calculate graph bounds from nodes', async () => {
const { calculateNodeBounds, enforceMinimumBounds } = await import( const { calculateNodeBounds, enforceMinimumBounds } =
'@/renderer/core/spatial/boundsCalculator' await import('@/renderer/core/spatial/boundsCalculator')
)
vi.mocked(calculateNodeBounds).mockReturnValue({ vi.mocked(calculateNodeBounds).mockReturnValue({
minX: 100, minX: 100,
@@ -93,9 +92,8 @@ describe('useMinimapViewport', () => {
}) })
it('should handle empty graph', async () => { it('should handle empty graph', async () => {
const { calculateNodeBounds } = await import( const { calculateNodeBounds } =
'@/renderer/core/spatial/boundsCalculator' await import('@/renderer/core/spatial/boundsCalculator')
)
vi.mocked(calculateNodeBounds).mockReturnValue(null) vi.mocked(calculateNodeBounds).mockReturnValue(null)

View File

@@ -19,12 +19,10 @@ vi.mock('@/scripts/api', () => ({
} }
})) }))
const { useWorkflowThumbnail } = await import( const { useWorkflowThumbnail } =
'@/renderer/core/thumbnail/useWorkflowThumbnail' await import('@/renderer/core/thumbnail/useWorkflowThumbnail')
) const { createGraphThumbnail } =
const { createGraphThumbnail } = await import( await import('@/renderer/core/thumbnail/graphThumbnailRenderer')
'@/renderer/core/thumbnail/graphThumbnailRenderer'
)
const { api } = await import('@/scripts/api') const { api } = await import('@/scripts/api')
describe('useWorkflowThumbnail', () => { describe('useWorkflowThumbnail', () => {

View File

@@ -62,9 +62,8 @@ describe('useReleaseStore', () => {
} }
// Setup mock implementations // Setup mock implementations
const { useReleaseService } = await import( const { useReleaseService } =
'@/platform/updates/common/releaseService' await import('@/platform/updates/common/releaseService')
)
const { useSettingStore } = await import('@/platform/settings/settingStore') const { useSettingStore } = await import('@/platform/settings/settingStore')
const { useSystemStatsStore } = await import('@/stores/systemStatsStore') const { useSystemStatsStore } = await import('@/stores/systemStatsStore')
const { isElectron } = await import('@/utils/envUtil') const { isElectron } = await import('@/utils/envUtil')

View File

@@ -287,9 +287,8 @@ describe('versionUtil', () => {
vi.resetModules() vi.resetModules()
// Import fresh module // Import fresh module
const versionUtil = await import( const versionUtil =
'@/workbench/extensions/manager/utils/versionUtil' await import('@/workbench/extensions/manager/utils/versionUtil')
)
const version = versionUtil.getFrontendVersion() const version = versionUtil.getFrontendVersion()
expect(version).toBe('2.0.0') expect(version).toBe('2.0.0')
@@ -322,9 +321,8 @@ describe('versionUtil', () => {
vi.resetModules() vi.resetModules()
// Import fresh module // Import fresh module
const versionUtil = await import( const versionUtil =
'@/workbench/extensions/manager/utils/versionUtil' await import('@/workbench/extensions/manager/utils/versionUtil')
)
const version = versionUtil.getFrontendVersion() const version = versionUtil.getFrontendVersion()
expect(version).toBeUndefined() expect(version).toBeUndefined()