DEV Community

Smiling Sloth
Smiling Sloth

Posted on

Introducing EventFlow: A Type-Safe Event Broker for Modern Frontend Applications

Frontend applications are becoming increasingly complex, with components and modules needing to communicate across the application without creating tight coupling. While solutions like Redux or global state management tools work well for application state, they can be overkill for simple event-based communication or introduce unnecessary complexity.

Today, I'm excited to introduce EventFlow, a lightweight, type-safe event broker designed specifically for frontend applications.

What is EventFlow?

EventFlow is a TypeScript-first event broker that provides a simple yet powerful way to handle events in your frontend applications. It combines the simplicity of event emitters with the safety of TypeScript, making it an ideal choice for modern web applications.

Key Features

  • 🎯 Type Safety: Full TypeScript support with type inference for events and their payloads
  • Lightweight: Zero dependencies for core functionality
  • 🔌 Middleware System: Extensible through a powerful middleware system
  • 🛡️ Error Handling: Configurable error policies for robust applications
  • ⚛️ React Integration: First-class React support with hooks and context
  • 📦 Tree-shakeable: Only bundle what you use

Why Another Event Library?

While there are many event libraries available, EventFlow addresses several common challenges in frontend development:

  1. Type Safety: Unlike traditional event emitters, EventFlow ensures your events and their payloads are fully typed.
  2. Decoupled Communication: Enable components to communicate without direct dependencies.
  3. Cross-Cutting Concerns: Handle application-wide concerns through the middleware system.
  4. Framework Independence: Works with any JavaScript environment while providing first-class React support.
  5. Predictable Error Handling: Configure how your application behaves when events fail.

Getting Started

Installation is straightforward:

# Using npm
npm install @thesmilingsloth/eventflow-core
npm install @thesmilingsloth/eventflow-react # Optional React integration

# Using pnpm
pnpm add @thesmilingsloth/eventflow-core
pnpm add @thesmilingsloth/eventflow-react # Optional React integration
Enter fullscreen mode Exit fullscreen mode

Basic Usage

import { createEventBroker } from "@thesmilingsloth/eventflow-core";

// Define your events
interface MyEvents {
  "user:login": {
    userId: string;
    timestamp: number;
  };
  "app:notification": {
    message: string;
    type: "success" | "error";
  };
}

// Create broker
const broker = createEventBroker<MyEvents>({
  // Enable console logging middleware
  logger: true,
  // Configure max listeners per event
  maxListeners: 10,
  // Add custom middlewares
  middlewares: [
    // Example: Analytics middleware
    (next) => (event) => {
      console.log(`[Analytics] Event ${event.name} triggered`);
      next(event);
    },
    // Example: Error tracking middleware
    (next) => (event) => {
      try {
        next(event);
      } catch (error) {
        console.error(`[Error] in event ${event.name}:`, error);
        throw error;
      }
    },
  ],
});

// Subscribe to events
const unsubscribe = broker.on("user:login", (data) => {
  console.log(`User ${data.userId} logged in`);
});

// Emit events
broker.emit("user:login", {
  userId: "123",
  timestamp: Date.now(),
});
Enter fullscreen mode Exit fullscreen mode

React Integration

The React integration package provides hooks for seamless integration with React components:

import {
  EventBrokerProvider,
  useEventListener,
  useEventEmitter,
} from "@thesmilingsloth/eventflow-react";

function App() {
  return (
    <EventBrokerProvider broker={broker}>
      <LoginButton />
      <NotificationListener />
    </EventBrokerProvider>
  );
}

function LoginButton() {
  const emitLogin = useEventEmitter("user:login");

  return (
    <button
      onClick={() =>
        emitLogin({
          userId: "123",
          timestamp: Date.now(),
        })
      }
    >
      Login
    </button>
  );
}

function NotificationListener() {
  useEventListener("app:notification", (data) => {
    alert(`${data.type}: ${data.message}`);
  });

  return null;
}
Enter fullscreen mode Exit fullscreen mode

Advanced Features

Middleware System

EventFlow's middleware system allows you to intercept and transform events:

const analyticsMiddleware: Middleware<MyEvents> = (next) => (event) => {
  // Before event
  trackEvent(event.name, event.data);

  // Process event
  next(event);

  // After event
  console.log("Event processed:", event.name);
};

broker.use(analyticsMiddleware);
Enter fullscreen mode Exit fullscreen mode

Error Handling

Configure how your application handles errors:

const broker = createEventBroker<MyEvents>({
  errorPolicy: {
    onListenerError: "continue",
    onEmitError: "stop",
    onMiddlewareError: (error, event) => {
      reportError(error);
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

Use Cases

EventFlow is particularly useful for:

  1. Cross-Component Communication: When components need to communicate without direct coupling
  2. Application-Wide Events: For handling global notifications, theme changes, or user actions
  3. Analytics and Logging: Using middleware to track events across your application
  4. State Synchronization: When multiple components need to react to the same state changes
  5. Error Handling: Centralizing error handling and reporting

Conclusion

EventFlow brings type-safe event handling to frontend applications with a focus on developer experience and flexibility. Whether you're building a small React application or a large-scale frontend system, EventFlow provides the tools you need for robust event-based communication.

Try it out today and let me know what you think! The project is open source and contributions are welcome.

GitHub Repository | npm Package

Top comments (0)