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

react-runtime-pipe

v1.0.0

Published

A backend-style runtime for React with middleware, DI, plugins, and structured action execution.

Downloads

1,486

Readme

⚡ react-runtime-pipe

NPM Downloads Bundle Size

LIVE EXAMPLE

🚀 A backend-inspired execution runtime for React applications.

Build scalable frontend systems using middleware pipelines, typed actions, dependency injection, runtime context, plugins, orchestration, and event-driven execution.


Installation

npm install react-runtime-pipe

What is react-runtime-pipe?

react-runtime-pipe is a lightweight runtime for executing backend-style logic in React applications.

It brings concepts like middleware, dependency injection, and orchestration into frontend code.

It provides:

  • typed action execution
  • middleware pipelines
  • dependency injection
  • runtime context
  • plugins and event system
  • retry and cancellation support

without enforcing any specific state management approach.


Why react-runtime-pipe?

Frontend apps often become hard to scale as logic spreads across components and async flows become inconsistent.

Common problems:

  • business logic inside UI components
  • duplicated async logic
  • scattered dependencies
  • tightly coupled side effects
  • inconsistent orchestration

react-runtime-pipe solves this by introducing a structured execution layer:

  • predictable execution flow
  • composable middleware
  • centralized orchestration
  • backend-like architecture in frontend
  • framework-agnostic design

Features

  • ⚡ Runtime-first architecture
  • 🧩 Middleware pipeline
  • 🔌 Plugin system
  • 🧠 Typed execution context
  • 🛡 Action lifecycle hooks
  • ♻️ Retry orchestration
  • 📦 Dependency injection container
  • 📡 Event bus system
  • 📝 Full TypeScript inference
  • 🚦 Abort/cancellation support
  • 💾 Scoped execution cache
  • ⚛️ React integration
  • 🧱 Framework agnostic core

Mental Model

UI Event
    ↓
useAction()
    ↓
createExecutionContext()
    ↓
Plugins
    ↓
Middleware Pipeline
    ↓
Action Handler
    ↓
Service Layer
    ↓
Event Bus
    ↓
UI Update

Quick Start

Create App

// app.ts
import { createApp } from 'react-runtime-pipe'
import { loggerPlugin } from 'react-runtime-pipe/plugin'

import { ApiService } from './services/api'
import { ApiServiceToken } from './tokens'

export const app = createApp({
  services: [
    {
      token: ApiServiceToken,
      useValue: new ApiService(),
    },
  ],
})

app.plugin(loggerPlugin)

Define Action

import { defineAction } from 'react-runtime-pipe'
import { globalEvents } from 'react-runtime-pipe/react'
import { logger, retry } from 'react-runtime-pipe/middleware'

import { ApiServiceToken } from './tokens'

export const saveUserAction = defineAction({
  name: 'save-user',

  middleware: [logger, retry(3)],

  async handler({ input, context }) {
    context.logger.info('saving user', input)

    const api = context.container.resolve(ApiServiceToken)

    const user = await api.saveUser(input)

    // context.events.$emit('user:saved', user)
    globalEvents.$emit('user:saved', user)

    return {
      success: true,
      user,
    }
  },
})

Service Implementation

// api.ts
import { createRequestId } from 'react-runtime-pipe'

export class ApiService {
  async saveUser(input: any) {
    await new Promise((resolve) => {
      setTimeout(resolve, 500)
    })

    return {
      id: createRequestId(),
      input,
    }
  }
}

Tokens

// tokens.ts
import { createToken } from 'react-runtime-pipe'

import type { ApiService } from './services/api'

export const ApiServiceToken =
  createToken<ApiService>('ApiService')

React Usage

// Root.tsx
import React from 'react'

import {
  useAction,
  useEventBus,
  globalEvents,
} from 'react-runtime-pipe/react'

import { saveUserAction } from './saveUser'

export function Root() {
  const saveUser = useAction(saveUserAction)

  useEventBus(
    'user:saved',
    () => {
      alert('User saved successfully!')
    },
    globalEvents,
  )

  return (
    <div>
      <button
        disabled={saveUser.loading}
        onClick={() => {
          saveUser.execute({
            name: 'Tung',
          })
        }}
      >
        {saveUser.loading
          ? 'Saving...'
          : 'Save User'}
      </button>

      {saveUser.error ? (
        <pre>{String(saveUser.error)}</pre>
      ) : null}
    </div>
  )
}

Bootstrap

// main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'

import { RuntimeProvider } from 'react-runtime-pipe/react'

import { Root } from './Root'
import { app } from './app'

async function bootstrap() {
  await app.run()

  const rootElement =
    document.getElementById('root')

  if (!rootElement) {
    throw new Error(
      'Root element #root not found',
    )
  }

  ReactDOM.createRoot(rootElement).render(
    <React.StrictMode>
      <RuntimeProvider app={app}>
        <App />
      </RuntimeProvider>
    </React.StrictMode>,
  )
}

bootstrap()

Dependency Injection

