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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@zambezi/caballo-vivo

v1.3.0

Published

Caballo Vivo

Downloads

5

Readme

= Caballo Vivo

[quote, CJC] 1177. los cementerios no deben estrenarse enterrando un hombre muerto sino un caballo vivo

Thin, opinionated layer for pure RxJS applications to connect with React-Router (or any router using history). It has the advantage of scaling well, allowing more concise and expressive code and a better separation between business logic and view layer.

Here's the equivalent implementation of the Redux Reddit advanced tutorial with caballo-vivo, in less than 100 lines of code (https://codesandbox.io/s/caballo-vivo-reddit-w88kg[online sandbox]):

[source,javascript]

// type localStorage.setItem('cv-log', true) in the console to see the logs! import React from "react" import { render } from "react-dom" import { OrderedMap, Map } from "immutable" import { partialRight } from "ramda" import { Subject, merge, concat, of, from } from "rxjs" import { map, catchError, switchMap } from "rxjs/operators" import { Router, Switch, Route, Link } from "react-router-dom" import { createLocation$, createNavigateTo$, createStore$, history, flog, stow } from "@zambezi/caballo-vivo" import ClipLoader from "react-spinners/ClipLoader" import "./index.css"

const getPosts$ = new Subject()

const pathToIntent = OrderedMap([ ["/:subreddit", ({ subreddit }) => getPosts$.next({ subreddit })], ["/", () => getPosts$.next({ subreddit: "all" })] ])

const location$ = createLocation$(pathToIntent).pipe( // <1> map(location => state => state.set("location", location)) )

const redditJourney$ = getPosts$.pipe( // <2> switchMap(({ subreddit }) => concat( of(state => state.set("loading", true)), // <3> from(fetch(https://www.reddit.com/r/${subreddit}.json)).pipe( switchMap(res => from(res.json()).pipe( map(json => json.data.children.map(child => child.data)) ) ), stow("subreddit") // <4> ), createNavigateTo$(subreddit), // <5> of(state => state.set("loading", false)) ) ), catchError(() => of(state => state.set("error", "This subreddit is not available")) ) )

merge(location$, redditJourney$) .pipe(createStore$(Map()), flog("Render state"), map(toView)) // <6> .subscribe(partialRight(render, [document.getElementById("root")]))

function toView(state) { // <7> if (state.has("error")) return {state.get("error")} if (state.get("loading")) return ( ) return ( {["all", "reactjs", "rxjs", "javascript", "node"].map(l => ( {r/${l}} ))} {state.get("subreddit").map(post => ( {post.title} ))} ) }

<1> Passing a map to createLocation$ will block the hisory when the route changes and the new url matches one of the keys. <2> We listen to the getPosts$ intent, triggered by the routes above, to kickstart a complex series of asynchronous events (set/unset loader flag, download subreddit). <3> When we emit reducer functions, they get executed by the store (see below). All that a reducer function does is get the current state snapshot and return a new snapshot. <4> https://github.com/zambezi/caballo-vivo/blob/master/src/stow.js[stow] is just an operator which emits a reducer function to set the value received on a key or path in the store. This pattern is so common that it got its own operator. <5> createNavigateTo$ unblocks the history and changes the address in the URL bar. At this point, all the routes matching the new address can render. <6> createStore$ creates a store, which is an rxjs operator that has an initial value, takes reducers function in and spits state snapshots out. <7> The view function is just a function which takes state snapshots in and generates JSX. Views and state / business logic are decoupled and interchangeable.

For a more advanced example application, please check: https://github.com/gabrielmontagne/fa-doodle