Flowgix.Core 0.1.0

dotnet add package Flowgix.Core --version 0.1.0
                    
NuGet\Install-Package Flowgix.Core -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Flowgix.Core" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Flowgix.Core" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Flowgix.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Flowgix.Core --version 0.1.0
                    
#r "nuget: Flowgix.Core, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#addin nuget:?package=Flowgix.Core&version=0.1.0
                    
Install Flowgix.Core as a Cake Addin
#tool nuget:?package=Flowgix.Core&version=0.1.0
                    
Install Flowgix.Core as a Cake Tool

@flowgix/core

A powerful and flexible core library for the Flowgix plugin system, written in F# and compiled to JavaScript using Fable. This library provides the foundation for building node-based visual programming environments with a robust plugin architecture.

Features

  • Plugin System: A robust plugin architecture that allows for easy extension of functionality
    • Dynamic plugin registration and unregistration
    • Plugin lifecycle management (initialization and cleanup)
    • Custom plugin configurations and engines
  • Node Graph Engine: A powerful engine for evaluating node graphs with support for:
    • Custom node types with type-safe inputs and outputs
    • Port types with automatic type conversion
    • Control system for node configuration
    • Circular dependency detection
    • Caching for performance optimization
  • Type Safety: Full TypeScript support with comprehensive type definitions
    • Strong typing for all core components
    • Type-safe plugin development
    • Runtime type checking and validation
  • Extensibility: Easy to extend with custom node types, port types, and plugins
    • Flexible plugin API
    • Custom resolvers for ports and nodes
    • Support for custom renderers and controls

Installation

NPM (JavaScript/TypeScript)

npm install @flowgix/core

