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

@synthesis-labs/operator

v1.0.4

Published

Operator is a simple, type-safe state management library, inspired by the observable pattern.

Downloads

6

Readme

Operator

Operator is a simple, type-safe state management library, inspired by the observable pattern.

The name comes from the movie Matrix where the operators are crew members on the hovercraft who send information and resources to those connected to the Matrix. Similarly this library sends informations about the state changes to the different software component.

Installation

The package is available on NPM, you can install it either with npm or yarn:

npm install @synthesis-labs/operator
yarn add @synthesis-labs/operator

Usage

Creating the state

Create an interface describing your state:

interface Person {
  name: string;
  age: number;
  boss: boolean;
}

Instantiate the store by providing the default values:

const person = Store.make<Person>({
  name: "John",
  age: 25,
  boss: false,
});

Finally export this person object and import where you need to access or manipulate the state.

Retrieving field

The library provides type safe, auto generated getters on the object, based on the provided interface. You can access any field directly like this:

console.log(`${person.name} is ${person.age} years old`);

Setting values

You can change the value of one or multiple fields by using the set(data: Partial<T>) method on the object. For example here we change the field age and boss, but not the name:

person.set({ age: 30, boss: true });

Subscribing for changes

Changes can happen anytime, especially if the store is used by multiple function, modules, components, etc. If you don't want to miss any change, you can subscribe to the changes:

const listenerIds = person.addListeners({
  age: (value: number) => console.log(`New age is ${value}.`),
  name: (value: string) => console.log(`New name is ${value}.`),
});

The addListener method returns an object containing a subscription ID for every field we subscribed for.

Unsubscribing from changes

If you don't want to keep listening for the changes, you can unsubsribe from them. For this simply pass an object containing the fields and subscription IDs. For example here we unsubscribe from everything we subscriber for earlier:

person.removeListeners(listenerIds);

Using with React

Changing the values in the store is pretty easy:

import person from ".sometPath/store/person";

export default function IncrementAge() {
  return (
    <button onClick={() => person.set({ age: person.age + 1 })}>
      Increment
    </button>
  );
}

To use the fields of the store in your React component and keep everything reactive, we recommend to sync your global state to your local state:

import { useState, useEffect } from "react";
import person from ".sometPath/store/person";

export default function Person() {
  const [age, setAge] = useState(0);
  const [name, setName] = useState("");

  useEffect(() => {
    let listenerIds = person.addListeners({
      age: setAge,
      name: setName,
    });

    return () => {
      person.removeListeners(listenerIds);
    };
  }, []);

  return (
    <div>
      {name} - {age}
    </div>
  );
}

Don't worry too much about the initial values of the local state, since they get synced up to the global state at the subscription, even if there are no new changes.

We can achieve the same thing by using class components as well:

import React from "react";
import person from ".sometPath/store/person";
import { CallbackIdMap } from "@synth-labs/operator";

interface PersonState {
  name: string;
  age: number;
}

class Person extends React.Component<{}, PersonState> {
  listenerIds!: CallbackIdMap<PersonState>;

  constructor(props: {}) {
    super(props);

    this.state = {
      name: "",
      age: 0,
    };
  }

  render(): React.ReactNode {
    return (
      <div>
        {this.state.name} - {this.state.age}
      </div>
    );
  }

  componentDidMount() {
    this.listenerIds = person.addListeners({
      name: (value: string) => this.setState({ name: value }),
      age: (value: number) => this.setState({ age: value }),
    });
  }

  componentWillUnmount() {
    person.removeListeners(this.listenerIds);
  }
}

export default Person;

Plans

  • custom hook for easier use with functional components
  • custom decorator for easier use with functional components
  • support for custom set function (e.g increment)
  • better support for complex state
    • selector functions
    • subscribe to fields of fields