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

sea-of-amoebas

v2.1.6

Published

A declarative and event-driven execution framework for building scalable, asynchronous flow systems.

Downloads

126

Readme

Sea of Amoebas (SofA)

A declarative, event-driven framework for modular and scalable workflow execution in JavaScript, empowering you to manage and orchestrate complex processes within your web application.

Imagine effortlessly building and coordinating intricate workflows in your web application, chaining functions and creating dynamic process flows. With SofA, you can seamlessly integrate asynchronous processes, conditionally trigger events, and handle complex data interactions—enabling scenarios like specialized AI assistants collaborating and queuing tasks, where one assistant's output becomes another's input.

The best part? It's so intuitive and efficient, it's like coding from the comfort of your couch ;) .

Sit back, relax, and let SofA handle the flow.

Overview and Features

SofA provides a framework to implement workflows as a network of interconnected Amoeba Nodes. Each node represents a function, modeled as f(x1, x2, ..., xn), which waits for all required input parameters to arrive before executing. Once the function completes, it emits output events that can trigger other nodes, creating a continuous flow of processes. This design results in a latent "sea" of nodes (or Amoebas) awaiting events to process, forming a dynamic and responsive system within your web application.

Key Features

  1. Event-Driven Execution:
    • Amoebas execute only after receiving all required inputs as events.
    • Events can carry data from simple primitives to complex objects.
  2. Flexible Output Events:
    • Nodes can emit multiple output events (e1, e2, ..., em), enabling branching and parallel workflows.
    • Conditional events allow nodes to evaluate dynamic conditions and emit specific events based on their results, providing fine-grained control over process flows.
  3. Modularity and Scalability:
    • Event emitters can be shared across multiple AmoebaSeas, allowing interconnected workflows.
    • Define your "sea of Amoebas" in modular parts, simplifying complex systems and allowing the reuse or extension of existing definitions.
  4. Asynchronous Support:
    • Fully compatible with both synchronous and asynchronous functions.
  5. Declarative Design:
    • Define workflows in JSON or YAML syntax for a readable, shareable structure.

Installation

Install the package directly from npm:

npm install sea-of-amoebas

That's it! The package is now ready to use in your project.

Quickstart Example

Basic Example

import { AmoebaSea } from 'sea-of-amoebas';
// Define functions
const add = (a, b) => a + b;
const multiply = (x, y) => x * y;
const increment = async (z) => z + 1;

const sofa = new AmoebaSea();
// Add amoebas using the new object syntax
sofa.addAmoeba({
    id: 'AmoebaA',
    func: add,
    inputEvents: ['input.a', 'input.b'],
    outputEvents: ['AmoebaB.input']
});
sofa.addAmoeba({
    id: 'AmoebaB',
    func: multiply,
    inputEvents: ['AmoebaB.input', 'input.y'],
    outputEvents: ['AmoebaC.input']
});
sofa.addAmoeba({
    id: 'AmoebaC',
    func: increment,
    inputEvents: ['AmoebaC.input']
});
// Finalize configuration
sofa.finalizeConfiguration();
// Set initial inputs
sofa.setInput('input.a', 5); //Initial value for 'input.a'
sofa.setInput('input.b', 3); //Initial value for 'input.b'
sofa.setInput('input.y', 2); //Initial value for 'input.y'
// Wait for the last amoeba to execute
const finalResult = await sofa.waitForAmoebaExecution('AmoebaC');

Define a Flow with a JavaScript Object

import { AmoebaFlowParser } from 'sea-of-amoebas';
// Define the workflow as a JavaScript object
const jsonFlow = {
    amoebas: [
        // Amoeba A: Adds 1 to the input and emits to "Logger",
        // and either B.Input or C.Input based on conditions
        {
            id: 'A',
            func: (x) => x + 1,
            inputEvents: ['input.x'],
            outputEvents: [
                "Logger", // Sends all results to Logger, regardless of value
                {
                    condition: (result) => result > 5, // If result > 5, send to B.Input
                    then: ["B.Input"],
                    else: ["C.Input"], // Else 
                },
                {
                    condition: (result) => result == 5, // If result == 5, send to an Extra Logger (All condition are evaluated)
                    then: ["Logger"]
                }
            ]
        },
        // Amoeba B: Multiplies the input by 2 and emits conditionally to D or Logger
        {
            id: 'B',
            func: (y) => y * 2,
            inputEvents: ['B.Input'],
            outputEvents: [
                {
                    condition: (result) => result > 15,// If result > 15, send to D.Input
                    then: ["D.Input"]
                },
                {
                    condition: (result) => result <= 15,// If result <= 15, send to Logger (without 'else' example)
                    then: ["Logger"]
                }
            ]
        },
        // Amoeba C: Subtracts 2 from the input and sends the result to Logger
        {
            id: 'C',
            func: (z) => z - 2,
            inputEvents: ['C.Input'],
            outputEvents: ["Logger"]
        },
        // Amoeba D: Computes modulus of input with 3
        // While it does not define explicit output events to pass its result to another amoeba,
        // every amoeba emits a default event named `ID.executed` upon completion.
        // This allows you to retrieve its result if needed.
        // Example: Use `await sea.waitForAmoebaExecution("D")` to wait for its execution
        // or `await sea.waitForOutputEvent("D.executed")` to directly capture the emitted event.
        {
            id: 'D',
            func: (w) => w % 3,
            inputEvents: ['D.Input']
        },
        // Logger: Logs all incoming data
        // If no input events are specified, the amoeba listens for events matching its name by default.
        // This simplify the definition for single-input functions.
        // In this case, "Logger" listens for "Logger" events        
        {
            id: 'Logger',
            func: (data) => console.log(`Log: ${data}`)
        }
    ]
};
// Parse the JSON and create the workflow
const sofa = AmoebaFlowParser.fromObject(jsonFlow);
// Finalize configuration
sofa.finalizeConfiguration();
// Test the workflow with different inputs
const inputs = [3, 6, 10];
for (const input of inputs) {
    console.log(`Processing input: ${input}`);
    sofa.setInput('input.x', input);    
}

Explore Advanced Examples

For more illustrative and complex examples, check the tests folder in the repository. It contains a variety of test cases showcasing advanced workflows, including conditional logic, branching, and modular designs.

Supported Formats

  • JSON: Define amoeba, inputs, and connections in a structured format.
  • YAML: Similar to JSON but with more human-readable syntax.

License

This project is licensed under the PolyForm Noncommercial License 1.0.0.
You are free to use, modify, and share this software for noncommercial purposes only.

If you would like to use this project or any part of it in a commercial context (e.g., in a paid product, SaaS, monetized API, or any product or service that generates revenue), you must obtain a commercial license.

Please contact the author at https://github.com/gaotisan to discuss commercial licensing options.

Contact

Created by Gaotisan. Feel free to reach out via GitHub Issues. You can also connect with me on LinkedIn.