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

@context-action/core

v0.8.4

Published

Type-safe action pipeline management library for JavaScript/TypeScript

Readme

@context-action/core

Type-safe action pipeline management library for JavaScript/TypeScript applications with advanced filtering, performance optimizations, and React integration support.

Installation

npm install @context-action/core
# or
pnpm install @context-action/core

Quick Start

import { ActionRegister } from '@context-action/core';

// Define your action types
interface MyActions {
  increment: void;
  setCount: number;
  updateUser: { id: string; name: string };
}

// Create action register
const actions = new ActionRegister<MyActions>({
  name: 'MyApp',
  registry: { debug: true }
});

// Register handlers with priorities
actions.register('increment', () => {
  console.log('Increment called');
}, { priority: 10 });

actions.register('setCount', (count) => {
  console.log(`Setting count to: ${count}`);
}, { priority: 5 });

// Dispatch actions
await actions.dispatch('increment');
await actions.dispatch('setCount', 42);

Memory Management

// Configure handler limits for memory safety (v0.4.1+)
const actions = new ActionRegister<MyActions>({
  registry: {
    maxHandlersPerAction: 1000      // Default: 1000, prevents memory issues
    // maxHandlersPerAction: 5000   // Higher limit for complex applications
    // maxHandlersPerAction: Infinity // Disable limit (use with caution)
  }
});

// Use cases for different limits:
// - 1000 (default): Most applications
// - 5000-10000: Large enterprise applications  
// - Infinity: Only for controlled environments with trusted code

🚀 New Features (v0.4.0+)

Advanced Filtering System

Filter handlers by priority, ID, or custom conditions:

// Filter by priority range
await actions.dispatch('updateUser', userData, {
  filter: {
    priority: { min: 10, max: 50 }  // Only handlers with priority 10-50
  }
});

// Filter by specific handler IDs
await actions.dispatch('processData', data, {
  filter: {
    handlerIds: ['validation', 'logging'],  // Only these handlers
    excludeHandlerIds: ['analytics']        // Exclude analytics handler
  }
});

// Custom filtering logic
await actions.dispatch('secureAction', data, {
  filter: {
    custom: (config) => config.blocking === true  // Only blocking handlers
  }
});

// Combined filtering
await actions.dispatch('complexAction', data, {
  filter: {
    priority: { min: 20 },
    excludeHandlerIds: ['debug'],
    custom: (config) => !config.id.includes('test')
  }
});

Enhanced Handler Configuration

actions.register('myAction', handler, {
  priority: 10,
  id: 'my-handler',
  blocking: true,
  once: false,
  debounce: 300,
  throttle: 1000,
  replaceExisting: true  // 🆕 Replace handler with same ID (great for React HMR)
});

Immediate Execution & Queue Control

// Bypass queue for immediate execution
await actions.dispatch('urgentAction', data, {
  immediate: true
});

// Queue with custom priority
await actions.dispatch('backgroundTask', data, {
  queuePriority: 5
});

// Execution timeout
await actions.dispatch('timedAction', data, {
  timeout: 5000
});

Result Collection with Strategies

const result = await actions.dispatchWithResult('processData', data, {
  result: {
    collect: true,
    strategy: 'all',      // 'first' | 'last' | 'all' | 'merge' | 'custom'
    maxResults: 10,
    includeErrors: true
  }
});

console.log('Results:', result.results);
console.log('Execution time:', result.execution.duration);
console.log('Success:', result.success);

React Integration Helpers

import { 
  useActionHandler, 
  ReactDevUtils 
} from '@context-action/core';

// React hook pattern
function MyComponent() {
  const registry = useActionRegister();
  
  // Auto-cleanup on unmount, HMR support
  const handlerConfig = useActionHandler(
    registry,
    'userAction', 
    async (payload) => {
      // Handler logic
    },
    { priority: 10 },
    [] // dependencies
  );
  
  // Direct registry dispatch with error handling
  const handleDispatch = useCallback(async (action, payload) => {
    try {
      await registry.dispatch(action, payload);
    } catch (error) {
      console.error(`Failed to dispatch ${action}:`, error);
    }
  }, [registry]);
}

