BaklavaJS Documentation

repository·master·Indexed 24 days ago

https://github.com/newcat/baklavajs

A web-based graph and node editor built with VueJS and TypeScript. BaklavaJS features a modular plugin system allowing for visual UI editing and headless graph execution. It provides a core engine for node-based programming, a Vue renderer, and specialized packages for event management, interface types, and calculation execution.

Tokens
38.6K
Snippets
83
Records
205
Agent score
83%

What's inside BaklavaJS

  1. Overview of BaklavaJS

    master
    BaklavaJS is a graph and node editor designed for the web, built using VueJS. It provides a user-friendly editor interface and a highly extensible plugin system that allows developers to create custom nodes. The entire ecosystem is written in TypeScript to ensure type safety.
  2. What is the Forward Engine and when to use it

    master

    The Forward Engine is an execution model where execution flows forward through explicit connections, while data dependencies are resolved backward on demand. This is similar to Unreal Engine Blueprints or Unity Visual Scripting.

    Use the Forward Engine when you need:

    • Explicit execution flow: Control the order and selection of running nodes.
    • Branching: Conditionally execute different paths.
    • Loops: Execute a subchain of nodes multiple times.
    • Event-driven execution: Start execution from a specific trigger node.

    Use the Dependency Engine instead if: You only need a simple dataflow graph where all nodes are always calculated based on their dependencies.

  3. Cycle handling in the Forward Engine

    master

    The Forward Engine has different rules for connection types:

    • Execution-flow connections: Cycles are allowed (required for implementing loops).
    • Data connections: Cycles are not allowed. The engine will prevent the creation of data connections that would introduce a cycle.
  4. Use normal and preventable events

    master

    BaklavaJS distinguishes between two types of events:

    1. Normal Events: Fired after an action occurs, typically used for reacting to changes.
    2. Preventable Events: Fired before an action occurs. Listeners can call a prevent() function provided in the callback arguments to cancel the action. These events often use the before prefix (e.g., beforeAddConnection).

    When using a PreventableBaklavaEvent, the .emit() method returns a boolean indicating whether the action was prevented.

    import { PreventableBaklavaEvent } from "@baklavajs/events";
    
    const ev = new PreventableBaklavaEvent<string, null>(null);
    const token = Symbol();
    
    ev.subscribe(token, (data, prevent) => {
        if (data === "prevent me") {
            prevent();
            return;
        }
        console.log(data);
    });
    
    function emit(data: string) {
        if (ev.emit(data)) {
            console.log("prevented");
        }
    }
    
    emit("prevent me");
    emit("this works");
  5. How BaklavaJS plugins work

    master

    BaklavaJS uses a modular architecture where the core logic is separated from rendering and execution. This allows you to build different types of applications (e.g., a visual editor, a headless calculation engine, or a type-safe logic builder) by composing different packages.

    • Core: Manages the graph structure and node logic.
    • Engine: Extends the core to allow the graph to actually execute logic/calculations.
    • Interface Types: Adds a layer of validation to the graph, ensuring connections only occur between compatible types and handling conversions.
    • Renderer: The visual layer (specifically @baklavajs/renderer-vue for Vue users) that turns the graph data into an interactive UI.
  6. Understand the BaklavaJS Editor model

    master

    The Editor is the central model class in BaklavaJS and serves as the primary container for all other components. Everything in a Baklava application lives inside an editor instance.

    Key responsibilities of the Editor include:

    • Managing the lifecycle of graphs.
    • Providing functions for saving and loading state.
    • Registering node types.
    • Providing a subscription mechanism for the event system.

    An editor instance always contains exactly one main graph, known as the root graph, which is accessible via editor.graph. The editor also maintains a collection of all graph instances (including subgraphs) via editor.graphs.

  7. What are Commands in BaklavaJS

    master
    Commands are an abstraction used to extend actions within BaklavaJS. They allow you to encapsulate logic (like undo/redo or custom node manipulations) into named, executable units. All command-related functionality is managed via the commandHandler interface (specifically ICommandHandler).
  8. Understand the `onUpdate` return structure for Dynamic Nodes

    master

    The onUpdate(inputValues, outputValues) function determines the target state of a dynamic node's interfaces. It returns a DynamicNodeUpdateResult object.

    If a key is present in the returned inputs or outputs object, the interface is created or updated. If a key is missing from the returned object, the corresponding interface is removed from the node. This allows the node to automatically synchronize its interface state with the returned definition.

    type DynamicNodeDefinition = Record<string, () => NodeInterface<any>>;
    interface DynamicNodeUpdateResult {
        inputs?: DynamicNodeDefinition;
        outputs?: DynamicNodeDefinition;
        forceUpdateInputs?: string[];
        forceUpdateOutputs?: string[];
    }
  9. How Subgraph Instances and Templates Work

    master

    Subgraphs operate through a relationship between a GraphNode and a GraphTemplate:

    1. GraphTemplate: The source of truth containing the nodes and connections.
    2. GraphNode: An instance in a parent graph that contains an internal graph instance.
    3. Relationship: Each GraphNode holds an internal graph that is based on the GraphTemplate of the subgraph.

    When you edit a subgraph, you are modifying the GraphTemplate. The GraphNode instances in the root graph reference this template. Changes to the template are propagated to the instances when the template is saved.

  10. How graph execution works with Engines

    master

    BaklavaJS uses Engines to execute compute graphs. While the Editor is used for editing, Engines handle the actual computation logic. There are two primary engine types:

    • Dependency Engine: Executes based on dependency tracking. Use this if you want the behavior of Baklava V1.
    • Forward Engine: Executes in a forward-pass manner.

    Regardless of the engine type, all nodes must implement a calculate function to participate in execution.

  11. How the BaklavaJS event system works

    master

    BaklavaJS uses a custom event system designed for extensibility and plugin support. Classes supporting this system expose events and/or hook properties.

    To support inline arrow functions (which cannot be easily removed via function reference), BaklavaJS uses tokens. A token can be any reference type (object, array, this) or a Symbol. You provide the token when calling .subscribe() and must provide the same token when calling .unsubscribe() to remove the listener.

    import { BaklavaEvent } from "@baklavajs/events";
    const ev = new BaklavaEvent<string, null>(null);
    const token = Symbol();
    
    ev.subscribe(token, (data) => {
        console.log("Event triggered:", data);
    });
    
    ev.emit("Hello World");
    ev.unsubscribe(token);
    ev.emit("This won't be printed");