Skip to content

wespreadjam/jam-nodes

Repository files navigation

jam-nodes

Extensible workflow node framework for building automation pipelines. Define, register, and execute typed nodes with Zod validation.

📚 Documentation · 🎮 Playground

Packages

Installation

npm install @jam-nodes/core @jam-nodes/nodes zod

Quick Start

import { NodeRegistry, defineNode, ExecutionContext } from "@jam-nodes/core";
import { conditionalNode, endNode, builtInNodes } from "@jam-nodes/nodes";
import { z } from "zod";

// Create a registry and register built-in nodes
const registry = new NodeRegistry();
registry.registerAll(builtInNodes);

// Define a custom node
const greetNode = defineNode({
  type: "greet",
  name: "Greet",
  description: "Generate a greeting message",
  category: "action",
  inputSchema: z.object({
    name: z.string(),
  }),
  outputSchema: z.object({
    message: z.string(),
  }),
  executor: async (input) => ({
    success: true,
    output: { message: `Hello, ${input.name}!` },
  }),
});

// Register custom node
registry.register(greetNode);

// Execute a node
const context = new ExecutionContext({ userName: "World" });
const executor = registry.getExecutor("greet");
const result = await executor(
  { name: context.interpolate("{{userName}}") },
  context.toNodeContext("user-123", "workflow-456"),
);

console.log(result.output?.message); // "Hello, World!"

Creating Custom Nodes

import { defineNode } from "@jam-nodes/core";
import { z } from "zod";

export const myNode = defineNode({
  type: "my_custom_node",
  name: "My Custom Node",
  description: "Does something awesome",
  category: "action", // 'action' | 'logic' | 'integration' | 'transform'

  inputSchema: z.object({
    input1: z.string(),
    input2: z.number().optional(),
  }),

  outputSchema: z.object({
    result: z.string(),
  }),

  capabilities: {
    supportsRerun: true,
    supportsCancel: true,
  },

  executor: async (input, context) => {
    // Access workflow variables
    const previousData = context.resolveNestedPath("someNode.output");

    // Your logic here
    const result = `Processed: ${input.input1}`;

    return {
      success: true,
      output: { result },
      // Optional: send notification
      notification: {
        title: "Node Complete",
        message: "Processing finished",
      },
    };
  },
});

Built-in Nodes

Logic

  • conditional - Branch workflow based on conditions
  • end - Mark end of workflow branch
  • delay - Wait for specified duration

Transform

  • map - Extract property from array items
  • filter - Filter array based on conditions

Examples

  • http_request - Make HTTP requests to external APIs

Variable Interpolation

The ExecutionContext supports powerful variable interpolation:

const ctx = new ExecutionContext({
  user: { name: "Alice", email: "alice@example.com" },
  items: [1, 2, 3],
});

// Simple interpolation
ctx.interpolate("Hello {{user.name}}"); // "Hello Alice"

// Direct value (returns actual type)
ctx.interpolate("{{items}}"); // [1, 2, 3]

// JSONPath
ctx.evaluateJsonPath("$.user.email"); // "alice@example.com"

License

MIT

About

Extensible workflow node framework for building automation pipelines. Define, register, and execute typed nodes with Zod validation.

Resources

License

Contributing

Stars

197 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages