New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

mobus

Package Overview
Dependencies
Maintainers
0
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mobus

Turn state into an RxJS state machine

  • 1.4.2
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
6
increased by100%
Maintainers
0
Weekly downloads
 
Created
Source

Mo'Bus

Supercharge your state management with events, and predictable pure function state machines.

Adapt any existing class, MobX store, or Javascript Object to be event driven. Great for 3D projects in ThreeJS.

Installation

npm i mobus

Why?

You are looking for:

  • pure function state machines, to avoid the pain from side effects
  • event driven architecture, streaming solutions, or functional reactive programming
  • how to leverage the power of RxJS (EGs in React with MobX)

Example

https://github.com/jtmckay/mobus/tree/main/examples/preact

Control state with commands

import { definedEntity, stateMachineFactory } from 'mobus';

export const counterStore = { count: 0 }

export const { commandFactory, subscribe } = stateMachineFactory('counter', {
  storeSingle: counterStore
});
subscribe();

export const increment = commandFactory<void>({
  eventHandler: (entity) => {
    const counter = definedEntity(entity)
    counter.count++;
    return counter
  }
})

If you need it in a render cycle (EG: React with MobX)

import { definedEntity, stateMachineFactory } from 'mobus';
import { observable, runInAction } from 'mobx';

export const counterStore = observable({ count: 0 })

export const { commandFactory, subscribe } = stateMachineFactory('counter', {
  wrapper: runInAction,
  storeSingle: counterStore
});

Then render it in React, Preact etc.

import { increment, counterStore } from '../../domain/counter/counter.bus';
import { observer } from 'mobx-react-lite';

const Counter = observer(() => (
  <div onClick={() => increment()}>
    Counter: {counterStore.count}
	</div>
));

Optimistic updates

This example uses a more advanced store. EG: Map<string, Pedometer>.

import { stateMachineFactory } from 'mobus';
import { pedometerStore } from './pedometer.store';

export const { commandFactory, subscribe } = stateMachineFactory(ENTITY, { wrapper: runInAction, store: pedometerStore });
subscribe();

const syncHeartRate = commandFactory<WithID & { rate: number }>({
  eventHandler: (entity, event) => {
    // EG: optional eventHandler immediately updates the state
    const pedometer = definedEntity(entity);
    pedometer.heartRate = event.payload.rate;
    return pedometer;
  },
  asyncEventHandler: async (entity, event) => {
    // EG: optional asyncEventHandler will update the state again (after hitting server etc.)
    const pedometer = definedEntity(entity);
    await new Promise((resolve) => setTimeout(resolve, 2000));
    runInAction(() => {
      pedometer.heartRate = 100;
    });
    return pedometer;
  },
});

Parallel handlers

By default, all stores will only handle one event at a time, and will queue any events that are triggered in the meantime.

import { stateMachineFactory } from 'mobus';
import { pedometerStore } from './pedometer.store';

export const { commandFactory, subscribe } = stateMachineFactory(ENTITY, {
  wrapper: runInAction,
  store: pedometerStore,
  parallel: true, // Setting parallel to true will allow multiple async handlers to fire simultaneously
});

Testing

Incredibly simple testing when compared to most RxJS implementations, because it exposes a promise that can be awaited.

describe('when incrementing the counter with a delay', () => {
  beforeEach(async () => {
    await delayedIncrement()
  });

  it('increases the count to 1', () => {
    expect(counterStore.count).toBe(1)
  });
});

Future examples

With events driving the system, it is trivial to develop advanced features for your product such as:

  • stream interactions over websockets for live collaboration
  • analytics for user engagement or business changelog

Flow

graph TD
    subgraph RxJS Events
        Event1["Command 1"]
        Event2["Command 2"]
        Event3["Command 3"]
        Event4["Command 4"]
    end
    
    subgraph Bus
        Event4 --> Commands
        Event3 --> Commands
        Event2 --> Commands
        Event1 --> Commands
        Commands --> Get
        Database -->Get
        Get --> Function["Pure Function Bussiness Logic Handlers"]
        Function --> Set
        Set --> Database["MobX Store"]
    end

    Database --> React["React (any UI)"]

    Function --> EntityStream["RxJS Stream"]

Developing & Publishing

yarn build

cd package

npm login --auth-type=legacy

npm publish

Keywords

FAQs

Package last updated on 02 Jul 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc