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

@epikodelabs/streamix

v3.0.12

Published

Pull-based reactive streams with async iterators

Downloads

1,239

Readme

Project status: Core development of the current generation is complete. Angular, React, and Vue integrations support atoms and scopes; broader integration testing and real-world feedback are ongoing. Found an edge case? We'd love a reproduction.

Why Streamix?

Reactive code should describe what changes, not spend half its life explaining who subscribes to whom.

Streamix is a lightweight reactive runtime for JavaScript and TypeScript. It combines synchronous state, dependency-tracked calculations, and async-iterator-based flows with explicit ownership and cleanup.

  • Values are atoms. Read and update state synchronously.
  • Calculations are derived. Track dependencies instead of manually syncing copies.
  • Time is a flow. Compose events, timers, and async work with familiar operators.
  • Related things belong in scopes. Own state, subscriptions, and disposal together.
  • Multiple writes can be one transaction. Avoid showing observers half-finished updates.
  • Async iteration is native. Use for await...of instead of learning another universe.

Less orchestration. More consumption. The runtime handles the wiring; you write the logic.

Get started

npm install @epikodelabs/streamix

Also available via pnpm add @epikodelabs/streamix or yarn add @epikodelabs/streamix.

1. Start with a scope

A scope looks like an ordinary object, but its members are reactive and share a lifecycle.

import { scope } from '@epikodelabs/streamix';

const counter = scope<{
  count: number;
  doubled: number;
}>({
  count: 0,
  doubled: self => self.count * 2,
});

counter.count = 5;
console.log(counter.doubled); // 10

counter.subscribeTo('count', value => console.log('Count:', value));
counter.count = 6; // Count: 6

counter.dispose(); // One exit. No subscription archaeology.

You work with plain properties. When you need the reactive primitive itself, use counter.get('count'); to write through the scope API, use counter.set('count', 7).

Scopes keep their owned atoms active, including flow-backed members, and dispose of their resources together. Prefer a scope for related state; a standalone atom is perfect when one value genuinely stands alone.

2. Use atoms for standalone values

import { atom, iterate } from '@epikodelabs/streamix';

const temperature = atom(21);
temperature.set(22);

for await (const value of iterate(temperature)) {
  console.log('Temperature:', value);
}

atom(initial) has a value immediately; atom<T>() can start without one. Subscribers receive the current value when available, then subsequent updates. Use derived() for synchronous computations whose dependencies should be tracked automatically.

Rule of thumb: If it can be calculated, don't store a second copy of it.

3. Let asynchronous work flow

import { pipe, take } from '@epikodelabs/streamix';

async function* countdown() {
  for (let seconds = 3; seconds > 0; seconds--) {
    yield `T-${seconds}`;
    await new Promise(resolve => setTimeout(resolve, 500));
  }
  yield '🚀 Launch!';
}

for await (const message of pipe(countdown(), take(4))) {
  console.log(message);
}

Flows compose sequences with operators such as map, filter, switchMap, debounce, and scan — plus 40+ others. Pull-based iteration means a consumer requests the next value rather than receiving an uncontrolled stream of work.

For computations that need await, cancellation, or restart semantics, use a flow rather than an asynchronous derived() function. For related writes that must appear together, use transaction().

Four rules worth remembering

1. If it has a value, make it an atom.
2. If it can be calculated, don't store it.
3. If it takes time, let it flow.
4. Don't chase values — ask for the next one.

There are 14 unofficial rules, but don't worry: there's no exam. The remaining principles cover ownership, cancellation, multicasting, and keeping the machinery out of your way.

Under the hood (without the engine diagram)

| Concept | Responsibility | | --- | --- | | Atom | Hold and publish a reactive value. | | Derived | Calculate a value from tracked dependencies. | | Flow | Represent values and asynchronous work over time. | | Scope | Group reactive members and own their lifecycle. | | Transaction | Make a set of writes observable as one consistent update. | | Operators | Transform and coordinate sequences. |

