npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@flowgix/core

v0.1.1

Published

Core library for the Flowgix plugin system

Readme

@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, FlowgixNode>
{
    ["node1"] = new FlowgixNode
    {
        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: FlowgixNode, inputData: any, nodeType: NodeType, context: any) => Record<string, any>
    ): FlowgixRootEngine;

    evaluateGraph(engine: FlowgixRootEngine, nodes: Map<string, FlowgixNode>): 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.