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

spark-state

v1.2.0

Published

Helper library that introduces the solution to manage a group effect's global state by creating globally synchronized data signals

Downloads

21

Readme

Meta Spark Studio

Meta Spark Studio

Spark State

The Spark State library introduces a solution to manage a group effect's global state by creating globally synchronized data signals and making them available within an effect's JavaScript.

Contents

Getting started

Meta Spark project setup

  1. Download or upgrade to Meta Spark Studio v134 or higher.
  2. Open your project in Meta Spark Studio.
  3. Open the AR Library from within the Assets panel and select the Script Packages tab.
  4. Import the spark-state package to the project.
  5. In the project's Properties, add the Scripting Writeable Signal Source capability.

Loading the module

  1. Add a new Javascript script to the project from the Assets panel, or open an existing one.

  2. At the top of the script, load the module using the following line of code:

    const State = require('spark-state');
  3. The current implementation also requires that you load the Multipeer and Participants modules in your script in order to enable the two associated capabilities:

    const Multipeer = require('Multipeer');
    const Participants = require('Participants');

Documentation

GlobalCounterSignal

GlobalCounterSignal is a wrapper object for the ScalarSignal class from the Meta Spark API's ReactiveModule. However, the scalar value contained by the signal is synchronized globally across all participants in a group effect.

Additionally, it's possible to subscribe to a GlobalCounterSignal like you would with an EventSource:

GlobalCounterSignal.monitor().subscribe((event) => {
  // Code here will run when the value of the signal changes
});

| Methods | Description | |---|---| | createGlobalCounterSignal(startValue: number, signalName: string) | Creates a new GlobalCounterSignal with a globally unique name as specified by signalName, and with the initial value set by startValue. | | increment(i: number) | Increases the value of the GlobalCounterSignal by the value of i. | | decrement(i: number) | Decreases the value of the GlobalCounterSignal by the value of i. |

GlobalCounterSignal extends the ScalarSignal class. As such, methods exposed by ScalarSignal can also be called on GlobalCounterSignal.

const State = require('spark-state');

(async function () {

    // Initializes a new global counter signal with the initial value: 1
    const globalCounter = await State.createCounterGlobalSignal(1, 'globalCounter');

    // Increments the counter signal value by 2
    globalCounter.increment(2);
})();

GlobalStringSignal

GlobalStringSignal is a wrapper object for the StringSignal class from the Meta Spark API's ReactiveModule. However, the string value contained by the signal is synchronised globally across all participants in a group effect.

Additionally, it's possible to subscribe to a GlobalStringSignal like you would with an EventSource:

GlobalStringSignal.monitor().subscribe((event) => {
  // Code here will run when the value of the signal changes
});

| Methods | Description | |---|---| | createGlobalStringSignal(startValue: string, signalName: string) | Creates a new GlobalStringSignal with a globally unique name as specified by signalName, and with the initial value set by startValue. | | set(val: string) | Sets the value of the GlobalStringSignal to val. |

GlobalStringSignal extends the StringSignal class. As such, methods exposed by StringSignal can also be called on GlobalStringSignal.

const State = require('spark-state');

(async function () {

    // Initializes a new global string signal with the initial value: 'Hello'
    const globalString = await State.createStringGlobalSignal('Hello', 'globalString');

    // Sets the value of the signal to 'Hello world'
    globalString.set('Hello world');
})();

GlobalScalarSignal

GlobalScalarSignal is a wrapper object for the ScalarSignal class from the Meta Spark API's ReactiveModule. However, the scalar value contained by the signal is synchronised globally across all participants in a group effect.

Additionally, it's possible to subscribe to a GlobalScalarSignal like you would with an EventSource:

GlobalScalarSignal.monitor().subscribe((event) => {
  // Code here will run when the value of the signal changes
});

| Methods | Description | |---|---| | createGlobalScalarSignal(startValue: number, signalName: string) | Creates a new GlobalScalarSignal with a globally unique name as specified by signalName, and with the initial value set by startValue. | | set(val: number) | Sets the value of the GlobalScalarSignal to val. |

GlobalScalarSignal extends the ScalarSignal class. As such, methods exposed by ScalarSignal can also be called on GlobalScalarSignal.

const State = require('spark-state');

(async function () {

    // Initializes a new global scalar signal with the initial value: 0
    const globalScalar = await State.createScalarGlobalSignal(0, 'globalScalar');

    // Sets the value of the signal to 42
    globalScalar.set(42);
})();

GlobalPeersMap

GlobalPeersMap is a key-value pair data type which contains the IDs of all participants in a group effect as keys, and their global signals as values.

Values of types GlobalScalarSignal and GlobalStringSignal are supported.

The participantId parameters in the method calls refer to each effect participant's unique ID string as returned by the Participant.id property from the Meta Spark API.

| Methods | Description | |---|---| | createGlobalPeersMap(participantsStartValue: number \| string, signalName: string) | Creates a new GlobalPeersMap with a globally unique name as specified by signalName, and with the initial value set by participantsStartValue. | | get(participantId: string) | Returns the GlobalScalarSignal or GlobalStringSignal from the Participant specified by participantId. | | set(participantId: string, value: number \| string) | Sets the value of the GlobalScalarSignal or GlobalStringSignal to the value specified by value, for the Participant specified by participantId. | | keys() | Returns all of the keys from the GlobalPeersMap, as participantIds. | | setOnNewPeerCallback(callback: Function) | Sets a callback function to call whenever a new peer is added to the GlobalPeersMap. |

const State = require('spark-state');
const Participants = require('Participants');

