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

easy-signal

v4.1.1

Published

A package with 2 types of signals, an small and simple event signal, and a reactive value-based signal called stores.

Downloads

498

Readme

Easy Signal

Two interfaces for creating two types of signals. The first (and original signal in this module) is a function that defines an event and can be triggered and listened to with the single function. The second is a reactive data store that allows to react to changes (popularized by solid-js). These two are Signal and Readable/Writable.

Full type safety with TypeScript with both use-cases.

Installation

npm install easy-signal

Signal Usage

A Signal is a function that represents a single event. The function can be used to subscribe to be notified of the events as well as to trigger them.

Signals offer similar functionality as the browser's eventDispatcher API, but rather than a general API for any event, each event would use its own signal. This allows each signal to have a specific function signature as opposed to the browser's generic event object. This is a great system in TypeScript being able to see the exact data each event produces.

Signal Basic Usage

// file seconds.ts
import { signal } from 'easy-signal';

// Create the signal and export it for use. Optionally provide the subscriber signature
export const onSecond = signal<number>();

// Passing a non-function value will dispatch the event
setInterval(() => {
  const currentSecond = Math.floor(Date.now() / 1000);
  onSecond(currentSecond);
});
import { onSecond } from './seconds.ts';

// Typescript knows that seconds is a number because of the concrete type definition in seconds.ts
const unsubscribe = onSecond(seconds => {
  console.log(seconds, 'since epoc');
});

Errors may also be listened to from the signal by passing ForErrors as the second parameter when adding the listener and errors may be dispatched by passing an Error object to the signal method.

import { signal, ForErrors } from 'easy-signal';

const dataStream = signal();

dataStream(data => console.log('data is:' data));
dataStream(error => console.log('Error is:' error), ForErrors);

stream.on('data', obj => dataStream(obj));
stream.on('error', err => dataStream(err));

To get a subscriber-only method for external use, pass in the GetOnSignal constant.

import { signal, GetOnSignal } from 'easy-signal';

function getMyAPI() {
  const doSomething = signal();

  // doSomething() will trigger subscribers that were added in onSomething(...). This protects the signal from being
  // triggered/dispatched outside of `getMyAPI`. Sometimes you may want more control to prevent just anyone from
  // triggering the event.

  return {
    onSomething: doSomething(GetOnSignal),
  };
}

To clear the listeners from the signal, pass in the ClearSignal constant.

import { signal, ClearSignal } from 'easy-signal';

const onSomething = signal();

onSomething(ClearSignal); // clears signal

Store Usage

A store is an object that represents a single piece of data. The store's methods can be used to get, set, and update the data and subscribe to changes on the data. An observe function allows for a given function to be rerun whenever any stores it depends on are changed. And a derived function allows a readonly store to be created which depends on, or is derived from, other stores. Both observe and derived automatically track dependencies within the scope of their function.

Store Basic Usage

Here we will use an example similar to the Signal, but unlike the Signal, the current seconds since epoch will be stored and can be accessed any time, whereas the Signal only fires an event with the data provided. This particular example isn't very compelling.

// file seconds.ts
import { writable } from 'easy-signal';

// Create the signal and export it for use. Optionally provide the subscriber signature
export const onSecond = writable(0);

// Passing a non-function value will dispatch the event
setInterval(() => {
  const currentSecond = Math.floor(Date.now() / 1000);
  onSecond.set(currentSecond);
});
import { onSecond } from './seconds.ts';

// Get the value of onSecond.get() at any time
console.log(onSecond.get(), 'since epoc');

// Typescript knows that seconds is a number because of the concrete type definition in seconds.ts
const unsubscribe = onSecond.subscribe(seconds => {
  console.log(seconds, 'since epoc');
});

observe Basic Usage

To take action whenever data changes, you can observe one or more signals by accessing them in a function call. Below, we update the content of the DOM whenever the user or billing data is updated, but we only do it after an animation frame to prevent the DOM updates from being too frequent.

Because user.get() and billing.get() are called the first time the observe function is run, it automatically subscribes to know when they are changed so that the function may be rerun.

Note that easy-signal provides 3 simple debounce functions to make it easy to have effects happen less often while still allowing the stores to always be accurate:

  • onAnimationFrame
  • onTick
  • onTimeout
import { writable, observe, onAnimationFrame } from 'easy-signal';

const user = writable(userData);
const billing = writable(billingData);

const updateDom = onAnimationFrame((name, plan) => {
  // will be called with only the most recent values if updateDom was called multiple times between frames
  document.body.innerText = `${name} has the plan ${plan}`;
});

const unobserve = observe(() => {
  updateDom(user.get().name, billing.get().plan);
});

derived Basic Usage

Create read-only signals whose value is derived from other signals and which will be updated whenever they are.

import { derived } from 'easy-signal';
import { user, billing } from 'my-other-signals';

const delinquent = derived(() => {
  if (user.get().subscribed) {
    return billing.get().status === 'delinquent';
  }
  return false;
});

delinquent.subscribe(delinquent => {
  console.log(`The user is${delinquent ? '' : ' not'} delinquent`);
});

batch(fn: () => void) allows updating multiple stores and only triggering those updates once at the end.