// Development utilities
ReactDevUtils.enableDebugMode();
const stats = ReactDevUtils.getStats(registry);

Core Features

🎯 Type-Safe Action Pipeline

  • Full TypeScript support with compile-time type checking
  • Priority-based execution with configurable handler ordering
  • Pipeline control - abort, modify payloads, conditional execution
  • Multiple execution modes - sequential, parallel, race

⚡ Performance & Memory Optimizations

  • Cached environment checks for better performance
  • Optimized handler ID generation without random numbers
  • Smart array filtering - only copies when needed
  • Automatic memory cleanup with idle handler cleanup
  • Optional concurrency queues for thread safety

🔧 Advanced Configuration

const registry = new ActionRegister<MyActions>({
  name: 'MyApp',
  registry: {
    debug: true,
    autoCleanup: true,
    defaultExecutionMode: 'sequential',
    useConcurrencyQueue: true,
    errorHandler: (error, context) => {
      console.error('Unhandled action error:', error);
    }
  }
});

🎛️ Pipeline Controller

Full control over pipeline execution:

actions.register('validate', (data, controller) => {
  // Abort pipeline
  if (!data.isValid) {
    controller.abort('Validation failed');
    return;
  }
  
  // Modify payload for next handlers
  controller.modifyPayload(data => ({ 
    ...data, 
    validated: true,
    timestamp: Date.now()
  }));
  
  // Jump to high-priority handlers
  if (data.urgent) {
    controller.jumpToPriority(100);
  }
  
  // Set result for collection
  controller.setResult({ validation: 'passed' });
  
  // Early return with result
  if (data.fastPath) {
    controller.return({ fastPath: true });
  }
});

Advanced Usage

Action Guard (Debounce/Throttle)

// Built-in debounce/throttle support
actions.register('searchUsers', searchHandler, {
  debounce: 300  // Wait 300ms after last call
});

actions.register('scrollHandler', updateUI, {
  throttle: 100  // Max once per 100ms
});

// Via dispatch options
await actions.dispatch('search', query, {
  debounce: 500
});

Execution Modes

// Set execution mode per action
actions.setActionExecutionMode('logEvent', 'parallel');
actions.setActionExecutionMode('fetchData', 'race');

// Override via dispatch options
await actions.dispatch('processFiles', files, {
  executionMode: 'parallel'
});

Error Handling & Recovery

actions.register('riskyOperation', async (data, controller) => {
  try {
    const result = await riskyAPI(data);
    return result;
  } catch (error) {
    if (error.retryable) {
      // Let other handlers try
      return undefined;
    } else {
      // Abort pipeline for critical errors
      controller.abort(`Critical error: ${error.message}`);
    }
  }
});

// With retry configuration
await actions.dispatch('apiCall', data, {
  retryOnError: {
    maxAttempts: 3,
    delay: 1000
  }
});

Statistics & Monitoring

// Registry information
const info = actions.getRegistryInfo();
console.log(`Total actions: ${info.totalActions}`);
console.log(`Total handlers: ${info.totalHandlers}`);

// Action-specific statistics
const stats = actions.getActionStats('updateUser');
if (stats) {
  console.log(`Handler count: ${stats.handlerCount}`);
  console.log(`Success rate: ${stats.executionStats?.successRate}%`);
  console.log(`Average duration: ${stats.executionStats?.averageDuration}ms`);
}

// Clear statistics
actions.clearExecutionStats();

Cleanup & Resource Management

// Explicit cleanup when done
const registry = new ActionRegister({ name: 'MyApp' });

// Use the registry...

// Clean up all resources
registry.destroy(); // Cleans up pipelines, guards, queues, stats

API Reference

ActionRegister

