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

repostream

v1.3.4

Published

[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)

Downloads

20

Readme

RepoStream

License

Concept

RepoStream serves as an intermediary layer between the UI and Business logic of your application. It leverages the StateStream to deliver the application state to the UI, while incorporating business logic through the use of middlewares and joinStates within the RepoStream.

RepoStream

RepoStream acts as the central manager of the application states. Clients connect to one or multiple states within the repo by utilizing the createStream method, which returns a StateStream object connected to the desired states. Communication between the repo and streams occurs via event messages. Clients can employ three different messages (push, pop, and request) to instruct the repo to modify the application state.

State and State Path

RepoStream maintains all application states within its states object. Here's an example of the states object structure:

states = {
  stores: {
    city: {
      hcmc: [
        'Dev Store', 'Play Store'
      ]
    }
  },
  stocks: {
    games: [
      {
        title: 'Awesome adventure of a poor dev',
        quantity: 100
      }
    ]
  }
}

In the above example, two application states are present: stores and stocks. Each state acts as the root of its respective state tree. For instance, stores and stocks serve as the root for their corresponding state trees. A state path represents the path to reach a specific point within the state tree. For example, stocks.games and stores.city.hcmc are state paths within the provided example.

State path support wildcast * character, for example 'users.*.profile' will match users.bob.profile and users.anna.profile.

The StateStream object can request changes to the state root or a specific state path. You need to define the middleware function to handle the request for a specific state path

Middleware

const middleware = {
  push: (changePath, changeValue, currentValue, state, setState, setError) => {
    currentValue.push(changeValue);
    return currentValue;
  }
}

const repo = new Repo();
repo.addMiddleware('stores.city.*', middleware);

stream = repo.createStream(['stocks', 'stores']);

stream.push('stores.city.hcmc', 'Game Store');

The middleware function handles state path requests and can return a new state value for the specified changePath. Alternatively, it can return a promise that resolves to a new value.

If the middleware function returns undefined, the state will not be updated unless setState is called within the middleware body.

To manipulate the state object, you can use the setState callback. In certain cases, such as deleting a state branch, the callback is useful. It accepts a new state tree or a function to avoid potential issues with stale state.

Here's an example of defining a middleware function:

const middleware = {
  remove: (changePath, changeValue, currentValue, state, setState, setError) => {
    delete state.stocks.games;
    setState(state);
  },
}

joinState

The joinState method in the RepoStream API allows you to create a virtual state by joining multiple states together. Whenever any of the states in the joining array changes, the joined state will be automatically updated using the provided joinFunction.

Usage

repo.joinState(name, states, joinFunction);
  • name (string): The name of the joining state.
  • states (array): An array of states to join together.
  • joinFunction (function): A function that accepts the repo's state object, performs logic to join the states, and returns the joined state.

The joinFunction takes the repo's state object as an argument and should return the joined state object.

Example

Here's an example of using joinState to create a virtual state called itemsInStore by joining the stocks and stores states:

repo.joinState('itemsInStore', ['stocks', 'stores'], state => {
  const itemsInStore = {};
  for (let store of state.stores) {
    const items = [];
    for (let item in state.stocks) {
      items.push({
        name: item,
        quantity: state.stocks[item].filter(item => item.store === store).length
      });
    }
    itemsInStore[store] = items;
  }
  return itemsInStore;
});

In the above example, the joinFunction iterates over each store in the stores state and collects the items from the stocks state that belong to that store. It creates an object itemsInStore where each store is a key and its corresponding value is an array of items with their quantities. Whenever either the stocks or stores state changes, the itemsInStore state will be updated accordingly.

The joined state itemsInStore can then be accessed and used in the application to display the relevant information.

Installation

To use RepoStream in your project, follow these steps:

  1. Install the package via npm:
npm install repostream --save
  1. Import RepoStream into your project:
import RepoStream from 'repostream';

Usage

Here's an example of how to use RepoStream:

import RepoStream from 'repostream';

const schemas = {
  profile: {
    username: 'username',
    picture: 'default_url'
  },
  enrolls: [],
  score: {
    math: 0,
    physics: 0,
  }
};

const repo = new RepoStream({ schemas });

repo.addMiddleware('user.enrolls', {
  push: (changePath, changeValue, currentValue, state, setState, setError) => {
    state.user.enrolls = [...state.user.enrolls, changeData];
    setState(state);
  }
});

// Create a stream that connects to the 'user' state in the repo
const stream = repo.createStream(['user']);

// Set up listeners for state changes and errors
stream.onStateChange(state => console.log(state));
stream.onError(err => console.error(err));

// Push a new state change to the stream
const requestPush = stream.request('push');
requestPush('user.enrolls', 'javascript');

console.log(stream.state);

// Remove the stream itself
stream.remove();

Developer Document

RepoStream API

Methods

  • constructor({ schemas }): Initializes a new instance of RepoStream with the specified schemas.
  • createStream(states): Creates a stream that connects to the specified states in the repo.
  • addMiddleware(statePath, middleware): Adds middleware for the given state path.
  • invokeMiddleware({ statePath, action, changeValue }): Invode the middleware.
  • joinState(name, states, joinFunction): Joins multiple states using a custom join function.

Properties

  • schemas: The schemas defined for RepoStream.
  • repo: The underlying Repo instance.
  • streams: The active streams created from the repo.

StateStream API

Methods

  • constructor({ id, eventEmitter, state }): Initializes a new instance of StateStream with the provided parameters.
  • request(requestType): Returns a requester function that can be used to request a state change.
  • onStateChange(callback): Sets up a listener for state change events.
  • onError(callback): Sets up a listener for error events.
  • remove(): Removes the StateStream.

Properties

  • state: The current state associated with the StateStream.

EventEmitter API

Methods

  • addListener(eventName, handler): Adds a listener for the specified event.
  • removeListener(eventName, handler): Removes a previously added event listener.
  • emit(eventName, ...args): Emits an event with optional arguments.

TODO

  • Create repostream-middlewares package that includes common middleware functions, such as pushing to an array.
  • Enable the usage of repo.addMiddleware('state.path', { push: mw.pushToArray }).

Contributing

Contributions are welcome! If you have any ideas, suggestions, or bug reports, please open an issue or submit a pull request.

License

This project is licensed under the MIT License.