From 43ef563ae73fac311d59bd1b337660a38fcf782f Mon Sep 17 00:00:00 2001 From: Max Richter Date: Wed, 21 Jan 2026 17:08:47 +0100 Subject: [PATCH 1/3] feat: show all nodes in add menu --- .../graph-interface/graph-manager.svelte.ts | 22 ++++++++- packages/registry/src/node-registry-client.ts | 46 ++++++++++--------- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/app/src/lib/graph-interface/graph-manager.svelte.ts b/app/src/lib/graph-interface/graph-manager.svelte.ts index b47a664..d0134d7 100644 --- a/app/src/lib/graph-interface/graph-manager.svelte.ts +++ b/app/src/lib/graph-interface/graph-manager.svelte.ts @@ -1,4 +1,5 @@ import throttle from '$lib/helpers/throttle'; +import { RemoteNodeRegistry } from '@nodarium/registry'; import type { Edge, Graph, @@ -18,6 +19,8 @@ import { HistoryManager } from './history-manager'; const logger = createLogger('graph-manager'); logger.mute(); +const remoteRegistry = new RemoteNodeRegistry(''); + const clone = 'structuredClone' in self ? self.structuredClone : (args: any) => JSON.parse(JSON.stringify(args)); @@ -173,7 +176,9 @@ export class GraphManager extends EventEmitter<{ return areSocketsCompatible(edgeOutputSocketType, accepted); }); - const bestOutputIdx = draggedOutputs.findIndex(outputType => areSocketsCompatible(outputType, targetAcceptedTypes)); + const bestOutputIdx = draggedOutputs.findIndex(outputType => + areSocketsCompatible(outputType, targetAcceptedTypes) + ); if (!bestInputEntry || bestOutputIdx === -1) { logger.error('Could not find compatible sockets for drop'); @@ -308,6 +313,21 @@ export class GraphManager extends EventEmitter<{ const nodeIds = Array.from(new Set([...graph.nodes.map((n) => n.type)])); await this.registry.load(nodeIds); + // Fetch all nodes from all collections of the loaded nodes + const allCollections = new Set<`${string}/${string}`>(); + for (const id of nodeIds) { + const [user, collection] = id.split('/'); + allCollections.add(`${user}/${collection}`); + } + for (const collection of allCollections) { + remoteRegistry + .fetchCollection(collection) + .then((collection: { nodes: { id: NodeId }[] }) => { + const ids = collection.nodes.map((n) => n.id); + return this.registry.load(ids); + }); + } + logger.info('loaded node types', this.registry.getAllNodes()); for (const node of this.graph.nodes) { diff --git a/packages/registry/src/node-registry-client.ts b/packages/registry/src/node-registry-client.ts index 464b6ac..a316f86 100644 --- a/packages/registry/src/node-registry-client.ts +++ b/packages/registry/src/node-registry-client.ts @@ -1,32 +1,31 @@ import { - NodeDefinitionSchema, type AsyncCache, type NodeDefinition, - type NodeRegistry, -} from "@nodarium/types"; -import { createLogger, createWasmWrapper } from "@nodarium/utils"; + NodeDefinitionSchema, + type NodeRegistry +} from '@nodarium/types'; +import { createLogger, createWasmWrapper } from '@nodarium/utils'; -const log = createLogger("node-registry"); +const log = createLogger('node-registry'); log.mute(); export class RemoteNodeRegistry implements NodeRegistry { - status: "loading" | "ready" | "error" = "loading"; + status: 'loading' | 'ready' | 'error' = 'loading'; private nodes: Map = new Map(); constructor( private url: string, - public cache?: AsyncCache, + public cache?: AsyncCache ) { } async fetchJson(url: string, skipCache = false) { - const finalUrl = `${this.url}/${url}`; if (!skipCache && this.cache) { const cachedValue = await this.cache?.get(finalUrl); if (cachedValue) { // fetch again in the background, maybe implement that only refetch after a certain time - this.fetchJson(url, true) + this.fetchJson(url, true); return JSON.parse(cachedValue); } } @@ -46,14 +45,13 @@ export class RemoteNodeRegistry implements NodeRegistry { } async fetchArrayBuffer(url: string, skipCache = false) { - const finalUrl = `${this.url}/${url}`; if (!skipCache && this.cache) { const cachedNode = await this.cache?.get(finalUrl); if (cachedNode) { // fetch again in the background, maybe implement that only refetch after a certain time - this.fetchArrayBuffer(url, true) + this.fetchArrayBuffer(url, true); return cachedNode; } } @@ -79,7 +77,7 @@ export class RemoteNodeRegistry implements NodeRegistry { async fetchCollection(userCollectionId: `${string}/${string}`) { const col = await this.fetchJson(`nodes/${userCollectionId}.json`); - return col + return col; } async fetchNodeDefinition(nodeId: `${string}/${string}/${string}`) { @@ -87,7 +85,6 @@ export class RemoteNodeRegistry implements NodeRegistry { } private async fetchNodeWasm(nodeId: `${string}/${string}/${string}`) { - const node = await this.fetchArrayBuffer(`nodes/${nodeId}.wasm`); if (!node) { throw new Error(`Failed to load node wasm ${nodeId}`); @@ -99,7 +96,7 @@ export class RemoteNodeRegistry implements NodeRegistry { async load(nodeIds: `${string}/${string}/${string}`[]) { const a = performance.now(); - const nodes = await Promise.all( + const nodes = (await Promise.all( [...new Set(nodeIds).values()].map(async (id) => { if (this.nodes.has(id)) { return this.nodes.get(id)!; @@ -107,17 +104,23 @@ export class RemoteNodeRegistry implements NodeRegistry { const wasmBuffer = await this.fetchNodeWasm(id); - return this.register(wasmBuffer); - }), - ); + try { + return await this.register(wasmBuffer); + } catch (e) { + console.log('Failed to register: ', id); + console.error(e); + return; + } + }) + )).filter(Boolean) as NodeDefinition[]; const duration = performance.now() - a; - log.group("loaded nodes in", duration, "ms"); + log.group('loaded nodes in', duration, 'ms'); log.info(nodeIds); log.info(nodes); log.groupEnd(); - this.status = "ready"; + this.status = 'ready'; return nodes; } @@ -128,17 +131,16 @@ export class RemoteNodeRegistry implements NodeRegistry { const definition = NodeDefinitionSchema.safeParse(wrapper.get_definition()); if (definition.error) { - console.error(definition.error); throw definition.error; } if (this.cache) { - await this.cache.set(definition.data.id, wasmBuffer); + this.cache.set(definition.data.id, wasmBuffer); } let node = { ...definition.data, - execute: wrapper.execute, + execute: wrapper.execute }; this.nodes.set(definition.data.id, node); From 7f2214f15c666f4c1354f753582b1df6e3c45218 Mon Sep 17 00:00:00 2001 From: Max Richter Date: Wed, 21 Jan 2026 17:24:54 +0100 Subject: [PATCH 2/3] fix(utils): make sure we do not build a .wasm file for utils --- packages/utils/Cargo.toml | 6 +++--- packages/utils/src/lib.rs | 16 ++++++++++++++++ packages/utils/src/main.rs | 36 ------------------------------------ 3 files changed, 19 insertions(+), 39 deletions(-) delete mode 100644 packages/utils/src/main.rs diff --git a/packages/utils/Cargo.toml b/packages/utils/Cargo.toml index 776a455..4e81b1e 100644 --- a/packages/utils/Cargo.toml +++ b/packages/utils/Cargo.toml @@ -2,15 +2,15 @@ name = "nodarium_utils" version = "0.1.0" edition = "2021" -description = "A collection of utilities for Nodarium" license = "MIT" repository = "https://github.com/jim-fx/nodes" +description = "A collection of utilities for Nodarium" [lib] crate-type = ["rlib"] [dependencies] -serde = { version = "1.0", features = ["derive"] } -serde_json = { version = "1.0", default-features = false, features = ["alloc"] } glam = "0.30.10" noise = "0.9.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = { version = "1.0", default-features = false, features = ["alloc"] } diff --git a/packages/utils/src/lib.rs b/packages/utils/src/lib.rs index 0bcf629..5809ecb 100644 --- a/packages/utils/src/lib.rs +++ b/packages/utils/src/lib.rs @@ -33,3 +33,19 @@ macro_rules! log { }}; } +#[allow(dead_code)] +#[rustfmt::skip] +fn test_split_args(){ + let inputs = vec![ + vec![0, 1, 0, 4, 1056964608, 1065353216, 1056964608, 1, 4, 1080872141, 1054951342, 32, 1, 1 ], + vec![0, 4, 1056964608, 1065353216, 1056964608, 1, 4], + vec![0, 1, 0, 3, 0, 0, 0, 5, 0, 0, 1073741824, 1073741824, 1, 1, 1, 1, 1, 4, 1065353216, 1054615798, 5, 1, 1 ], + vec![ 0, 1, 0, 3, 0, 0, 0, 1, 4, 1073741824, 1073741824, 32, 1, 1 ], + vec![0, 1, 0, 1, 0, 14, 0, 1056964608, 1056964608, 1056964608, 1058810102, 1056964608, 1069547520, 1056964608, 1050421494, 1056964608, 1075838976, 1056964608, 0, 1, 1, 1, 2, 13, 1, 1], + vec![ 0, 1, 0, 2, 0, 0, 5, 0, 0, 1073741824, 1073741824, 1, 2, 0, 1, 4, 1088212173, 1083388723, 20, 1, 1 ] + ]; + + for input in inputs { + println!("RESULT: {:?}", split_args(&input)); + } +} diff --git a/packages/utils/src/main.rs b/packages/utils/src/main.rs deleted file mode 100644 index b628469..0000000 --- a/packages/utils/src/main.rs +++ /dev/null @@ -1,36 +0,0 @@ -use nodarium_utils::{ - geometry::{create_multiple_paths, wrap_multiple_paths}, - split_args, -}; - -#[allow(dead_code)] -#[rustfmt::skip] -fn test_split_args(){ - let inputs = vec![ - vec![0, 1, 0, 4, 1056964608, 1065353216, 1056964608, 1, 4, 1080872141, 1054951342, 32, 1, 1 ], - vec![0, 4, 1056964608, 1065353216, 1056964608, 1, 4], - vec![0, 1, 0, 3, 0, 0, 0, 5, 0, 0, 1073741824, 1073741824, 1, 1, 1, 1, 1, 4, 1065353216, 1054615798, 5, 1, 1 ], - vec![ 0, 1, 0, 3, 0, 0, 0, 1, 4, 1073741824, 1073741824, 32, 1, 1 ], - vec![0, 1, 0, 1, 0, 14, 0, 1056964608, 1056964608, 1056964608, 1058810102, 1056964608, 1069547520, 1056964608, 1050421494, 1056964608, 1075838976, 1056964608, 0, 1, 1, 1, 2, 13, 1, 1], - vec![ 0, 1, 0, 2, 0, 0, 5, 0, 0, 1073741824, 1073741824, 1, 2, 0, 1, 4, 1088212173, 1083388723, 20, 1, 1 ] - ]; - - for input in inputs { - println!("RESULT: {:?}", split_args(&input)); - } -} - -fn test_path() { - // let path_data = create_path(3, 2); - // println!("{:?}", path_data); - - let mut multiple_paths = create_multiple_paths(1, 4, 1); - let mut wrapped_paths = wrap_multiple_paths(&mut multiple_paths); - wrapped_paths[0].points[0] = 1.0; - println!("{:?}", wrapped_paths); - println!("{:?}", multiple_paths); -} - -fn main() { - test_path() -} From 6f5c5bb46ee49464e455aac533666a237cea6d25 Mon Sep 17 00:00:00 2001 From: Max Richter Date: Thu, 22 Jan 2026 12:07:37 +0100 Subject: [PATCH 3/3] feat: change initial camera position so that nodes are visible --- app/src/lib/graph-interface/graph-state.svelte.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/lib/graph-interface/graph-state.svelte.ts b/app/src/lib/graph-interface/graph-state.svelte.ts index 7301b13..c75d4f7 100644 --- a/app/src/lib/graph-interface/graph-state.svelte.ts +++ b/app/src/lib/graph-interface/graph-state.svelte.ts @@ -62,7 +62,7 @@ export class GraphState { ); camera = $state(null!); - cameraPosition: [number, number, number] = $state([0, 0, 100]); + cameraPosition: [number, number, number] = $state([140, 100, 3.5]); clipboard: null | { nodes: NodeInstance[];