Socket
Book a DemoInstallSign in
Socket

@actioncrew/actionstack

Package Overview
Dependencies
Maintainers
1
Versions
64
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@actioncrew/actionstack

3.0.14
latest
Source
npmnpm
Version published
Maintainers
1
Created
Source

ActionStack Logo

Next-generation state management for reactive applications
Built on Streamix for ultimate performance and simplicity

Build Status NPM Version NPM Downloads Bundle Size AI-Powered

✨ Key Features

  • 🧩 Modular Architecture — Feature-based modules with co-located state and logic
  • ⚡ Reactive Streams — Built on Streamix for high-performance reactive updates
  • 🔄 Action Handlers — No reducers needed - sync actions with state logic
  • ⚡ Thunk Support — Built-in async operations via thunks
  • 🔒 Safe Concurrency — Built-in locking and execution control
  • 📦 Dynamic Loading — Load/unload modules at runtime
  • 🎯 Type Safety — Full TypeScript support with intelligent inference

📦 Installation

npm install @actioncrew/actionstack

🚀 Quick Start

import { createStore, createModule, action, thunk, selector } from '@actioncrew/actionstack';

// Actions with built-in state handlers
const increment = action('increment', 
  (state: number, payload: number = 1) => state + payload
);

const reset = action('reset', () => 0);

// Create module
const counterModule = createModule({
  slice: 'counter',
  initialState: 0,
  actions: { increment, reset },
  selectors: {
    count: selector((state: number) => state),
  }
});

// Initialize
const store = createStore();
counterModule.init(store);

// Use actions directly
counterModule.actions.increment(5);  // Counter: 5
counterModule.actions.reset();       // Counter: 0

// Subscribe to changes
counterModule.data$.count().subscribe(count => {
  console.log('Counter:', count);
});

🎯 Real-World Example

interface TodoState {
  todos: Todo[];
  loading: boolean;
}

const addTodo = action('add', 
  (state: TodoState, text: string) => ({
    ...state,
    todos: [...state.todos, { id: Date.now(), text, completed: false }]
  })
);

const setTodos = action('setTodos',
  (state: TodoState, todos: Todo[]) => ({ ...state, todos, loading: false })
);

const setLoading = action('setLoading',
  (state: TodoState, loading: boolean) => ({ ...state, loading })
);

// Thunk using createThunk
const fetchTodos = thunk('fetchTodos', () => 
  (dispatch, getState, dependencies) => {
    todoModule.actions.setLoading(true);
    
    dependencies.todoService.fetchTodos()
      .then(todos => todoModule.actions.setTodos(todos))
      .catch(error => {
        todoModule.actions.setLoading(false);
        console.error('Failed to fetch todos:', error);
      });
  }
);

// Selectors
const selectActiveTodos = selector(
  (state: TodoState) => state.todos.filter(t => !t.completed)
);

// Module with dependencies
const todoModule = createModule({
  slice: 'todos',
  initialState: { todos: [], loading: false },
  actions: { addTodo, setTodos, setLoading, fetchTodos },
  selectors: { selectActiveTodos },
  dependencies: { todoService: new TodoService() }
});

// Usage
todoModule.init(store);
todoModule.actions.fetchTodos();

// Reactive UI updates
todoModule.data$.selectActiveTodos().subscribe(activeTodos => {
  renderTodos(activeTodos);
});

🔄 Advanced Features

Static Module Loading

let store = createStore();
store.populate(authModule, uiModule, settingsModule);

Dynamic Module Loading

// Load modules at runtime
const featureModule = createDashboardModule();
featureModule.init(store);

// Unload when no longer needed and clear state
featureModule.destroy(true);

Stream Composition

import { combineLatest, map, filter, eachValueFrom } from '@actioncrew/streamix';

// Combine data from multiple modules
const dashboardData$ = combineLatest([
  userModule.data$.selectCurrentUser(),
  todoModule.data$.selectActiveTodos(),
  notificationModule.data$.selectUnread()
]).pipe(
  map(([user, todos, notifications]) => ({
    user,
    todoCount: todos.length,
    hasNotifications: notifications.length > 0
  }))
);

// React to combined state changes
for await (const data of eachValueFrom(dashboardData$)) {
  updateDashboard(data);
}

Store Configuration

const store = createStore({
  dispatchSystemActions: true,
  awaitStatePropagation: true,
  enableGlobalReducers: false,
  exclusiveActionProcessing: false
}, applyMiddleware(logger, devtools));

🔗 Why Query + Thunks = Perfect Match

The combination of Streamix's query() method and ActionStack's thunks creates a uniquely powerful and streamlined approach:

  • Reactive by default — Subscribe to streams for UI updates
  • Imperative when needed — Use query() for instant access in business logic
  • Consistent API — Same selectors work for both reactive and imperative use
  • Type-safe — Full TypeScript inference across reactive and sync access patterns
  • Performance optimized — Query avoids subscription overhead for one-time reads

🆚 ActionStack vs Other Solutions

FeatureActionStack V3Redux + RTKZustand
Bundle SizeMinimalLargeSmall
ReactivityBuilt-inManualManual
ModulesNativeManualManual
Type SafetyExcellentGoodGood
Async ActionsNativeThunksManual

📚 Resources

Ready for next-gen state management? 🚀
Install from NPMView on GitHub

Keywords

ActionStack

FAQs

Package last updated on 03 Sep 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.