mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-06 13:40:25 +00:00
knip: YOLO pass, all the unused exports enabled, YAGNI for the rest (#5313)
* knip: Enable unusedBinaries, add two exceptions * knip: YOLO pass, all the unused exports enabled. Paired with @christian-byrne to allow for some special cases to remain with custom knip ignore tags. * knip: remove post-rebase
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import type { Rectangle } from './infrastructure/Rectangle'
|
||||
import type { CanvasColour, Rect } from './interfaces'
|
||||
import { LiteGraph } from './litegraph'
|
||||
import { LinkDirection, RenderShape, TitleMode } from './types/globalEnums'
|
||||
import { RenderShape, TitleMode } from './types/globalEnums'
|
||||
|
||||
const ELLIPSIS = '\u2026'
|
||||
const TWO_DOT_LEADER = '\u2025'
|
||||
@@ -22,12 +22,7 @@ export enum SlotShape {
|
||||
}
|
||||
|
||||
/** @see LinkDirection */
|
||||
export enum SlotDirection {
|
||||
Up = LinkDirection.UP,
|
||||
Right = LinkDirection.RIGHT,
|
||||
Down = LinkDirection.DOWN,
|
||||
Left = LinkDirection.LEFT
|
||||
}
|
||||
export enum SlotDirection {}
|
||||
|
||||
export enum LabelPosition {
|
||||
Left = 'left',
|
||||
|
||||
@@ -278,9 +278,6 @@ export type KeysOfType<T, Match> = Exclude<
|
||||
undefined
|
||||
>
|
||||
|
||||
/** A new type that contains only the properties of T that are of type Match */
|
||||
export type PickByType<T, Match> = { [P in keyof T]: Extract<T[P], Match> }
|
||||
|
||||
/** The names of all (optional) methods and functions in T */
|
||||
export type MethodNames<T> = KeysOfType<T, ((...args: any) => any) | undefined>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { ContextMenu } from './ContextMenu'
|
||||
import type { LGraphNode } from './LGraphNode'
|
||||
import { LiteGraphGlobal } from './LiteGraphGlobal'
|
||||
import type { ConnectingLink, Point } from './interfaces'
|
||||
import type { IContextMenuOptions, INodeSlot, Size } from './interfaces'
|
||||
import type { IContextMenuOptions, Size } from './interfaces'
|
||||
import { loadPolyfills } from './polyfills'
|
||||
import type { CanvasEventDetail } from './types/events'
|
||||
import type { RenderShape, TitleMode } from './types/globalEnums'
|
||||
@@ -22,8 +22,6 @@ loadPolyfills()
|
||||
// Definitions by: NateScarlet <https://github.com/NateScarlet>
|
||||
/** @deprecated Use {@link Point} instead. */
|
||||
export type Vector2 = Point
|
||||
/** @deprecated Use {@link Rect} instead. */
|
||||
export type Vector4 = [number, number, number, number]
|
||||
|
||||
export interface IContextMenuItem {
|
||||
content: string
|
||||
@@ -46,14 +44,6 @@ export type ContextMenuEventListener = (
|
||||
node: LGraphNode
|
||||
) => boolean | void
|
||||
|
||||
export interface LinkReleaseContext {
|
||||
node_to?: LGraphNode
|
||||
node_from?: LGraphNode
|
||||
slot_from: INodeSlot
|
||||
type_filter_in?: string
|
||||
type_filter_out?: string
|
||||
}
|
||||
|
||||
export interface LinkReleaseContextExtended {
|
||||
links: ConnectingLink[]
|
||||
}
|
||||
@@ -117,7 +107,6 @@ export type {
|
||||
LinkNetwork,
|
||||
LinkSegment,
|
||||
MethodNames,
|
||||
PickByType,
|
||||
Point,
|
||||
Positionable,
|
||||
ReadonlyLinkNetwork,
|
||||
|
||||
@@ -84,10 +84,6 @@ export function isINodeInputSlot(slot: INodeSlot): slot is INodeInputSlot {
|
||||
return 'link' in slot
|
||||
}
|
||||
|
||||
export function isINodeOutputSlot(slot: INodeSlot): slot is INodeOutputSlot {
|
||||
return 'links' in slot
|
||||
}
|
||||
|
||||
/**
|
||||
* Type guard: Whether this input slot is attached to a widget.
|
||||
* @param slot The slot to check.
|
||||
|
||||
@@ -50,9 +50,6 @@ export interface CanvasMouseEvent
|
||||
Readonly<CanvasPointerExtensions>,
|
||||
LegacyMouseEvent {}
|
||||
|
||||
/** DragEvent with canvasX/Y and deltaX/Y properties */
|
||||
export interface CanvasDragEvent extends DragEvent, CanvasPointerExtensions {}
|
||||
|
||||
export type CanvasEventDetail =
|
||||
| GenericEventDetail
|
||||
| GroupDoubleClickEventDetail
|
||||
|
||||
@@ -89,9 +89,6 @@ export enum LGraphEventMode {
|
||||
}
|
||||
|
||||
export enum EaseFunction {
|
||||
LINEAR = 'linear',
|
||||
EASE_IN_QUAD = 'easeInQuad',
|
||||
EASE_OUT_QUAD = 'easeOutQuad',
|
||||
EASE_IN_OUT_QUAD = 'easeInOutQuad'
|
||||
}
|
||||
|
||||
|
||||
@@ -179,14 +179,6 @@ export interface ISerialisedGroup {
|
||||
flags?: IGraphGroupFlags
|
||||
}
|
||||
|
||||
export type TClipboardLink = [
|
||||
targetRelativeIndex: number,
|
||||
originSlot: number,
|
||||
nodeRelativeIndex: number,
|
||||
targetSlot: number,
|
||||
targetNodeId: NodeId
|
||||
]
|
||||
|
||||
/** Items copied from the canvas */
|
||||
export interface ClipboardItems {
|
||||
nodes?: ISerialisedNode[]
|
||||
@@ -196,12 +188,6 @@ export interface ClipboardItems {
|
||||
subgraphs?: ExportedSubgraph[]
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
export interface IClipboardContents {
|
||||
nodes?: ISerialisedNode[]
|
||||
links?: TClipboardLink[]
|
||||
}
|
||||
|
||||
export interface SerialisableReroute {
|
||||
id: RerouteId
|
||||
parentId?: RerouteId
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
||||
import type { LinkId } from '@/lib/litegraph/src/LLink'
|
||||
import { parseSlotTypes } from '@/lib/litegraph/src/strings'
|
||||
|
||||
import type { ConnectingLink, ISlotType, Positionable } from '../interfaces'
|
||||
import type { ISlotType, Positionable } from '../interfaces'
|
||||
|
||||
/**
|
||||
* Creates a flat set of all positionable items by recursively iterating through all child items.
|
||||
@@ -45,19 +44,6 @@ export function findFirstNode(
|
||||
}
|
||||
}
|
||||
|
||||
/** @returns `true` if the provided link ID is currently being dragged. */
|
||||
export function isDraggingLink(
|
||||
linkId: LinkId,
|
||||
connectingLinks: ConnectingLink[] | null | undefined
|
||||
): ConnectingLink | undefined {
|
||||
if (connectingLinks == null) return
|
||||
|
||||
for (const connectingLink of connectingLinks) {
|
||||
if (connectingLink.link == null) continue
|
||||
if (linkId === connectingLink.link.id) return connectingLink
|
||||
}
|
||||
}
|
||||
|
||||
type FreeSlotResult<T extends { type: ISlotType }> =
|
||||
| { index: number; slot: T }
|
||||
| undefined
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
||||
import type {
|
||||
IBaseWidget,
|
||||
IBooleanWidget,
|
||||
IButtonWidget,
|
||||
IComboWidget,
|
||||
ICustomWidget,
|
||||
IKnobWidget,
|
||||
INumericWidget,
|
||||
ISliderWidget,
|
||||
IStringWidget,
|
||||
IWidget,
|
||||
TWidgetType
|
||||
} from '@/lib/litegraph/src/types/widgets'
|
||||
@@ -130,49 +123,9 @@ export function toConcreteWidget<TWidget extends IWidget | IBaseWidget>(
|
||||
|
||||
// #region Type Guards
|
||||
|
||||
/** Type guard: Narrow **from {@link IBaseWidget}** to {@link IButtonWidget}. */
|
||||
export function isButtonWidget(widget: IBaseWidget): widget is IButtonWidget {
|
||||
return widget.type === 'button'
|
||||
}
|
||||
|
||||
/** Type guard: Narrow **from {@link IBaseWidget}** to {@link IBooleanWidget}. */
|
||||
export function isBooleanWidget(widget: IBaseWidget): widget is IBooleanWidget {
|
||||
return widget.type === 'toggle'
|
||||
}
|
||||
|
||||
/** Type guard: Narrow **from {@link IBaseWidget}** to {@link ISliderWidget}. */
|
||||
export function isSliderWidget(widget: IBaseWidget): widget is ISliderWidget {
|
||||
return widget.type === 'slider'
|
||||
}
|
||||
|
||||
/** Type guard: Narrow **from {@link IBaseWidget}** to {@link IKnobWidget}. */
|
||||
export function isKnobWidget(widget: IBaseWidget): widget is IKnobWidget {
|
||||
return widget.type === 'knob'
|
||||
}
|
||||
|
||||
/** Type guard: Narrow **from {@link IBaseWidget}** to {@link IComboWidget}. */
|
||||
export function isComboWidget(widget: IBaseWidget): widget is IComboWidget {
|
||||
return widget.type === 'combo'
|
||||
}
|
||||
|
||||
/** Type guard: Narrow **from {@link IBaseWidget}** to {@link INumericWidget}. */
|
||||
export function isNumberWidget(widget: IBaseWidget): widget is INumericWidget {
|
||||
return widget.type === 'number'
|
||||
}
|
||||
|
||||
/** Type guard: Narrow **from {@link IBaseWidget}** to {@link IStringWidget}. */
|
||||
export function isStringWidget(widget: IBaseWidget): widget is IStringWidget {
|
||||
return widget.type === 'string'
|
||||
}
|
||||
|
||||
/** Type guard: Narrow **from {@link IBaseWidget}** to {@link ITextWidget}. */
|
||||
export function isTextWidget(widget: IBaseWidget): widget is IStringWidget {
|
||||
return widget.type === 'text'
|
||||
}
|
||||
|
||||
/** Type guard: Narrow **from {@link IBaseWidget}** to {@link ICustomWidget}. */
|
||||
export function isCustomWidget(widget: IBaseWidget): widget is ICustomWidget {
|
||||
return widget.type === 'custom'
|
||||
}
|
||||
|
||||
// #endregion Type Guards
|
||||
|
||||
@@ -169,140 +169,3 @@ export const subgraphTest = test.extend<SubgraphFixtures>({
|
||||
capture.cleanup()
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Fixtures that test edge cases and error conditions.
|
||||
* These may leave the system in an invalid state and should be used carefully.
|
||||
*/
|
||||
export interface EdgeCaseFixtures {
|
||||
/** Subgraph with circular references (for testing recursion detection) */
|
||||
circularSubgraph: {
|
||||
rootGraph: LGraph
|
||||
subgraphA: Subgraph
|
||||
subgraphB: Subgraph
|
||||
nodeA: SubgraphNode
|
||||
nodeB: SubgraphNode
|
||||
}
|
||||
|
||||
/** Deeply nested subgraphs approaching the theoretical limit */
|
||||
deeplyNestedSubgraph: ReturnType<typeof createNestedSubgraphs>
|
||||
|
||||
/** Subgraph with maximum inputs and outputs */
|
||||
maxIOSubgraph: Subgraph
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with edge case fixtures. Use sparingly and with caution.
|
||||
* These tests may intentionally create invalid states.
|
||||
*/
|
||||
export const edgeCaseTest = subgraphTest.extend<EdgeCaseFixtures>({
|
||||
// @ts-expect-error TODO: Fix after merge - fixture use parameter type
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
circularSubgraph: async ({}, use: (value: unknown) => Promise<void>) => {
|
||||
const rootGraph = new LGraph()
|
||||
|
||||
// Create two subgraphs that will reference each other
|
||||
const subgraphA = createTestSubgraph({
|
||||
name: 'Subgraph A',
|
||||
inputs: [{ name: 'input', type: '*' }],
|
||||
outputs: [{ name: 'output', type: '*' }]
|
||||
})
|
||||
|
||||
const subgraphB = createTestSubgraph({
|
||||
name: 'Subgraph B',
|
||||
inputs: [{ name: 'input', type: '*' }],
|
||||
outputs: [{ name: 'output', type: '*' }]
|
||||
})
|
||||
|
||||
// Create instances (this doesn't create circular refs by itself)
|
||||
const nodeA = createTestSubgraphNode(subgraphA, { pos: [100, 100] })
|
||||
const nodeB = createTestSubgraphNode(subgraphB, { pos: [300, 100] })
|
||||
|
||||
// Add nodes to root graph
|
||||
rootGraph.add(nodeA)
|
||||
rootGraph.add(nodeB)
|
||||
|
||||
await use({
|
||||
rootGraph,
|
||||
subgraphA,
|
||||
subgraphB,
|
||||
nodeA,
|
||||
nodeB
|
||||
})
|
||||
},
|
||||
|
||||
// @ts-expect-error TODO: Fix after merge - fixture use parameter type
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
deeplyNestedSubgraph: async ({}, use: (value: unknown) => Promise<void>) => {
|
||||
// Create a very deep nesting structure (but not exceeding MAX_NESTED_SUBGRAPHS)
|
||||
const nested = createNestedSubgraphs({
|
||||
depth: 50, // Deep but reasonable
|
||||
nodesPerLevel: 1,
|
||||
inputsPerSubgraph: 1,
|
||||
outputsPerSubgraph: 1
|
||||
})
|
||||
|
||||
await use(nested)
|
||||
},
|
||||
|
||||
// @ts-expect-error TODO: Fix after merge - fixture use parameter type
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
maxIOSubgraph: async ({}, use: (value: unknown) => Promise<void>) => {
|
||||
// Create a subgraph with many inputs and outputs
|
||||
const inputs = Array.from({ length: 20 }, (_, i) => ({
|
||||
name: `input_${i}`,
|
||||
type: i % 2 === 0 ? 'number' : ('string' as const)
|
||||
}))
|
||||
|
||||
const outputs = Array.from({ length: 20 }, (_, i) => ({
|
||||
name: `output_${i}`,
|
||||
type: i % 2 === 0 ? 'number' : ('string' as const)
|
||||
}))
|
||||
|
||||
const subgraph = createTestSubgraph({
|
||||
name: 'Max IO Subgraph',
|
||||
inputs,
|
||||
outputs,
|
||||
nodeCount: 10
|
||||
})
|
||||
|
||||
await use(subgraph)
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Helper to verify fixture integrity.
|
||||
* Use this in tests to ensure fixtures are properly set up.
|
||||
*/
|
||||
export function verifyFixtureIntegrity<T extends Record<string, unknown>>(
|
||||
fixture: T,
|
||||
expectedProperties: (keyof T)[]
|
||||
): void {
|
||||
for (const prop of expectedProperties) {
|
||||
if (!(prop in fixture)) {
|
||||
throw new Error(`Fixture missing required property: ${String(prop)}`)
|
||||
}
|
||||
if (fixture[prop] === undefined || fixture[prop] === null) {
|
||||
throw new Error(`Fixture property ${String(prop)} is null or undefined`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a snapshot-friendly representation of a subgraph for testing.
|
||||
* Useful for serialization tests and regression detection.
|
||||
*/
|
||||
export function createSubgraphSnapshot(subgraph: Subgraph) {
|
||||
return {
|
||||
id: subgraph.id,
|
||||
name: subgraph.name,
|
||||
inputCount: subgraph.inputs.length,
|
||||
outputCount: subgraph.outputs.length,
|
||||
nodeCount: subgraph.nodes.length,
|
||||
linkCount: subgraph.links.size,
|
||||
inputs: subgraph.inputs.map((i) => ({ name: i.name, type: i.type })),
|
||||
outputs: subgraph.outputs.map((o) => ({ name: o.name, type: o.type })),
|
||||
hasInputNode: !!subgraph.inputNode,
|
||||
hasOutputNode: !!subgraph.outputNode
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,76 +382,6 @@ export function createTestSubgraphData(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a complex subgraph with multiple nodes and connections.
|
||||
* Useful for testing realistic scenarios.
|
||||
* @param nodeCount Number of internal nodes to create
|
||||
* @returns Complex subgraph data structure
|
||||
*/
|
||||
export function createComplexSubgraphData(
|
||||
nodeCount: number = 5
|
||||
): ExportedSubgraph {
|
||||
const nodes = []
|
||||
const links: Record<
|
||||
string,
|
||||
{
|
||||
id: number
|
||||
origin_id: number
|
||||
origin_slot: number
|
||||
target_id: number
|
||||
target_slot: number
|
||||
type: string
|
||||
}
|
||||
> = {}
|
||||
|
||||
// Create internal nodes
|
||||
for (let i = 0; i < nodeCount; i++) {
|
||||
nodes.push({
|
||||
id: i + 1, // Start from 1 to avoid conflicts with IO nodes
|
||||
type: 'basic/test',
|
||||
pos: [100 + i * 150, 200],
|
||||
size: [120, 60],
|
||||
inputs: [{ name: 'in', type: '*', link: null }],
|
||||
outputs: [{ name: 'out', type: '*', links: [] }],
|
||||
properties: { value: i },
|
||||
flags: {},
|
||||
mode: 0
|
||||
})
|
||||
}
|
||||
|
||||
// Create some internal links
|
||||
for (let i = 0; i < nodeCount - 1; i++) {
|
||||
const linkId = i + 1
|
||||
links[linkId] = {
|
||||
id: linkId,
|
||||
origin_id: i + 1,
|
||||
origin_slot: 0,
|
||||
target_id: i + 2,
|
||||
target_slot: 0,
|
||||
type: '*'
|
||||
}
|
||||
}
|
||||
|
||||
return createTestSubgraphData({
|
||||
// @ts-expect-error TODO: Fix after merge - nodes parameter type
|
||||
nodes,
|
||||
// @ts-expect-error TODO: Fix after merge - links parameter type
|
||||
links,
|
||||
inputs: [
|
||||
// @ts-expect-error TODO: Fix after merge - input object type
|
||||
{ name: 'input1', type: 'number', pos: [0, 0] },
|
||||
// @ts-expect-error TODO: Fix after merge - input object type
|
||||
{ name: 'input2', type: 'string', pos: [0, 1] }
|
||||
],
|
||||
outputs: [
|
||||
// @ts-expect-error TODO: Fix after merge - output object type
|
||||
{ name: 'output1', type: 'number', pos: [0, 0] },
|
||||
// @ts-expect-error TODO: Fix after merge - output object type
|
||||
{ name: 'output2', type: 'string', pos: [0, 1] }
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an event capture system for testing event sequences.
|
||||
* @param eventTarget The event target to monitor
|
||||
@@ -493,39 +423,5 @@ export function createEventCapture<T = unknown>(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility to log subgraph structure for debugging tests.
|
||||
* @param subgraph The subgraph to inspect
|
||||
* @param label Optional label for the log output
|
||||
*/
|
||||
export function logSubgraphStructure(
|
||||
subgraph: Subgraph,
|
||||
label: string = 'Subgraph'
|
||||
): void {
|
||||
console.log(`\n=== ${label} Structure ===`)
|
||||
console.log(`Name: ${subgraph.name}`)
|
||||
console.log(`ID: ${subgraph.id}`)
|
||||
console.log(`Inputs: ${subgraph.inputs.length}`)
|
||||
console.log(`Outputs: ${subgraph.outputs.length}`)
|
||||
console.log(`Nodes: ${subgraph.nodes.length}`)
|
||||
console.log(`Links: ${subgraph.links.size}`)
|
||||
|
||||
if (subgraph.inputs.length > 0) {
|
||||
console.log(
|
||||
'Input details:',
|
||||
subgraph.inputs.map((i) => ({ name: i.name, type: i.type }))
|
||||
)
|
||||
}
|
||||
|
||||
if (subgraph.outputs.length > 0) {
|
||||
console.log(
|
||||
'Output details:',
|
||||
subgraph.outputs.map((o) => ({ name: o.name, type: o.type }))
|
||||
)
|
||||
}
|
||||
|
||||
console.log('========================\n')
|
||||
}
|
||||
|
||||
// Re-export expect from vitest for convenience
|
||||
export { expect } from 'vitest'
|
||||
|
||||
Reference in New Issue
Block a user