initial migration to TS
This commit is contained in:
235
frontend/src/types.ts
Normal file
235
frontend/src/types.ts
Normal file
@@ -0,0 +1,235 @@
|
||||
import type { Node, Edge } from '@xyflow/react';
|
||||
import type { CSSProperties } from 'react';
|
||||
|
||||
// ── Input Specifications ─────────────────────────────────────────────
|
||||
|
||||
export interface InputOptions {
|
||||
label?: string;
|
||||
hidden?: boolean;
|
||||
socket_only?: boolean;
|
||||
accepted_types?: string[];
|
||||
default?: unknown;
|
||||
placeholder?: string;
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
slider?: boolean;
|
||||
min_widget?: string;
|
||||
max_widget?: string;
|
||||
text_input?: boolean;
|
||||
color_picker?: boolean;
|
||||
colormap_stops?: boolean;
|
||||
set_widgets?: Record<string, unknown>;
|
||||
show_when_source_type?: Record<string, string[]>;
|
||||
show_when_widget_value?: Record<string, unknown[]>;
|
||||
show_when_input_visible?: string | string[];
|
||||
hide_when_input_connected?: string | string[];
|
||||
choices_by_source_type?: Record<string, string[]>;
|
||||
choices_from_table_input?: string;
|
||||
choices_from_measure_input?: string;
|
||||
inline_with_input?: string | [string];
|
||||
source_type_input?: string;
|
||||
placement?: 'top';
|
||||
}
|
||||
|
||||
/** An input spec is either a bare type string, or a [type, opts] tuple. */
|
||||
export type InputSpec = string | [type: string | string[], opts?: InputOptions];
|
||||
|
||||
// ── Node Definition (from GET /nodes) ────────────────────────────────
|
||||
|
||||
export interface NodeDefinition {
|
||||
input: {
|
||||
required: Record<string, InputSpec>;
|
||||
optional: Record<string, InputSpec>;
|
||||
};
|
||||
output: string[];
|
||||
output_name: string[];
|
||||
output_paths?: string[];
|
||||
category: string;
|
||||
manual_trigger?: boolean;
|
||||
}
|
||||
|
||||
export type NodeDefsRegistry = Record<string, NodeDefinition>;
|
||||
|
||||
// ── Overlay Types ────────────────────────────────────────────────────
|
||||
|
||||
export interface OverlayData {
|
||||
kind: string;
|
||||
image?: string;
|
||||
image_width?: number;
|
||||
image_height?: number;
|
||||
x1?: number;
|
||||
y1?: number;
|
||||
x2?: number;
|
||||
y2?: number;
|
||||
xm?: number;
|
||||
ym?: number;
|
||||
a_locked?: boolean;
|
||||
b_locked?: boolean;
|
||||
section_title?: string;
|
||||
line?: number[];
|
||||
shape?: string;
|
||||
stroke_color?: string;
|
||||
stroke_width?: number;
|
||||
angle_deg?: number;
|
||||
color?: string;
|
||||
label_dx?: number;
|
||||
label_dy?: number;
|
||||
line_thickness?: number;
|
||||
histogram?: unknown;
|
||||
}
|
||||
|
||||
// ── Preview Image Types ──────────────────────────────────────────────
|
||||
|
||||
export interface PreviewPanel {
|
||||
kind: 'image' | 'line_plot';
|
||||
title?: string;
|
||||
image?: string;
|
||||
line?: number[];
|
||||
fallback_image?: string;
|
||||
}
|
||||
|
||||
export interface PreviewPayload {
|
||||
kind: 'image' | 'line_plot' | 'layer_gallery' | 'panels';
|
||||
image?: string;
|
||||
line?: number[];
|
||||
layers?: Array<{ name?: string; image: string }>;
|
||||
fallback_image?: string;
|
||||
panels?: PreviewPanel[];
|
||||
}
|
||||
|
||||
export type PreviewImage = string | PreviewPayload;
|
||||
|
||||
// ── Node Data (attached to each ReactFlow node) ──────────────────────
|
||||
|
||||
export interface GroupProxy {
|
||||
handleId: string;
|
||||
type: string;
|
||||
label: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface NodeData extends Record<string, unknown> {
|
||||
label: string;
|
||||
className: string;
|
||||
definition?: NodeDefinition | null;
|
||||
widgetValues: Record<string, unknown>;
|
||||
runtimeValues?: Record<string, unknown>;
|
||||
|
||||
// Execution results
|
||||
previewImage?: PreviewImage | null;
|
||||
tableRows?: Array<Record<string, unknown>> | null;
|
||||
scalarValue?: number | { value: number | string; unit?: string } | null;
|
||||
meshData?: unknown;
|
||||
overlay?: OverlayData | null;
|
||||
|
||||
// Status
|
||||
error?: string | null;
|
||||
warning?: string | null;
|
||||
processingTimeMs?: number | null;
|
||||
|
||||
// Group node fields
|
||||
proxyInputs?: GroupProxy[];
|
||||
proxyOutputs?: GroupProxy[];
|
||||
childCount?: number;
|
||||
collapsed?: boolean;
|
||||
expandedSize?: { width: number; height: number };
|
||||
|
||||
// Serialization extras
|
||||
extraData?: Record<string, unknown>;
|
||||
output?: string[];
|
||||
output_name?: string[];
|
||||
}
|
||||
|
||||
// ── ReactFlow Node & Edge ────────────────────────────────────────────
|
||||
|
||||
export type TonoNode = Node<NodeData, 'custom'>;
|
||||
export type TonoEdge = Edge<{
|
||||
groupProxyOwner?: string;
|
||||
groupProxyOriginal?: {
|
||||
source?: string;
|
||||
sourceHandle?: string;
|
||||
target?: string;
|
||||
targetHandle?: string;
|
||||
};
|
||||
}>;
|
||||
|
||||
// ── Serialized Workflow ──────────────────────────────────────────────
|
||||
|
||||
export interface SerializedNode {
|
||||
id: string;
|
||||
type?: string;
|
||||
position: { x: number; y: number };
|
||||
width?: number;
|
||||
height?: number;
|
||||
className?: string;
|
||||
parentId?: string;
|
||||
extent?: [[number, number], [number, number]];
|
||||
hidden?: boolean;
|
||||
style?: CSSProperties;
|
||||
dragHandle?: string;
|
||||
data: {
|
||||
label: string;
|
||||
className: string;
|
||||
widgetValues: Record<string, unknown>;
|
||||
runtimeValues?: Record<string, unknown>;
|
||||
extraData?: Record<string, unknown>;
|
||||
output?: string[];
|
||||
output_name?: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface SerializedEdge {
|
||||
id: string;
|
||||
source: string;
|
||||
sourceHandle?: string;
|
||||
target: string;
|
||||
targetHandle?: string;
|
||||
style?: CSSProperties;
|
||||
hidden?: boolean;
|
||||
data?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface SerializedWorkflow {
|
||||
version: number;
|
||||
nodes: SerializedNode[];
|
||||
edges: SerializedEdge[];
|
||||
packed?: boolean;
|
||||
packedFiles?: Record<string, { filename: string; data: string }>;
|
||||
}
|
||||
|
||||
// ── WebSocket Messages ───────────────────────────────────────────────
|
||||
|
||||
export type WsMessage =
|
||||
| { type: 'execution_start'; data: { prompt_id: string } }
|
||||
| { type: 'executing'; data: { node: string; prompt_id: string } }
|
||||
| { type: 'execution_complete'; data: { prompt_id: string } }
|
||||
| { type: 'execution_error'; data: { node_id: string; message: string } }
|
||||
| { type: 'preview'; data: { node_id: string; image: PreviewImage } }
|
||||
| { type: 'table'; data: { node_id: string; rows: Array<Record<string, unknown>> } }
|
||||
| { type: 'scalar'; data: { node_id: string; value: number | string; unit?: string } }
|
||||
| { type: 'node_timing'; data: { node_id: string; elapsed_ms: number } }
|
||||
| { type: 'mesh3d'; data: { node_id: string; mesh: unknown } }
|
||||
| { type: 'overlay'; data: { node_id: string; overlay: OverlayData } }
|
||||
| { type: 'node_warning'; data: { node_id: string; message: string } }
|
||||
| { type: 'nodes_updated'; data: Record<string, never> };
|
||||
|
||||
// ── Widget description (used by nodeWidgetLayout) ────────────────────
|
||||
|
||||
export interface WidgetDescriptor {
|
||||
name: string;
|
||||
type: string | string[];
|
||||
opts: InputOptions;
|
||||
socketType?: string;
|
||||
}
|
||||
|
||||
// ── Node Context (provided by App to CustomNode) ─────────────────────
|
||||
|
||||
export interface NodeContextValue {
|
||||
executingNodeId: string | null;
|
||||
onWidgetChange: (nodeId: string, name: string, value: unknown) => void;
|
||||
openFileBrowser: (callback: (files: File[]) => void, options?: unknown) => void;
|
||||
openHelp: (label: string) => void;
|
||||
getTableColumns: (nodeId: string, inputName: string) => string[];
|
||||
getMeasurementChoices: (nodeId: string, inputName: string) => string[];
|
||||
}
|
||||
Reference in New Issue
Block a user