import { createApp, createToken } from 'react-runtime-pipe'

class ApiService {
  async saveUser() {}
}

const ApiServiceToken = createToken<ApiService>('ApiService')

const app = createApp({
  services: [
    {
      token: ApiServiceToken,
      useFactory: () =>
        new ApiService(),
    },
  ],
})

Service Injection in Actions

import { defineAction } from 'react-runtime-pipe'

import { ApiServiceToken } from './tokens'

export const saveUserAction =
  defineAction({
    name: 'save-user',

    async handler({
      input,
      context,
    }) {
      const api =
        context.container.resolve(
          ApiServiceToken,
        )

      return api.saveUser(input)
    },
  })

useService hook

import { useService } from 'react-runtime-pipe/react'

import { ApiServiceToken } from './tokens'

export function UserPage() {
  const api = useService(ApiServiceToken)

  return null
}

Runtime Context

| Property | Description | |---------------|--------------------------| | ctx.requestId | execution request id | | ctx.signal | abort signal | | ctx.logger | runtime logger | | ctx.container | dependency container | | ctx.events | execution event bus | | ctx.cache | scoped execution cache | | ctx.auth | authenticated user state |


Event Bus

Emit Event

globalEvents.$emit(
  'user:saved',
  user,
)

Listen To Event

useEventBus(
  'user:saved',
  (payload) => {
    console.log(payload)
  },
  globalEvents,
)

Middleware

Middleware in react-runtime-pipe allows you to intercept and control the execution flow of an action.

Here is a simple example: Abort Middleware — used to stop execution if the request has been cancelled.

import type { Middleware } from 'react-runtime-pipe'

export const abortMiddleware: Middleware = async ({
  context,
  next,
}) => {
  // check before executing the handler
  context.throwIfAborted()

  const result = await next()

  // check after the handler finishes
  context.throwIfAborted()

  return result
}

This middleware ensures that if the user triggers an abort (e.g. cancels a request or unmounts a component), the action is immediately stopped both before and after execution.


Plugins

import type { Plugin } from 'react-runtime-pipe'

const analyticsPlugin: Plugin = {
  name: 'analytics',

  setup({ app }) {
    console.log('plugin setup')
  },
}

app.plugin(analyticsPlugin)

React Runtime Provider

import { RuntimeProvider } from 'react-runtime-pipe/react'

import { app } from './app'

export function Root() {
  return (
    <RuntimeProvider app={app}>
      <App />
    </RuntimeProvider>
  )
}

Action Lifecycle

useAction.execute()
      ↓
createExecutionContext()
      ↓
composeMiddleware()
      ↓
executeHandler()
      ↓
emitEvents()
      ↓
returnResult()

Execution Cache

const cacheKey = 'user:1'

if (ctx.cache.has(cacheKey)) {
  return ctx.cache.get(cacheKey)
}

const user = await api.getUser()

ctx.cache.set(cacheKey, user)

return user

Abort Support

ctx.throwIfAborted()
ctx.signal.addEventListener(
  'abort',
  () => {
    console.log('cancelled')
  },
)

Full Example

import { defineAction } from 'react-runtime-pipe'

import {
  logger,
  retry,
  auth,
} from 'react-runtime-pipe/middleware'
import { globalEvents } from 'react-runtime-pipe/react'

import { ApiServiceToken } from './tokens'

export const saveUserAction =
  defineAction({
    name: 'save-user',

    middleware: [
      auth,
      logger,
      retry(),
    ],

    async handler({
      input,
      context,
    }) {
      const api =
        context.container.resolve(
          ApiServiceToken,
        )

      const user =
        await api.saveUser(input)

      globalEvents.$emit(
        'user:saved',
        user,
      )

      return {
        success: true,
        user,
      }
    },
  })

Comparison

| Criteria | react-runtime-pipe | Redux | React Query | |---------------------|--------------------|-------|-------------| | Middleware Pipeline | ✅ | ⚠️ | ❌ | | Dependency Injection| ✅ | ❌ | ❌ | | Runtime Context | ✅ | ❌ | ❌ | | Event Bus | ✅ | ❌ | ❌ | | Orchestration Layer | ✅ | ❌ | ⚠️ | | Async Data Handling | ⚠️ | ❌ | ✅ | | Plugin System | ✅ | ❌ | ❌ | | Action-based API | ✅ | ❌ | ❌ | | Execution Pipeline | ✅ | ❌ | ❌ |

Philosophy

You control:
- middleware
- plugins
- orchestration
- architecture
- services

react-runtime-pipe controls:
- execution
- lifecycle
- context
- typing
- pipelines

Design

  • Explicit execution
  • Composition over inheritance
  • Backend-inspired architecture
  • Runtime-first design
  • Framework-agnostic core
  • Deterministic orchestration

When to Use

  • Large React applications
  • Complex async flows
  • Plugin-based frontends
  • Runtime orchestration systems
  • Event-driven UI architecture
  • Shared business execution layers
  • Backend/frontend unified patterns

License

MIT