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

zen-signals

v1.2.0

Published

☯ The simplest signal library possible

Downloads

4

Readme

zen-signals is a signal library focused on readability. You should be able to open the code and understand it. Therefore, its main value is educational. Yes, you can use it in your project, and maybe even in production, but it will fall short for more complex use cases. If you're learning Rx (or any other production ready signal library), you may find understanding and reading zen-signal's code helpful.

The "necessary" verbiage part

To understand zen-signals, you need to understand 3 things: signals, processes and side effects. As names suggest, a signal is a place where data comes from; a process is something that changes data - and only data; and a side effect is something that changes other things than data.

You'll discover that each signal library out there use sligthly different terms for these 3 components and this is a major source of confusion when learning them. The important thing here is to understand these 3 roles, after all it is not that hard, and then you can also call them however you like. If you like straightforward language, which appears not to be fashionable nowadays, you may wanna call these "the shit that happens", "the shit that gives me what I care about" and "the shit that changes shit". Suit yourself.

There are many cool things about using a signal library. Depending on who you ask people will give you a different perspective on why it is cool. This is another source of confusion. But the main things you'll hear about are composability, testability and isolation of side effects. People may talk about these things using other terms like expressiveness, purity, reasoning, etc... These are just jargon that eventually boils down to the relevant stuff.

Composability gives you a lot of power in a very expressive way. Being expressive makes reasoning easier, because you can state complex things in simpler terms. You'll see that, most of the time, the things you'll be composing are the processes.

Now, everyone is saying – in public – that these pesky called side effects should be avoided at all costs – while in private they may be doing lavish side effect banquets. But they actually have a point: side effects are where things generally go wrong. And we don't want things to go wrong, don't we? That's because side effects change things out of our control, so they may have unpredictable results. Therefore, clearly separating our processes from our side effects makes testing the processes a breeze, leaving the side effects very clearly defined, so we can build a strong fortification around them – to make them less unpredictable – and see clearly what to blame when shit hits the fan.

A classic example

To understand all that verbiage, let's consider a classic example: search. When searching we generally want to avoid doing unecessary trips to our data store. If we're talking about a web app, even worst! Blame those lazy physicists who still couldn't figure out how to build these quantum computers they love to talk about and make internet requests break the speed of light!

Therefore, let's add two commandments to our search:

  1. Thou shall not search before thy neighbour enters at least 3 characters. Not 4, not 5, not 2: 3 shall be thy minimal number.
  2. Thou shall not search if thy neighbour is typing too fast. Hear, Israel, one second shall be the waiting time, the waiting time is one.

Now that we have our laws, given consider the following implementations. First the imperative:

Now the one using zen-signal:

You're probably thinking "But wait, this is a strawman! I could have also used functions in the procedural version!". Thing is that the boundaries of these functions would not be so clearly defined, plus in the zen-signals version all the process that happens – defining clearly our laws – is perfectly composable. This means that, for instance, you could group them and then reuse them.

// search.js
const search = ({min, wait}) => pipe(
  map((event) => event.target.value),
  reject((value) => value.length < min),
  throttle(wait)
)

export default search

And then...

// advancedSearch.js
const advancedSearch = pipe(
  search({min: 3, wait: 1000}),
  // more laws here!
)

export default advancedSearch
hello world
import {signal, id} from 'zen-signals'

id(signal(10), console.log) // will immediatelly log 10

sources

signal, fromEvent, fromAnimationFrame

processes

always, bind, distinct, filter, fold, hub, id, liftN, map, merge, reject, snapshot, stepper, stop, takeBetween, takeUntil, throttle, transduce

always
import {signal, map} from 'zen-signals'

map((x) => x + 1, signal(10), console.log) // will immediatelly log 11

map
import {signal, map} from 'zen-signals'

map((x) => x + 1, signal(10), console.log) // will immediatelly log 11
filter
import {signal, filter} from 'zen-signals'

filter((x) => x > 20, signal(10), console.log)