One kilobyte reactive state management library for JavaScript and TypeScript.
It's heavily inspired by RxJS, but it's much more lightweight.
npm install cuprumimport{Cuprum}from"cuprum";constcount$=newCuprum<number>();count$.subscribe((value)=>{console.log(value);// 1, 2, 3, ...});count$.dispatch(1);count$.dispatch(2);count$.dispatch(3);The core class. Represents an observable stream that can also dispatch values.
constobs$=newCuprum<T>();Emits a value to all current subscribers. Returns this for chaining.
obs$.dispatch("hello");Subscribes to future values. If a value has already been dispatched, fn is called immediately with the current value. The callback receives both the new value and the previous value.
obs$.subscribe((value,oldValue)=>{console.log(value,oldValue);});Removes a previously subscribed function.
functionhandler(value: string){ ... }obs$.subscribe(handler);obs$.unsubscribe(handler);Returns the last dispatched value without subscribing.
constcurrent=obs$.value();Returns a new observable whose values are transformed by fn.
constdoubled$=number$.map((n)=>n*2);Returns a new observable that only emits values for which fn returns true.
constpositive$=number$.filter((n)=>n>0);Returns a Promise that resolves with the next dispatched value.
constvalue=awaitobs$.promise();Returns a read-only view of this observable. The returned object has no dispatch method — calling it throws an error. Useful for exposing a stream publicly without allowing external dispatches.
constreadOnly$=obs$.observable();Removes all subscribers.
obs$.clear();Creates a Cuprum that emits DOM events from the given element. Supports Window, Document, and HTMLElement with full TypeScript event map inference. The event listener is added only while there is at least one subscriber.
import{fromEvent}from"cuprum";constclick$=fromEvent(document.getElementById("btn"),"click");click$.subscribe((event)=>console.log(event));Like fromEvent but for custom or non-standard event names, without type inference.
import{fromCustomEvent}from"cuprum";constopen$=fromCustomEvent(element,"open");open$.subscribe(()=>console.log("opened"));Combines up to 7 observables into a single observable that emits a tuple of the latest values from each source. Emits whenever any source emits. Sources that have not yet emitted contribute undefined to the tuple.
import{combine}from"cuprum";constcombined$=combine(name$,age$);combined$.subscribe(([name,age])=>{console.log(name,age);});Merges multiple observables into one. Emits each value as-is from whichever source emits.
import{merge}from"cuprum";constall$=merge(stream1$,stream2$,stream3$);all$.subscribe((value)=>console.log(value));Creates an observable that emits an incrementing integer starting from 0 at the given interval in milliseconds. The timer only runs while there is at least one subscriber.
import{interval}from"cuprum";consttimer$=interval(1000);constsub=timer$.subscribe((i)=>console.log(i));// 0, 1, 2, ...// Stop the timersub.unsubscribe();A read-only view of Cuprum<T> — all methods except dispatch are available. Returned by .observable(), combine(), and merge().
typeObservable<T>=Omit<Cuprum<T>,"dispatch">;Returned by .subscribe() and .subscribeHot(). Call .unsubscribe() to stop receiving values.
interfaceSubscription{unsubscribe(): void;}constpipe$=newCuprum<string>();pipe$.subscribe((value)=>console.log(value));pipe$.dispatch("hello");// logs: helloconstsource$=newCuprum<string>();constupper$=source$.map((s)=>s.toUpperCase());upper$.subscribe((v)=>console.log(v));source$.dispatch("hello");// logs: HELLOconstnumbers$=newCuprum<number>();numbers$.filter((n)=>n%2===0).subscribe((n)=>console.log(n));numbers$.dispatch(1);// ignorednumbers$.dispatch(2);// logs: 2numbers$.dispatch(3);// ignorednumbers$.dispatch(4);// logs: 4constvalue$=newCuprum<string>();value$.subscribe((value,oldValue)=>{console.log(`${oldValue} → ${value}`);});value$.dispatch("a");// undefined → avalue$.dispatch("b");// a → bconstobs$=newCuprum<string>();setTimeout(()=>obs$.dispatch("done"),1000);constresult=awaitobs$.promise();console.log(result);// "done"consta$=newCuprum<string>();constb$=newCuprum<number>();combine(a$,b$).subscribe(([a,b])=>console.log(a,b));a$.dispatch("x");// "x", undefinedb$.dispatch(1);// "x", 1a$.dispatch("y");// "y", 1consta$=newCuprum<string>();constb$=newCuprum<string>();merge(a$,b$).subscribe((v)=>console.log(v));a$.dispatch("from a");// "from a"b$.dispatch("from b");// "from b"consttick$=interval(500);constsub=tick$.subscribe((i)=>console.log(i));// 0, 1, 2, ...setTimeout(()=>sub.unsubscribe(),3000);// stop after 3 secondsCopyright 2023 Edwin Martin and released under the MIT license.