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 🙏

© 2025 – Pkg Stats / Ryan Hefner

the-observable-plugin-system

v0.1.2

Published

The streaming plugin manager

Readme

npm

The Observable Plugin System

The first plugin/module manager for stream-oriented web applications

Motivation

If you have a growing webapp based on RxJS and/or Observables and you want to extend it with plugins, you may have noticed the Observable pattern is not directly compatible with the Request/Response nature of plugin systems.

We are bringing the best of both here, by creating the Duplex Observable: a new kind of Observable Subject that supports two-way communication, new methods such as .invoke() and .reply(), in addition to new operators such as switchInvoke() and emit().

Using the above you can define your plugins as pure observable streams.

Installation

npm install -S 'the-observable-plugin-system';

Usage

You can create a messabus and initialise your plugins in your main entry point:

main.js

import TOPS from 'the-observable-plugin-system';

import module1 from './plugins/module1.js';
import module2 from './plugins/module2.js';

function main() {
	TOPS({
		module1,
		module2,
	});
};

main()

Each plugin typically sits in its own file and exports a default function with this signature:

export default async ({ TOPIC1, TOPIC2, TOPIC3 }, config) => {

	TOPIC1.pipe(
		delay(1000),
		map(x => x+1),
		switchInvoke(TOPIC2),
		emit(TOPIC3),
	).reply()

};

Plugins can communicate with each-other via a common message bus through a number of topics. Each topic takes the form of an Observable Subject that's available to plugins via their default-exported function.

The example above listens to messages coming from TOPIC1, delays processing by 1s, adds one, emits the result to TOPIC2, all replies to which will be emitted to TOPIC3 and then returned to the original caller who emitted to TOPIC1.

Duplex Streams and their new operators

The Duplex Stream is a particular type of RxJS Subject that enables two-way communication, essential for the request-response communication pattern used by a message bus and that's not available in regular Observables.

Duplex streams bring two new instance methods: invoke and reply:

Duplex::invoke

This emits data into a duplex stream and returns an observable of the responses. This is a lower-level functionality, mostly used internally by the plugin system. You would most likely use the invoke operator instead.

const stream = new Duplex();

stream.invoke(value);

Duplex::reply

This makes it possible for a Duplex stream to return a value to the original emitter by simply taking values coming from the pipeline and re-emitting them into the caller stream.

const stream = new Duplex().pipe(
    ...operators,
    map(data => asReturnValue(data)),
).reply();

Duplex operators

These are special operators for Duplex streams to help implement various calling patterns

switchInvoke

Similar to RxJS switchMap. It emits the current value from the source stream and returns a new stream of the responses until a new value is received from the source

mergeInvoke

Similar to RxJS mergeMap. It emits the current value from the source stream into the specified topic and re-emits all returned values as they arrive

emit

A fire-and-forget operator that simply emits the current value into the specified stream and moves on

chain

WIP

parallel

WIP

Unit testing plugins

WIP

Examples

A Stream-Oriented Webapp where everything is a module, everything is a stream