Registration Methods

  • register<K>(action, handler, config?) - Register action handler
  • clearAction(action) - Remove all handlers for action
  • clearAll() - Remove all handlers

Dispatch Methods

  • dispatch<K>(action, payload?, options?) - Dispatch action
  • dispatchWithResult<K>(action, payload?, options?) - Dispatch with detailed results

Information Methods

  • getHandlerCount(action) - Get handler count for action
  • hasHandlers(action) - Check if action has handlers
  • getRegisteredActions() - Get all registered action names
  • getRegistryInfo() - Get comprehensive registry information
  • getActionStats(action) - Get detailed action statistics

Execution Mode Methods

  • setActionExecutionMode(action, mode) - Set execution mode for action
  • getActionExecutionMode(action) - Get execution mode for action
  • removeActionExecutionMode(action) - Reset to default execution mode

Utility Methods

  • getName() - Get registry name
  • isDebugEnabled() - Check if debug mode is enabled
  • destroy() - Clean up all resources

Configuration Interfaces

interface HandlerConfig {
  priority?: number;           // Handler priority (higher = first)
  id?: string;                // Unique handler identifier
  blocking?: boolean;          // Wait for async completion
  once?: boolean;             // Remove after first execution  
  debounce?: number;          // Debounce delay in ms
  throttle?: number;          // Throttle delay in ms
  replaceExisting?: boolean;   // Replace handler with same ID
}

interface DispatchOptions {
  debounce?: number;
  throttle?: number;
  executionMode?: 'sequential' | 'parallel' | 'race';
  signal?: AbortSignal;
  immediate?: boolean;         // Bypass queue
  queuePriority?: number;      // Queue priority
  timeout?: number;           // Execution timeout
  
  retryOnError?: {
    maxAttempts: number;
    delay: number;
  };
  
  filter?: {
    handlerIds?: string[];
    excludeHandlerIds?: string[];
    priority?: { min?: number; max?: number };
    custom?: (config: HandlerConfig) => boolean;
  };
  
  result?: {
    strategy?: 'first' | 'last' | 'all' | 'merge' | 'custom';
    merger?: <R>(results: R[]) => R;
    collect?: boolean;
    maxResults?: number;
    includeErrors?: boolean;
  };
}

TypeScript Support

Full type safety with excellent IntelliSense support:

interface AppActions {
  // Void actions
  reset: void;
  logout: void;
  
  // Actions with payloads
  setUser: { id: string; name: string; email: string };
  updatePreferences: { theme: 'light' | 'dark'; language: string };
  
  // Union type payloads
  navigate: { route: string } | { url: URL };
}

const actions = new ActionRegister<AppActions>();

// ✅ Type-safe - all good
await actions.dispatch('reset');
await actions.dispatch('setUser', { id: '1', name: 'John', email: '[email protected]' });

// ❌ TypeScript errors
await actions.dispatch('setUser');              // Missing required payload
await actions.dispatch('setUser', { id: '1' }); // Missing required fields
await actions.dispatch('invalidAction');        // Unknown action

Migration from v0.3.x

Most existing code works without changes. New features are opt-in:

// v0.3.x code - still works
const actions = new ActionRegister();
actions.register('myAction', handler);
await actions.dispatch('myAction', payload);

// v0.4.x - new features available
actions.register('myAction', handler, { 
  replaceExisting: true  // New option
});

await actions.dispatch('myAction', payload, {
  filter: { priority: { min: 10 } }  // New filtering
});

// Clean up when done (recommended)
actions.destroy();

Performance Tips

  1. Use handler IDs for better debugging and filtering
  2. Enable replaceExisting for React components to prevent duplicates
  3. Use immediate: false (default) to benefit from queue optimizations
  4. Call destroy() when registry is no longer needed
  5. Use priority filtering instead of excludeHandlerIds for better performance
  6. Cache ActionRegister instances - don't create new ones frequently

License

Apache-2.0

Links