refactor: split ui/runtime/serialized node types

Closes #6
This commit is contained in:
Max Richter
2025-12-03 19:18:56 +01:00
parent 1126cf8f9f
commit 7ae1fae3b9
24 changed files with 306 additions and 343 deletions

View File

@@ -1,4 +1,4 @@
import type { Graph, NodeDefinition, NodeType } from "./types";
import type { Graph, NodeDefinition, NodeId } from "./types";
export interface NodeRegistry {
/**
@@ -13,13 +13,13 @@ export interface NodeRegistry {
* @throws An error if the nodes could not be loaded
* @remarks This method should be called before calling getNode or getAllNodes
*/
load: (nodeIds: NodeType[]) => Promise<NodeDefinition[]>;
load: (nodeIds: NodeId[]) => Promise<NodeDefinition[]>;
/**
* Get a node by id
* @param id - The id of the node to get
* @returns The node with the given id, or undefined if no such node exists
*/
getNode: (id: NodeType | string) => NodeDefinition | undefined;
getNode: (id: NodeId | string) => NodeDefinition | undefined;
/**
* Get all nodes
* @returns An array of all nodes

View File

@@ -6,10 +6,11 @@ export type {
AsyncCache,
} from "./components";
export type {
Node,
SerializedNode,
NodeInstance,
NodeDefinition,
Socket,
NodeType,
NodeId,
Edge,
Graph,
} from "./types";

View File

@@ -1,36 +1,35 @@
import { z } from "zod";
import { NodeInputSchema } from "./inputs";
export const NodeTypeSchema = z
export const NodeIdSchema = z
.string()
.regex(/^[^/]+\/[^/]+\/[^/]+$/, "Invalid NodeId format")
.transform((value) => value as `${string}/${string}/${string}`);
export type NodeType = z.infer<typeof NodeTypeSchema>;
export type NodeId = z.infer<typeof NodeIdSchema>;
export type Node = {
/**
* .tmp only exists at runtime
*/
tmp?: {
depth?: number;
mesh?: any;
parents?: Node[];
children?: Node[];
inputNodes?: Record<string, Node>;
type?: NodeDefinition;
downX?: number;
downY?: number;
x?: number;
y?: number;
ref?: HTMLElement;
visible?: boolean;
isMoving?: boolean;
};
} & z.infer<typeof NodeSchema>;
export type NodeRuntimeState = {
depth?: number;
mesh?: any;
parents?: NodeInstance[];
children?: NodeInstance[];
inputNodes?: Record<string, NodeInstance>;
type?: NodeDefinition;
downX?: number;
downY?: number;
x?: number;
y?: number;
ref?: HTMLElement;
visible?: boolean;
isMoving?: boolean;
};
export type NodeInstance = {
state: NodeRuntimeState;
} & SerializedNode;
export const NodeDefinitionSchema = z.object({
id: NodeTypeSchema,
id: NodeIdSchema,
inputs: z.record(z.string(), NodeInputSchema).optional(),
outputs: z.array(z.string()).optional(),
meta: z
@@ -43,7 +42,7 @@ export const NodeDefinitionSchema = z.object({
export const NodeSchema = z.object({
id: z.number(),
type: NodeTypeSchema,
type: NodeIdSchema,
props: z
.record(z.string(), z.union([z.number(), z.array(z.number())]))
.optional(),
@@ -56,17 +55,20 @@ export const NodeSchema = z.object({
position: z.tuple([z.number(), z.number()]),
});
export type SerializedNode = z.infer<typeof NodeSchema>;
export type NodeDefinition = z.infer<typeof NodeDefinitionSchema> & {
execute(input: Int32Array): Int32Array;
};
export type Socket = {
node: Node;
node: NodeInstance;
index: number | string;
position: [number, number];
};
export type Edge = [Node, number, Node, string];
export type Edge = [NodeInstance, number, NodeInstance, string];
export const GraphSchema = z.object({
id: z.number(),
@@ -81,4 +83,4 @@ export const GraphSchema = z.object({
edges: z.array(z.tuple([z.number(), z.number(), z.number(), z.string()])),
});
export type Graph = z.infer<typeof GraphSchema> & { nodes: Node[] };
export type Graph = z.infer<typeof GraphSchema>;

View File

@@ -1,44 +1,39 @@
<script lang="ts">
interface Props {
ctrl?: boolean;
shift?: boolean;
alt?: boolean;
key: string | string[];
}
interface Props {
ctrl?: boolean;
shift?: boolean;
alt?: boolean;
key: string | string[];
}
let {
ctrl = false,
shift = false,
alt = false,
key
}: Props = $props();
let { ctrl = false, shift = false, alt = false, key }: Props = $props();
</script>
<div class="command">
{#if ctrl}
<span>Ctrl</span>
{/if}
{#if shift}
<span>Shift</span>
{/if}
{#if alt}
<span>Alt</span>
{/if}
{key}
{#if ctrl}
<span>Ctrl</span>
{/if}
{#if shift}
<span>Shift</span>
{/if}
{#if alt}
<span>Alt</span>
{/if}
{key}
</div>
<style>
.command {
background: var(--layer-2);
padding: 0.4em;
font-size: 0.8em;
border-radius: 0.3em;
white-space: nowrap;
width: fit-content;
}
.command {
background: var(--layer-2);
padding: 0.4em;
font-size: 0.8em;
border-radius: 0.3em;
white-space: nowrap;
width: fit-content;
}
span::after {
content: " +";
opacity: 0.5;
}
span::after {
content: ' +';
opacity: 0.5;
}
</style>