Streamix is async-iterator first and tree-shakeable. The package marks its optional introspection entry point as side-effectful so bundlers preserve diagnostics activation when it is included. It supports familiar reactive operators without requiring a framework to own your state.

Use it where you build

Streamix is framework-independent at its core. Angular, React, and Vue integrations bring atoms and scopes into application code; integration testing continues, so check the documentation and report compatibility issues.

The runtime, diagnostics, and framework tooling are separate entry points within the same @epikodelabs/streamix npm package. Install the package once and import the parts you need.

| Runtime and tooling entry point | Includes | | --- | --- | | @epikodelabs/streamix | Atoms, derived state, scopes, flows, operators | | @epikodelabs/streamix/aggregates | Aggregates including average, min, max, and sum | | @epikodelabs/streamix/dom | DOM observers, animation frames, media queries, intersections | | @epikodelabs/streamix/networking | HTTP, WebSocket, JSONP | | @epikodelabs/streamix/introspection | Optional runtime diagnostics, execution inspection, and the browser inspector panel | | @epikodelabs/streamix/compiler | Shared introspection transforms and activation injection used by framework toolchains |

Each framework has its own runtime adapter, compiler, builder, and editor integration. React and Vue also provide Vite plugins.

| Framework | Runtime adapter | Compiler | Architect builder | Vite plugin | Editor tooling | | --- | --- | --- | --- | --- | --- | | Angular | /angular | /angular/compiler | /angular/builder | — | /angular/editor | | React | /react | /react/compiler | /react/builder | /react/vite | /react/editor | | Vue | /vue | /vue/compiler | /vue/builder | /vue/vite | /vue/editor |

All paths in the framework table are relative to @epikodelabs/streamix; for example, @epikodelabs/streamix/react/vite. The runtime adapters connect Streamix state to each framework's rendering model, while the compiler and build tooling transform application code. Editor tooling supplies framework-specific authoring support.

Project structure

projects/libraries/streamix/
├── src/                  # Framework-independent reactive runtime
│   └── lib/
│       ├── atoms/        # Reactive state and derived values
│       ├── factories/    # Flow factories
│       ├── operators/    # Flow transformations and coordination
│       ├── primitives/   # Shared reactive primitives
│       ├── runtime/      # Execution, scheduling, and lifecycle machinery
│       └── utils/        # Runtime utilities
├── aggregates/           # Aggregate operators
├── dom/                  # DOM and browser observation utilities
├── networking/           # HTTP, WebSocket, and JSONP
├── introspection/        # Optional diagnostics and inspector panel
├── compiler/             # Shared diagnostics instrumentation
├── angular/              # Angular runtime adapter
│   ├── compiler/         # Template compiler
│   ├── builder/          # Angular Architect integration
│   ├── editor/           # Editor integration
│   └── benchmarks/       # Angular benchmark applications
├── react/                # React runtime adapter
│   ├── compiler/         # JSX/TSX compiler
│   ├── builder/          # Angular Architect integration for React apps
│   ├── vite/             # Vite plugin
│   └── editor/           # Editor integration
└── vue/                  # Vue runtime adapter
    ├── compiler/         # Vue SFC compiler
    ├── builder/          # Angular Architect integration for Vue apps
    ├── vite/             # Vite plugin
    └── editor/           # Editor integration

Diagnostics are opt-in: development toolchains can inject introspection activation and mount the inspector, while application code continues to import reactive primitives from the core entry point. See the framework guides for build configuration.

The extended family

Streamix also works alongside other Epikode Labs packages:

| Package | What it's for | | --- | --- | | @epikodelabs/coroutines | Workers, structured tasks, channels, and actors | | @epikodelabs/waypoint | Server-authorized routing for Angular | | @epikodelabs/forms | Framework-independent reactive forms |

No need to adopt the whole family. Start with the piece that solves your problem.

Learn more

Come build with us

Have a question, an operator idea, a bug report, or a spectacularly strange use case? We're interested.

Build reactive applications. Not subscription management systems.

License

MIT