(async function () {

    // Initializes a new global peer map
    const points = await State.createGlobalPeersMap(0, 'points');

    // Retrieve the ID for the self participant
    const myParticipantId = (await Participants.self).id;

    // Get the GlobalScalarSignal from the specified participant
    const pointCounter = points.get(myParticipantId);

})();

GlobalMap

GlobalMap is a key-value pair data type which allows synchronizing arbitrary key-value pairs in a group effect.

Values of types GlobalScalarSignal and GlobalStringSignal are supported.

| Methods | Description | |---|---| | createGlobalMap(name: string) | Creates a new GlobalMap with a globally unique name as specified by name. | | get(key: string) | Returns the GlobalScalarSignal or GlobalStringSignal assigned to the key. | | set(key: string, value: number \| string) | Sets the value of the GlobalScalarSignal or GlobalStringSignal to the value specified by value, for the key. | | keys() | Returns all keys from the GlobalMap in a form of Array<String>. | | getMap() | Returns the JS Map. | | subscribe(callback: Function, fireOnInitialValue: Boolean) | Sets a callback function to call whenever there is a change in the GlobalMap.| | subscribeOnNewKey(callback: Function, fireOnInitialValue: Boolean) | Sets a callback function to call whenever a new key is added to the GlobalMap. |

const State = require('spark-state');

(async function () {

    // Initializes a new global map
    const globalMap = await State.createGlobalMap('globalMap');

    // Sets new key-value pair
    globalMap.set('key', 1);

    // Gets the signal specified by the key
    const keySignal = globalMap.get('key');

})();

GlobalArray

GlobalArray is an array-like data structure that allows users to store and modify similar items and subscribe to the changes made to the array in a group effect.

Only Number and String types are supported, ‘GlobalScalarSignal’ and ‘GlobalStringSignal’ will be supported in the next version.

| Methods | Description | |---|---| | createGlobalArray(name: string) | Creates a new GlobalArray with a globally unique name as specified by name. | | get(ind: number) | Returns element at the specified index. |. | push(val: number \| string) | Pushes the value to the end of the array. | | set(ind: number, val: number \| string) | Changes the value at the specified index. | | insert(ind: number, val: number \| string) | Inserts the value at the specified index. | | remove(ind: number) | Removes and returns the value at the specified index. | | getArray() | Returns JS Array. | | subscribe(callback: Function, fireOnInitialValue: Boolean) | Sets a callback function to call whenever there is a change in the array.|

const State = require('spark-state');

(async function () {

    // Initializes a new global array
    const globalArray = await State.createGlobalArray('globalArray');

    // Pushes 1 to the array
    globalArray.push(1);

    // Inserts 0 at the index 1
    globalArray.insert(1,0);

    // Returns the array
    globalArray.getArray();

})();

GlobalDatabase

GlobalDatabase is a key-value pair data type like GlobalMap but also allows to nest maps and perform atomic transactions.

| Methods | Description | |---|---| | createGlobalDatabase(name: string) | Creates a new GlobalDatabase with a globally unique name as specified by name. | | get(key: string) | Returns the value assigned to the key. | | set(key: string, value: number \| string \| JS Object(Map)) | Sets the value to the specified key. | | keys() | Returns all keys from the GlobalDatabase in a form of Array<String>. | | getJSON() | Returns the JSON representation of the GlobalDatabase.| | transact(f: Function) | Makes the changes inside of a function as a single transaction. | | subscribe(callback: Function, path: String, fireOnInitialValue: Boolean) | Sets a callback function to call whenever there is a change in the map specified by path.|

const State = require('spark-state');

(async function () {

    // Initializes a new global database
    const globalDatabase = await State.createGlobalDatabase('database');

    // Sets new key-value pairs
    globalDatabase.set('companyA/personA', 100);
    globalDatabase.set('companyB/personB', 0);

    // Applies the changes as one transcation
    globalDatabase.transact(() => {
      globalDatabase.set('companyA/personA', 50);
      globalDatabase.set('companyB/personB', 50);
    });

})();

SortedParticipantArray

SortedParticipantArray provides access to an array containing a sorted list of the participants in a group effect, which is synchronized across all participants.

The object can be queried to get a snapshot of the participants active in the effect or that have been active in the call at some point, sorted by join time.

| Methods | Description | |---|---| | createSortedParticipantArray() | Creates a new SortedParticipantArray object that can be queried for sorted participant lists. | | getSortedActiveParticipants() | Returns a snapshot of the participants active in the group effect as an array of Participant objects, sorted by join time. | | getSortedAllTimeParticipants() | Returns a snapshot of the participants that have been in the call as an array of Participant objects, sorted by join time. The returned array includes all of the participants who have joined the call, whether they are currently active or not. |

| Properties | Description | |---|---| | changesSignal | A ScalarSignal updated every time there’s a change in the call’s participants propagated to the Sorted Active Participants array.

const State = require('spark-state');
(async function () {
    // Initializes a new sorted participant array
    const sortedParticipantArray = await State.createSortedParticipantArray();
    // Get all of the participants currently active in the effect
    let activeParticipants = await sortedParticipantArray.getSortedActiveParticipants();

    sortedParticipantArray.changesSignal.monitor().subscribe(async () => {
        // Update activeParticipants with new values
        activeParticipants = await sortedParticipantArray.getSortedActiveParticipants();
        doSomething();
    });

})();

Full Meta Spark API documentation is available on the main documentation site.

Example

You can check out this tutorial on the official Meta Spark documentation site, which uses the State API to synchronize data across participants.

Additional resources

The following resources are available on the Meta Spark Studio documentation site:

  • ParticipantsModule
  • MultipeerModule
  • Creating a Group Effect with the Multipeer API
  • Creating Turn-Based Experiences with the Participants API
  • Synchronizing Data Across Participants with the State API

License

The Spark State library is MIT licensed.