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

ustor

v0.1.0

Published

A lightweight reactive store library that provides a powerful reactivity system for managing state, compatible with any UI framework, including Solid.js, and Preact Signals.

Downloads

211

Readme

UStor

tests Version Badge size Badge size

Reactive Store Library

This library provides a powerful reactivity system for creating stateful objects using signals, integrated seamlessly into JavaScript objects and arrays. This library does not depend on any specific reactive library and can be used by any UI framework to manage and react to changes in state effectively.

Table of Contents

Installation

To use this library, you can install it using npm or yarn:

npm install ustor
yarn add ustor

This library can be integrated with solid-js, @preact/signals-core, ulive, usignal, oby, sinuous any other libarary you can think of for managing reactive signals.

Setup

First, import the store function and the api object. You need to initialize api with your preferred signal implementation.

import { store, api } from "./src";
import { createSignal } from "solid-js";
// import { signal } from '@preact/signals-core'; // 'usignal' 'ulive'

// Solid.js setup
api.signal = createSignal;
api.get = (v) => v[0]();
api.set = (signal, v) => signal[1](v);
api.is = (v) =>
	(Array.isArray(v) &&
		typeof v[0] === "function" &&
		typeof v[1] === "function") ||
	v[0]?.name?.includes("readSignal");

// @preact/signals-core, usignal or ulive setup
api.signal = signal;
api.get = (v) => v.value;
api.set = (signal, v) => (signal.value = v);
api.is = (v) => v?.peek;

API

store(values, proto)

The store function creates a stateful object that automatically converts properties into reactive signals.

  • values: The initial values for the store, which can be objects, arrays, or primitives.
  • proto: Optional prototype to set for the new store object.

The function returns a reactive store object that maintains the structure of the original values while adding reactivity.

is(value)

The is function checks if a given value is a reactive store instance.

  • value: The value to check.

Returns true if the value is a reactive store, otherwise false.

api.is

The api.is function checks if a given value is a signal.

  • value: The value to check.

Returns true if the value is a signal, otherwise false.

api.signal

The api.signal function is used to create a reactive signal.

  • value: The initial value for the signal.

Returns a signal that can be used to create reactive state within the store.

api.get

The api.get function retrieves the current value of a signal.

  • signal: The signal whose value you want to retrieve.

Returns the current value of the signal.

api.set

The api.set function updates the value of a signal.

  • signal: The signal whose value you want to update.
  • value: The new value to set.

Updates the signal with the provided value.

Usage

Basic Usage

const s = store({ a: 1, b: 2 });
console.log(s.a); // 1
s.a = 5;
console.log(s.a); // 5

You can use the store function to create a reactive state object. Assigning a new value to s.a will automatically trigger updates wherever s.a is used.

Advanced Usage

const s = store({
	a: 2,
	b: 3,
	get sum() {
		return this.a + this.b;
	},
});

console.log(s.sum); // 5
s.a = 5;
console.log(s.sum); // 8

Here, you can define getters that automatically compute derived state values, and these getters will update whenever the underlying signals change.

Deeply Nested Structures

The store function can also handle deeply nested objects, converting nested properties into reactive signals:

const s = store({ nested: { deep: { value: 10 } } });
const deepValue = s.nested.deep.value * 2;

console.log(deepValue); // 20
s.nested.deep.value = 15;
console.log(s.nested.deep.value) * 2; // 30

Arrays and Objects

This library can handle arrays and objects seamlessly, automatically wrapping array elements with reactivity:

const s = store({ list: [1, 2, 3] });
const sum = s.list.reduce((acc, item) => acc + item, 0);

console.log(sum); // 6
s.list = [1, 5, 3];
console.log(s.list.reduce((acc, item) => acc + item, 0)); // 9

Reactivity and Effects

The signal value trigger with effects to track dependencies and automatically re-run whenever dependencies change:

const s = store({ a: 1 });
let effectValue = 0;

effect(() => {
	effectValue = s.a * 2;
});

console.log(effectValue); // 2
s.a = 4;
console.log(effectValue); // 8

state.$prop

The $ properties are automatically generated for each property in the store. These $-prefixed properties contain the underlying signal, providing direct access to the signal itself, separate from the reactive value it holds. The $ properties are non-enumerable and are useful when you need to access or manipulate the signal directly, rather than the reactive value.

For example, if you have a store with a count property:

const s = store({ count: 0 });
console.log(s.count); // 0
console.log(s.$count); // The underlying signal object

Integration with Solid.js, Preact Signals or any

This library can be used with Solid.js, Preact Signals, or any other UI framework to provide reactive signals.

To use Solid.js:

import { createSignal } from "solid-js";

api.signal = createSignal;
api.get = (v) => v?.[0]();
api.set = (signal, v) => signal?.[1](v);
api.is = (v) =>
	(Array.isArray(v) &&
		typeof v[0] === "function" &&
		typeof v[1] === "function") ||
	v?.[0]?.name?.includes("readSignal");

To use Preact Signals, usignal, ulive, etc:

import { signal } from "@preact/signals-core";

api.signal = signal;
api.get = (v) => v?.value;
api.set = (signal, v) => (signal.value = v);
api.is = (v) => v?.peek;

To use any signal library

import ... from "...";

api.signal = ...;
api.get = ...;
api.set = (signal, value) => ...;
api.is = (v) => ...;

const state = store({
	count: 0
});

The library provides a unified API to work with different reactive systems, allowing you to switch between Solid.js, Preact Signals, or any other UI framework easily.

License

This library is provided "as-is" under the MIT license. Feel free to use, modify, and distribute it in your projects.

Thanks and Inspiration