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

@avallo/workflow-sdk

v0.2.0

Published

SDK for building custom Avallo Workflow nodes

Readme

@avallo/workflow-sdk

Official SDK for building custom integrations with Avallo Workflow Engine

npm version License: MIT

Build production-ready workflow actions and triggers for the Avallo Workflow Engine with a simple, TypeScript-first API.

Features

  • Simple API: Define actions and triggers with minimal boilerplate
  • 🔒 Type-Safe: Full TypeScript support with intelligent autocomplete
  • 🎯 Best-in-Class DX: Optimized for developer experience
  • 🔄 Variable Interpolation: Built-in support for {{variable}} syntax
  • 📊 Schema Generation: Automatic JSON Schema + UI Schema generation
  • 🔌 Plug & Play: Works seamlessly with the Avallo Workflow Engine

Installation

npm install @avallo/workflow-sdk
# or
pnpm add @avallo/workflow-sdk
# or
yarn add @avallo/workflow-sdk

Quick Start

Creating an Action

import { defineAction } from '@avallo/workflow-sdk';

export default defineAction({
  id: 'send-email',
  name: 'Send Email',
  description: 'Sends an email via SMTP',
  
  config: {
    to: {
      type: 'string',
      label: 'To',
      description: 'Recipient email address',
      required: true,
      supportsVariables: true,
    },
    subject: {
      type: 'string',
      label: 'Subject',
      required: true,
      supportsVariables: true,
    },
    body: {
      type: 'textarea',
      label: 'Body',
      required: true,
      supportsVariables: true,
    },
  },
  
  async execute(context) {
    // Interpolate variables like {{previous_node.email}}
    const to = context.utils.interpolate(context.config.to);
    const subject = context.utils.interpolate(context.config.subject);
    const body = context.utils.interpolate(context.config.body);
    
    // Your email sending logic here
    await sendEmail({ to, subject, body });
    
    return {
      success: true,
      message_id: 'msg_123',
      sent_at: new Date().toISOString(),
    };
  },
  
  outputs: {
    success: {
      type: 'boolean',
      label: 'Success',
      description: 'Whether the email was sent successfully',
    },
    message_id: {
      type: 'string',
      label: 'Message ID',
      description: 'Unique identifier for the sent email',
    },
    sent_at: {
      type: 'string',
      label: 'Sent At',
      description: 'Timestamp when the email was sent',
    },
  },
});

Creating a Trigger

import { defineTrigger } from '@avallo/workflow-sdk';

export default defineTrigger({
  id: 'new-email',
  name: 'New Email',
  description: 'Triggers when a new email arrives',
  type: 'polling',
  
  config: {
    folder: {
      type: 'select',
      label: 'Folder',
      description: 'Which folder to monitor',
      required: true,
      options: [
        { label: 'Inbox', value: 'inbox' },
        { label: 'Sent', value: 'sent' },
        { label: 'Drafts', value: 'drafts' },
      ],
    },
  },
  
  async execute(context) {
    const folder = context.trigger_config.folder;
    
    // Fetch new emails
    const emails = await fetchNewEmails(folder);
    
    // Return result
    return context.utils.createResult(
      emails.length > 0,
      emails,
      {
        checked_at: new Date(),
        items_found: emails.length,
      }
    );
  },
  
  outputs: {
    from: {
      type: 'string',
      label: 'From',
      description: 'Sender email address',
    },
    subject: {
      type: 'string',
      label: 'Subject',
      description: 'Email subject',
    },
    body: {
      type: 'string',
      label: 'Body',
      description: 'Email body content',
    },
    received_at: {
      type: 'string',
      label: 'Received At',
      description: 'Timestamp when email was received',
    },
  },
  
  polling_config: {
    interval_seconds: 300, // Check every 5 minutes
    dedupe_key: 'email_id',
  },
});

Creating a Complete App

import { defineApp } from '@avallo/workflow-sdk';
import sendEmailAction from './actions/send-email';
import newEmailTrigger from './triggers/new-email';

export default defineApp({
  app_id: 'my-email-app',
  name: 'My Email App',
  description: 'Email integration for workflows',
  category: 'communication',
  icon_url: 'https://example.com/icon.png',
  
  actions: [sendEmailAction],
  triggers: [newEmailTrigger],
});

API Reference

defineAction(options)

Define a workflow action node.

Options:

  • id (string): Unique identifier for the action
  • name (string): Display name
  • description (string): Short description
  • category (string, optional): Category for grouping
  • icon (string, optional): Icon name or URL
  • config (SimplifiedConfigSchema): Configuration fields
  • execute (function): Execution handler
  • outputs (SimplifiedOutputSchema): Output field definitions
  • requires_connection (boolean, optional): Whether connection is needed
  • is_premium (boolean, optional): Whether action requires premium plan
  • documentation_url (string, optional): Link to documentation

Returns: { definition, execute }

defineTrigger(options)

Define a workflow trigger node.

Options:

  • id (string): Unique identifier for the trigger
  • name (string): Display name
  • description (string): Short description
  • type ('webhook' | 'polling' | 'event'): Trigger type
  • category (string, optional): Category for grouping
  • icon (string, optional): Icon name or URL
  • config (SimplifiedConfigSchema): Configuration fields
  • execute (function): Execution handler
  • outputs (SimplifiedOutputSchema): Output field definitions
  • polling_config (object, optional): Polling configuration
    • interval_seconds (number): Check interval in seconds
    • dedupe_key (string, optional): Field to deduplicate on
  • requires_connection (boolean, optional): Whether connection is needed
  • is_premium (boolean, optional): Whether trigger requires premium plan
  • documentation_url (string, optional): Link to documentation

Returns: { definition, execute }

defineApp(options)

Define a complete app with multiple actions and triggers.

Options:

  • app_id (string): Unique app identifier
  • name (string): App name
  • description (string, optional): App description
  • icon_url (string, optional): App icon URL
  • category (string, optional): App category
  • actions (array): Array of defined actions
  • triggers (array, optional): Array of defined triggers

Returns: App registration object

Configuration Field Types

| Type | Description | Example | |------|-------------|---------| | string | Text input | Email address, name | | number | Numeric input | Age, count | | boolean | Checkbox | Enable feature | | select | Dropdown | Choose option | | multiselect | Multi-select | Tags | | textarea | Multi-line text | Message body | | date | Date picker | Birth date | | datetime | Date + time picker | Scheduled time |

Context Utilities

Action Context

context.config                    // Parsed configuration
context.workflow_id               // Current workflow ID
context.execution_id              // Current execution ID
context.node_id                   // Current node ID
context.previous_outputs          // All previous node outputs

// Utilities
context.utils.interpolate(str)    // Interpolate {{variables}}
context.utils.fetch(url, options) // Make HTTP requests
context.utils.log(level, msg)     // Log messages

Trigger Context

context.trigger_config            // Trigger configuration
context.workflow_id               // Workflow ID
context.client_id                 // Client ID
context.account_id                // Account ID

// Utilities
context.utils.interpolate(str)           // Interpolate {{variables}}
context.utils.fetch(url, options)        // Make HTTP requests
context.utils.log(level, msg)            // Log messages
context.utils.createResult(hasData, data) // Create trigger result

Variable Interpolation

The SDK supports variable interpolation using {{variable}} syntax:

// In config
{
  email: {
    type: 'string',
    label: 'Email',
    supportsVariables: true, // Enable variable interpolation
  }
}

// In execute function
const email = context.utils.interpolate(context.config.email);
// "{{webhook.body.email}}" → "[email protected]"

Error Handling

import { createActionError, createActionSuccess } from '@avallo/workflow-sdk';

async execute(context) {
  try {
    const result = await doSomething();
    return createActionSuccess(result, {
      duration_ms: 150,
      records_processed: 5,
    });
  } catch (error) {
    return createActionError(error.message, {
      error_code: error.code,
    });
  }
}

Best Practices

  1. Validate Configuration: Use the validate hook to validate configuration before execution
  2. Use Type Safety: Leverage TypeScript for better DX
  3. Log Appropriately: Use context.utils.log() for debugging
  4. Handle Errors Gracefully: Always wrap execution in try/catch
  5. Document Outputs: Provide clear descriptions for all output fields
  6. Support Variables: Enable supportsVariables for user-facing strings
  7. Test Thoroughly: Test with real workflow executions

Examples

See the examples directory for more complete examples:

Support

License

MIT © Avallo