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

@strategies/collaborate-on-fire

v1.2.3

Published

Multi-user shared state persistence using patches built on firebase

Downloads

3

Readme

collaborate-on-fire

Use collaborate-on-fire to enable multi-user shared-state environments using mobx-keystone and firebase.

Motivation

Firebase provides many mechanisms required for creating multi-user environments. It is trivial to create a chat-client or a simple game where each user controls only their own state. However, true collaboration in web-based tools often requires operating on the same set of elements simultaneously. This creates conflicts when trying to centralize state in firestore or realtime db. This solution uses the patch feature of mobx-keystone to send patches from actions performed by one user to all other users.

Features

  • Synchronize shared file state between multiple users:
    • Watch for changes to the shared file data and push these changes to all other users using realtime-db.
    • Apply incoming patches from other users to the local document state.
    • Collect patches to be sent using a configurable interval, to reduce traffic for more intensive operations.
  • Synchronize independent user state - such as cursor position or selection.
  • Load a file from cloud firestore, and track any incoming patches while it loads to ensure consistency.
  • Save the file to cloud firestore based on the most recent user to update.
  • Undo/Redo support: incoming changes do not get added to the stack. Users will only undo/redo their own changes.

Example

https://github.com/sasakiassociates/collaborate-on-fire-example

Installation

Run the following command to install collaborate-on-fire in your project:

yarn add collaborate-on-fire

OR

npm install collaborate-on-fire

Usage

Initialize Firebase

Firebase should be initialized using initializeApp before creating the MultiUserPersistence instance.

firebase.initializeApp(firebaseConfig);

Create a RootStore class with a file, userStore and undoManager that implement the IRootStore interface. Once the user id has been determined (via login) the MultiUserPersistence instance can be created.

const stateContainer: IStateContainer = new KeystoneContainer();//see example for KeystoneContainer
const rootStore: IRootStore = new RootStore();
firebase.auth().onAuthStateChanged(user => {
    new MultiUserPersistence(rootStore, stateContainer, user.uid);
});

Considerations

Think carefully about what needs to persist in your file, what can go in temporary state (e.g. interface state) and what (if anything) needs to be synced as user state.

Be careful applying snapshots e.g. to undo a change because that will undo globally and delete all actions by another user. e.g. if one were to use the practice of reverting a modal's changes to a previous snapshot on cancel this would not work well in a multi-user setup: if one user left a modal open, came back and cancelled it later, it would revert all changes by other users while that modal was open. The built-in mobx-keystone undo middleware uses patches instead of snapshots and therefore works well with this patch-based approach.

Realtime Transaction Counter

The Realtime Transaction Counter (RTC) is a centralized counter used to keep track of patches and the order in which they are applied. The same counter is saved on the firestore file's metadata so that patches since the last save can be applied when loading.

IRootStore.undoManager (optional)

It is best practice to exclude user patches from other users from the undo/redo stack. If using the mobx-keystone undo middleware, this can be specified on the rootStore object and withoutUndo will be wrapped around incoming patches.

import {UndoManager, undoMiddleware} from "mobx-keystone";
import IRootStore from "collaborate-on-fire";

class RootStore implements IRootStore {
    persist: FileStore;
    undoManager: UndoManager;
    userStore: UserStore;

    constructor(persist: FileStore, userStore: UserStore) {
        this.persist = persist;
        this.userStore = userStore;
        this.undoManager = undoMiddleware(persist);
    }
};

SingleUserPersistence

If you want to disable the multi-user behavior - for example while testing or for a demo version, you can simply use SingleUserPersistence instead (the user id is not needed)

new SingleUserPersistence(rootStore, stateContainer);

Keystone

For an example using keystone, take a look at collaborate-on-fire-example.

License

MIT