NuGet (.NET/C#/F#)

# Using the .NET CLI
dotnet add package Flowgix.Core

# Using the Package Manager Console
Install-Package Flowgix.Core

Package References

C# (.csproj)
<PackageReference Include="Flowgix.Core" Version="0.1.0" />
F# (.fsproj)
<PackageReference Include="Flowgix.Core" Version="0.1.0" />

Prerequisites

For development:

Development Setup

  1. Install Fable as a local tool:
dotnet new tool-manifest
dotnet tool install fable
  1. Install npm dependencies:
npm install

Building

One-time Build

npm run build

Watch Mode (for development)

npm run watch

Testing

Run Tests Once

npm test

Watch Mode for Tests

npm run test:watch

Project Structure

flowgix-core/
├── src/
│   ├── Types.fs        # Core type definitions
│   ├── Plugin.fs       # Plugin system implementation
│   ├── Engine.fs       # Node graph engine
│   ├── index.ts        # TypeScript declarations
│   └── example.ts      # Usage example
├── tests/              # Test files
├── dist/              # Compiled output
├── package.json       # npm package configuration
├── tsconfig.json      # TypeScript configuration
├── babel.config.js    # Babel configuration
└── jest.config.cjs    # Jest configuration

Usage

TS Example

import { IFlowgixEngine, IPluginManager, type NodeType, type PortType } from 'flowgix-core';

// Define port types
const numberPort: PortType = {
    name: 'number',
    type: 'number',
    resolver: (type, inputData, value) => Number(value)
};

// Define node types
const addNumbers: NodeType = {
    id: 'add-numbers',
    name: 'Add Numbers',
    description: 'Adds two numbers together',
    category: 'Math',
    inputs: ['a', 'b'],
    outputs: ['result'],
    controls: [],
    resolver: (node, inputData, nodeType, context) => {
        const a = Number(inputData['a']);
        const b = Number(inputData['b']);
        return { result: a + b };
    }
};

// Create a plugin
const mathPlugin = {
    id: 'math-plugin',
    name: 'Math Plugin',
    description: 'Basic mathematical operations',
    nodeTypes: [addNumbers],
    portTypes: [numberPort]
};

// Initialize the plugin manager
const pluginManager: IPluginManager = {
    registerPlugin: (registration) => { /* ... */ },
    unregisterPlugin: (pluginId) => { /* ... */ },
    getPluginConfig: (pluginId) => { /* ... */ },
    getPluginEngine: (pluginId) => { /* ... */ },
    getPlugins: () => { /* ... */ },
    onInit: () => { /* ... */ },
    onCleanup: () => { /* ... */ }
};

// Create and evaluate a graph
const engine: IFlowgixEngine = {
    createConfig: (nodeTypes, portTypes, controls) => { /* ... */ },
    createEngine: (config, portResolver, nodeResolver) => { /* ... */ },
    evaluateGraph: (engine, nodes) => { /* ... */ }
};

const config = engine.createConfig(
    [addNumbers],
    [numberPort],
    []
);

const rootEngine = engine.createEngine(
    config,
    (type, inputData, value) => Number(value),
    (node, inputData, nodeType, context) => {
        const resolver = nodeType.resolver;
        if (resolver) {
            return resolver(node, inputData, nodeType, context);
        }
        return {};
    }
);

const nodes = new Map([
    ['node1', {
        id: 'node1',
        type: 'add-numbers',
        root: true,
        inputData: { a: 5, b: 3 },
        connections: {}
    }]
]);

const result = engine.evaluateGraph(rootEngine, nodes);
console.log(result); // { result: 8 }

F# Example

open Flowgix.Core

// Define port types
let numberPort = {
    name = "number"
    type = "number"
    resolver = fun type inputData value -> 
        match value with
        | :? string as s -> float s
        | :? float as f -> f
        | _ -> 0.0
}

// Define node types
let addNumbers = {
    id = "add-numbers"
    name = "Add Numbers"
    description = "Adds two numbers together"
    category = "Math"
    inputs = ["a"; "b"]
    outputs = ["result"]
    controls = []
    resolver = fun node inputData nodeType context ->
        let a = float inputData["a"]
        let b = float inputData["b"]
        Map [("result", a + b)]
}

// Create a plugin
let mathPlugin = {
    id = "math-plugin"
    name = "Math Plugin"
    description = "Basic mathematical operations"
    nodeTypes = [addNumbers]
    portTypes = [numberPort]
}

// Initialize the plugin manager
let pluginManager = {
    registerPlugin = fun registration -> ()
    unregisterPlugin = fun pluginId -> ()
    getPluginConfig = fun pluginId -> Some mathPlugin
    getPluginEngine = fun pluginId -> None
    getPlugins = fun () -> [mathPlugin]
    onInit = fun () -> ()
    onCleanup = fun () -> ()
}

// Create and evaluate a graph
let engine = {
    createConfig = fun nodeTypes portTypes controls -> 
        { nodeTypes = nodeTypes; portTypes = portTypes; controls = controls }
    createEngine = fun config portResolver nodeResolver -> 
        { config = config; portResolver = portResolver; nodeResolver = nodeResolver }
    evaluateGraph = fun engine nodes -> 
        let node = Map.find "node1" nodes
        let result = engine.nodeResolver node node.inputData addNumbers Map.empty
        result
}

let config = engine.createConfig [addNumbers] [numberPort] []

let rootEngine = engine.createEngine(
    config,
    (fun type inputData value -> float value),
    (fun node inputData nodeType context ->
        match nodeType.resolver with
        | Some resolver -> resolver node inputData nodeType context
        | None -> Map.empty)
)

let nodes = Map [
    ("node1", {
        id = "node1"
        type = "add-numbers"
        root = true
        inputData = Map [("a", 5.0); ("b", 3.0)]
        connections = Map.empty
    })
]

let result = engine.evaluateGraph(rootEngine, nodes)
printfn "%A" result // Map [("result", 8.0)]

C# Example

using Flowgix.Core;

// Define port types
var numberPort = new PortType
{
    Name = "number",
    Type = "number",
    Resolver = (type, inputData, value) => Convert.ToDouble(value)
};

// Define node types
var addNumbers = new NodeType
{
    Id = "add-numbers",
    Name = "Add Numbers",
    Description = "Adds two numbers together",
    Category = "Math",
    Inputs = new[] { "a", "b" },
    Outputs = new[] { "result" },
    Controls = Array.Empty<ControlType>(),
    Resolver = (node, inputData, nodeType, context) =>
    {
        var a = Convert.ToDouble(inputData["a"]);
        var b = Convert.ToDouble(inputData["b"]);
        return new Dictionary<string, object> { { "result", a + b } };
    }
};

// Create a plugin
var mathPlugin = new FlowgixPlugin
{
    Id = "math-plugin",
    Name = "Math Plugin",
    Description = "Basic mathematical operations",
    NodeTypes = new[] { addNumbers },
    PortTypes = new[] { numberPort }
};

// Initialize the plugin manager
var pluginManager = new PluginManager
{
    RegisterPlugin = registration => { },
    UnregisterPlugin = pluginId => { },
    GetPluginConfig = pluginId => mathPlugin,
    GetPluginEngine = pluginId => null,
    GetPlugins = () => new[] { mathPlugin },
    OnInit = () => { },
    OnCleanup = () => { }
};

// Create and evaluate a graph
var engine = new FlowgixEngine
{
    CreateConfig = (nodeTypes, portTypes, controls) =>
        new FlowgixConfig { NodeTypes = nodeTypes, PortTypes = portTypes, Controls = controls },
    CreateEngine = (config, portResolver, nodeResolver) =>
        new FlowgixRootEngine { Config = config, PortResolver = portResolver, NodeResolver = nodeResolver },
    EvaluateGraph = (engine, nodes) =>
    {
        var node = nodes["node1"];
        var result = engine.NodeResolver(node, node.InputData, addNumbers, new Dictionary<string, object>());
        return result;
    }
};

var config = engine.CreateConfig(new[] { addNumbers }, new[] { numberPort }, Array.Empty<Control>());

var rootEngine = engine.CreateEngine(
    config,
    (type, inputData, value) => Convert.ToDouble(value),
    (node, inputData, nodeType, context) =>
    {
        if (nodeType.Resolver != null)
        {
            return nodeType.Resolver(node, inputData, nodeType, context);
        }
        return new Dictionary<string, object>();
    }
);

var nodes = new Dictionary<string, FlumeNode>
{
    ["node1"] = new FlumeNode
    {
        Id = "node1",
        Type = "add-numbers",
        Root = true,
        InputData = new Dictionary<string, object> { { "a", 5.0 }, { "b", 3.0 } },
        Connections = new Dictionary<string, object>()
    }
};

var result = engine.EvaluateGraph(rootEngine, nodes);
Console.WriteLine(string.Join(", ", result.Select(kvp => $"{kvp.Key}: {kvp.Value}"))); // result: 8

Core Components

Control Types

The library supports various control types for node configuration:

  • Text
  • Number
  • Checkbox
  • Select
  • MultiSelect
  • Custom
  • Boolean
  • Object

Port Types

Built-in port types include:

  • NumberPort
  • TextPort
  • BooleanPort
  • OutcomeActionCollectionPort
  • LLMAgentPort
  • CustomPort (for custom implementations)

Node Types

Core node types include:

  • AddNumbers
  • FlowgixResults
  • OutcomeAttributes
  • DivideNumbers
  • CustomNode (for custom implementations)

API Reference

Core Types

ControlType
interface ControlType {
    type: string;
    label: string;
    name: string;
    portName: string;
    defaultValue: any;
}
PortType
interface PortType {
    name: string;
    type: string;
    resolver?: (type: string, inputData: any, value: any) => any;
}
NodeType
interface NodeType {
    id: string;
    name: string;
    description: string;
    category: string;
    inputs: string[];
    outputs: string[];
    controls: ControlType[];
    resolver?: (node: any, inputData: any, nodeType: NodeType, context: any) => Record<string, any>;
}

Plugin System

IPluginManager
interface IPluginManager {
    registerPlugin(registration: PluginRegistration): void;
    unregisterPlugin(pluginId: string): void;
    getPluginConfig(pluginId: string): FlowgixPlugin | undefined;
    getPluginEngine(pluginId: string): FlowgixRootEngine | undefined;
    getPlugins(): FlowgixPlugin[];
    onInit(): void;
    onCleanup(): void;
}

Engine

IFlowgixEngine
interface IFlowgixEngine {
    createConfig(
        nodeTypes: NodeType[],
        portTypes: PortType[],
        controls: Control[]
    ): FlowgixConfig;

    createEngine(
        config: FlowgixConfig,
        portResolver: (type: string, inputData: any, value: any) => any,
        nodeResolver: (node: FlumeNode, inputData: any, nodeType: NodeType, context: any) => Record<string, any>
    ): FlowgixRootEngine;

    evaluateGraph(engine: FlowgixRootEngine, nodes: Map<string, FlumeNode>): Record<string, any>;
}

Publishing

To publish this package to npm:

  1. Build the package:
npm run build
  1. Test the package:
npm test
  1. Update the version in package.json:
npm version patch  # for bug fixes
npm version minor  # for new features
npm version major  # for breaking changes
  1. Login to npm (if not already logged in):
npm login
  1. Publish the package:
npm publish

For scoped packages (e.g., @your-org/flowgix-core):

npm publish --access public

Pre-publish Checklist

  • All tests pass
  • Build is successful
  • Version is updated
  • README is up to date
  • No sensitive data in the package
  • All necessary files are included
  • package.json has correct metadata

Contributing

  1. Fork the repository at github.com/flowgix/flowgix-core
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

For support, please open an issue in the GitHub repository.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.1.0 156 3/31/2025

Initial release