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

core-flux

v2.0.0

Published

½kb functional flux utility. Control the flow of state data between subscribers.

Downloads

29

Readme

See a demo of Core Flux in action!

Install

NPM / Yarn

$ npm i core-flux
$ yarn i core-flux

CDN

The CDN puts the library on window.CoreFlux.

<!-- The unminified bundle for development -->
<script
  type="text/javascript"
  src="https://cdn.jsdelivr.net/npm/[email protected]/dist/core-flux.js"
  integrity="sha256-yRWVHNaxTvbEj7ZEytgW2nmJAAf18mYs+5s3eeqLojc="
  crossorigin="anonymous"
></script>

<!-- Minified/uglified bundle for production -->
<script
  type="text/javascript"
  src="https://cdn.jsdelivr.net/npm/[email protected]/dist/core-flux.min.js"
  integrity="sha256-FXNzEKAxvH7fIAl913+qHOpG233431Ug3RBpghM3b+U="
  crossorigin="anonymous"
></script>

API

The one and only export of Core Flux. Use it to create a store instance. You can create as few or as many stores as your heart desires! They will all be independent from one another.

NOTE: The base state type must be a plain object. Invalid types will throw an error.

The function requires all four of its arguments, including bindings:

// foo-store.js

import { createStore } from "core-flux"
import { reducer, bindSubscriber, bindState } from "./foo-bindings"

const initialState = {
  foo: [],
  bar: { baz: 0, beep: "hello" },
}

const { subscribe, dispatch } = createStore(
  initialState,
  reducer,
  bindSubscriber,
  bindState
)

export { subscribe, dispatch }

Once a store is created, you'll be able to add subscriptions with subscribe and request state updates with dispatch.

Adds a subscription to your store. It will always be tied to a single store, and subsequently state object.

import { subscribe } from "./foo-store"

class FooItems {
  constructor() {
    subscribe(this, ["foo"])
  }

  get items() {
    return this.foo
  }
}

In the above example, we've designed the subscriber, the FooItems class, to declare an array of strings correlating to properties in the store's state. If you're from the Redux world, this is akin to "connecting" a consumer to a provider via higher-order function/component.

After the subscribe call is made, your bindSubscriber function will be called where you can pass along the default values as you see fit.

NOTE: In general, you should try to use a simple data structure as the second argument to subscribe; this ensures your bindings have generic and consistent expectations.

Requests a state change in your store.

We can extend the previous example with a setter to call dispatch:

import { subscribe, dispatch } from "./foo-store"

class FooItems {
  constructor() {
    subscribe(this, ["foo"])
  }

  get items() {
    return this.foo
  }

  addItem(item) {
    dispatch("ADD_ITEM", { item })
  }
}

const fooBar = new FooItems()
fooBar.addItem("bop")

Now when the addItem method is called, Core Flux will pass along the action type and payload to your reducer.

The reducer could have a logic branch on the action type called ADD_ITEM which adds the given item to state, then returns the resulting new state (containing the full items list).

Finally, the result would then be handed over to your bindState binding.

NOTE: Much like in subscribe, it's best to maintain data types in the payload so your reducer can have consistent expectations.

Bindings

Here's a breakdown of each binding needed when initializing a new store:

bindSubscriber(subscription, state)

subscription ([subscriber, data]): A tuple containing the subscribed object and its state-relational data.state (object): The current state object.

Called after a new subscribe is made and a subscription has been added to the store. Use it to set initial state on the new subscriber. Use the data provided to infer a new operation, e.g., setting a stateful property to the subscriber.

reducer(state, action)

state (object): Snapshot of the current state object.action ({ type: string, payload: object }): The dispatched action type and its payload.

Called during a new dispatch. Create a new version of state and return it.

bindState(subscriptions, reducedState, setState)

subscriptions (subscription[]): An array containing all subscriptions.reducedState (object): The state object as returned by the reducer.setState (function):

Called at the end of a dispatch call, after your reducer callback has processed the next state value. Set your new state back to subscribers and back to the store. It's possible and expected for you to call bindSubscriber again to DRYly apply these updates. You can return from this function safely to noop.

Exposing the store

For utility or debugging reasons, you may want to look at the store you're working with. To do so, you can use the __data property when creating a store:

const fooStore = createStore(initialState, reducer, bindSubscriber, bindState)

window.fooStoreData = fooStore.__data

console.log(window.fooStoreData) // { state: {...}, subscriptions: [...] }

NOTE: Avoid including __data in production environments; the data is mutable and therefore exposes a security risk if accessible.

Data model

Core Flux has a relatively simple data model that you should understand when creating bindings.

Here is how state looks in all cases:

Store {
  state: { ... },
  subscriptions: [
    [subscriber, data],
    [subscriber, data],
    [subscriber, data],
    // ...
  ]
}

Each item in subscriptions contains a subscriber and some form of data that informs a relationship between state and subscriber.

NOTE: _You define data in the above model. This ensures that ultimately you control communicating state relationships to subscribers._

Data flow

Here is the general lifecycle of subscribing to the store & dispatching a state update.

  • subscribe > bindSubscriber
  • dispatch > reducer > bindState