feat: add validation to include_definition macro

This commit is contained in:
2024-04-18 15:40:41 +02:00
parent c33e2642e1
commit e7f43020dc
27 changed files with 466 additions and 147 deletions

View File

@ -0,0 +1,96 @@
import type { NodeInput } from "./inputs";
export type { NodeInput } from "./inputs";
export type Node = {
id: number;
type: string;
props?: Record<string, any>,
tmp?: {
depth?: number;
mesh?: any;
random?: number;
parents?: Node[],
children?: Node[],
inputNodes?: Record<string, Node>
type?: NodeType;
downX?: number;
downY?: number;
x?: number;
y?: number;
ref?: HTMLElement;
visible?: boolean;
isMoving?: boolean;
},
meta?: {
title?: string;
lastModified?: string;
},
position: [x: number, y: number]
}
export type NodeType = {
id: string;
inputs?: Record<string, NodeInput>
outputs?: string[];
meta?: {
title?: string;
},
execute?: (args: number[]) => unknown;
}
export type Socket = {
node: Node;
index: number | string;
position: [number, number];
};
export interface NodeRegistry {
/**
* The status of the node registry
* @remarks The status should be "loading" when the registry is loading, "ready" when the registry is ready, and "error" if an error occurred while loading the registry
*/
status: "loading" | "ready" | "error";
/**
* Load the nodes with the given ids
* @param nodeIds - The ids of the nodes to load
* @returns A promise that resolves when the nodes are loaded
* @throws An error if the nodes could not be loaded
* @remarks This method should be called before calling getNode or getAllNodes
*/
load: (nodeIds: string[]) => Promise<void>;
/**
* 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: string) => NodeType | undefined;
/**
* Get all nodes
* @returns An array of all nodes
*/
getAllNodes: () => NodeType[];
}
export interface RuntimeExecutor {
/**
* Execute the given graph
* @param graph - The graph to execute
* @returns The result of the execution
*/
execute: (graph: Graph) => unknown;
}
export type Edge = [Node, number, Node, string];
export type Graph = {
id: number;
meta?: {
title?: string;
lastModified?: string;
},
settings?: Record<string, any>,
nodes: Node[];
edges: [number, number, number, string][];
}

View File

@ -0,0 +1,50 @@
type NodeInputFloat = {
type: "float";
element?: "slider";
value?: number;
min?: number;
max?: number;
step?: number;
}
type NodeInputInteger = {
type: "integer";
element?: "slider";
value?: number;
min?: number;
max?: number;
}
type NodeInputBoolean = {
type: "boolean";
value?: boolean;
}
type NodeInputSelect = {
type: "select";
labels: string[];
value?: number;
}
type NodeInputSeed = {
type: "seed"
value?: number;
}
type DefaultOptions = {
internal?: boolean;
external?: boolean;
setting?: string;
label?: string | false;
}
type InputTypes = (NodeInputSeed | NodeInputBoolean | NodeInputFloat | NodeInputInteger | NodeInputSelect);
export type NodeInput = InputTypes & {
type: InputTypes["type"] | InputTypes["type"][];
} & DefaultOptions;
export type NodeInputType<T extends Record<string, NodeInput>> = {
[K in keyof T]: T[K]["value"]
};

133
packages/types/src/lib.rs Normal file
View File

@ -0,0 +1,133 @@
use serde::{Deserialize, Deserializer, Serialize};
use serde_json::Value;
use std::collections::HashMap;
#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "type")]
#[allow(non_camel_case_types)]
pub enum InputTypes {
float(NodeInputFloat),
integer(NodeInputInteger),
boolean(NodeInputBoolean),
select(NodeInputSelect),
seed(NodeInputSeed),
model(NodeInputModel),
plant(NodeInputPlant),
vec3(NodeInputVec3),
}
#[derive(Serialize, Deserialize, Debug)]
pub struct NodeInputVec3 {
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<Vec<f64>>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct NodeInputFloat {
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub min: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub step: Option<f64>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct NodeInputInteger {
#[serde(skip_serializing_if = "Option::is_none")]
pub element: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub min: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max: Option<i64>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct NodeInputBoolean {
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<bool>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct NodeInputSelect {
pub labels: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<usize>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct NodeInputSeed {
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<usize>,
}
// Assuming similar structure as other NodeInput types for Model and Plant
#[derive(Serialize, Deserialize, Debug)]
pub struct NodeInputModel {
// Model-specific fields can be added here
}
#[derive(Serialize, Deserialize, Debug)]
pub struct NodeInputPlant {
// Plant-specific fields can be added here
}
#[derive(Serialize, Deserialize, Debug)]
pub struct DefaultOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub internal: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub external: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub setting: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub label: Option<serde_json::Value>, // To handle both String and false
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum NodeTypeOrArray {
Single(InputTypes),
Multiple(Vec<String>),
}
#[derive(Debug, Serialize)]
pub struct NodeInput {
pub types: Vec<String>,
pub options: DefaultOptions,
}
impl<'de> Deserialize<'de> for NodeInput {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let raw_input: Value = Deserialize::deserialize(deserializer)?;
let options: DefaultOptions =
DefaultOptions::deserialize(&raw_input).map_err(serde::de::Error::custom)?; // Maps deserialization errors appropriately
let types: Vec<String> = match raw_input.get("type") {
Some(Value::String(single_type)) => vec![single_type.clone()],
Some(Value::Array(types)) => types
.iter()
.map(|t| t.as_str().unwrap_or("").to_owned())
.collect(),
_ => return Err(serde::de::Error::custom("Invalid or missing 'type' field")),
};
Ok(NodeInput { types, options })
}
}
#[derive(Deserialize, Debug, Serialize)]
pub struct NodeType {
#[serde(skip_serializing_if = "Option::is_none")]
pub inputs: Option<HashMap<String, NodeInput>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub outputs: Option<Vec<String>>,
}

View File

@ -0,0 +1,26 @@
type RandomParameter = {
type: "random";
min: Parameter;
max: Parameter;
seed: number;
}
type MathParameter = {
type: "math";
op_type: number;
a: Parameter;
b: Parameter;
}
type NoiseParameter = {
type: "noise";
frequency: Parameter;
amplitude: Parameter;
seed: number;
}
type Parameter = number | RandomParameter | MathParameter | NoiseParameter;