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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@muchekechege/pulsesync

v1.3.0

Published

Universal High-performance pull-model sync for React and backend node.js

Downloads

78

Readme

PulseSync ⚡️

A high-performance, Pull-Model state synchronization library for React. Specifically engineered for high-frequency data (Trading Bots, WebSockets, Tickers) where traditional React state or "push" models (like standard Redux or MobX) cause UI lag and "data skipping" on mobile devices.


🚀 The Problem: "The Push Bottleneck"

In high-frequency environments (like XAUUSD markets), ticks arrive constantly. Traditional state managers push every update to React: WebSocket -> Store -> Notify -> React Render -> Browser Paint

On a mobile device, if the "Paint" takes too long, the next tick is blocked. This leads to:

  • Skipped Ticks: The WebSocket buffer overflows because the UI thread is stuck.
  • UI Stutters: The Garbage Collector (GC) works overtime cleaning up discarded state objects.
  • Crashes: Memory pressure builds up until the mobile browser kills the tab.

🛡️ The Solution: "The Pull Model"

PulseSync reverses the flow. It updates a silent internal store instantly ($<0.1ms$) and allows React to pull the data only when the browser is ready to draw a frame: WebSocket -> Store (Instant Mutation) Browser Heartbeat -> requestAnimationFrame -> Pull Latest -> React Render


📦 Installation

npm install @muchekechege/pulsesync

usage

1. Create a Store

Define your initial state and initialize the store. This creates a singleton-like instance and a custom hook.

// stores/marketStore.ts
import { createPulseStore } from '@muchekechege/pulsesync';

export const { store, useSync } = createPulseStore({
  price: 0,
  timeStamp: 0,
  isCalculated: false
});

// Helper to update the store outside of the component
export const increment = () => {
  store.update({ price: store.getSnapshot().price + 1 });
};

export const decrement = () => {
  store.update({ price: store.getSnapshot().price - 1 });
};

2. Silent Updates (High Frequency)

Update the store inside your WebSocket listeners or calculation loops. These updates are "silent"—they do not trigger React's heavy rendering cycle immediately.

// logic/bot.ts
import { store } from './stores/marketStore';

socket.on('message', (data) => {
  // Ultra-fast mutation using Object.assign
  // Marks state as 'dirty' to trigger a sync on the next frame
  store.update({
    price: data.p,
    timeStamp: data.d
  });
});

3. Consume in React

Use the useSync hook with a selector. The component will only re-render if the specific slice of data you selected has changed during the last "heartbeat".

import { useSync } from './stores/marketStore';

const PriceDisplay = () => {
  // Only pulls 'price'. Ignores updates to 'timeStamp'.
  // Default equality is strict (a === b)
  const price = useSync(state => state.price);

  return <h1>${price.toFixed(2)}</h1>;
};

4. Advanced: Custom Equality

For selectors that return arrays or objects, pass a custom equality function as a second argument to useSync to prevent unnecessary renders.

const orders = useSync(
  state => state.orders,
  (prev, next) => prev.length === next.length // Custom comparison
);

Backend usage

On the backend, you treat the store object as a state-persistent buffer. In a Node.js environment, this is particularly powerful for handling high-frequency data (like market ticks) because it batches updates before triggering expensive operations like database writes or WebSocket broadcasts.

Here is how you initialize and use it to store and monitor data exactly like you would in a frontend state.

1. Initialization and "State" Logic

On the backend, you typically use the store returned by createPulseStore. This instance will now use setTimeout internally to provide the "Pulse".

// backend/marketStore.ts
import { createPulseStore } from '@muchekechege/pulsesync';

// 1. Initialize with your starting state
export const { store } = createPulseStore({
  ticks: [] as number[],
  lastMatch: null as number | null,
  isBotActive: false,
  connectionStatus: 'disconnected'
});

/**
 * Logic to update state (Same way you do in React, but on the Server)
 */
export const updateMarketData = (newDigit: number) => {
  const currentTicks = store.getSnapshot().ticks;

  // Keep only the last 500 ticks for analysis
  const updatedTicks = [...currentTicks, newDigit].slice(-500);

  store.update({
    ticks: updatedTicks,
    connectionStatus: 'connected'
  });
};

2. Using the "Pulse" for Side Effects

Instead of a useSync hook (which is for UI), on the backend you use the _subscribe method. This acts like a "Global Watcher" that fires whenever the state is marked as "dirty".

// backend/tradingBot.ts
import { store } from './marketStore';

// Subscribe to state changes to execute bot logic
store._subscribe(() => {
  const state = store.getSnapshot();

  // Example: Run your "Match Hunter" logic here
  // Because of PulseSync, this only runs once every 16ms,
  // even if 100 digits arrived in that timeframe.
  if (state.ticks.length > 10) {
     console.log(`[PULSE] Analyzing ${state.ticks.length} ticks. Current status: ${state.connectionStatus}`);
     // runMatchHunter(state.ticks);
  }
});

3. Real-World Usage: High-Frequency Data Feed

This is how you would bridge an incoming data stream (like a WebSocket from a broker) to your PulseSync state.

// backend/server.ts
import { updateMarketData, store } from './marketStore';
import { createServer } from 'http';
import { Server } from 'socket.io';

const io = new Server(createServer());

// A. Handle incoming raw data (Mutation)
const rawDataStream = someBrokerAPI.connect();

rawDataStream.on('tick', (digit: number) => {
  // Update the state as fast as the data arrives
  updateMarketData(digit);
});

// B. Broadcast processed state to clients (The Pulse)
// We only broadcast to connected clients at the Pulse rate (e.g. 16ms)
// to save bandwidth and prevent "CPU Shock" on the user's browser.
store._subscribe(() => {
  const latestState = store.getSnapshot();
  io.emit('market_update', latestState);
});

Important Note:

On the backend, remember that store is a singleton in memory. If your server restarts, the state will reset to initialState. For long-term persistence, you would typically save the snapshot to a database inside the _subscribe block.

Key Comparison: Frontend vs. Backend Usage

| Action | Frontend (React) | Backend (Node.js) | | :------------- | :------------------------------ | :----------------------------- | | Storage | createPulseStore(initial) | createPulseStore(initial) | | Updating | store.update({ key: val }) | store.update({ key: val }) | | Accessing | useSync(selector) | store.getSnapshot() | | Reactivity | Triggers Component Render | Triggers _subscribe callback | | Pulse Sync | Synced to Screen Refresh (60Hz) | Synced to setTimeout (16ms) |

🔥 Key Performance Features

  • Zero-Allocation Mutations: Internally uses Object.assign to update the state object. This prevents the creation of millions of temporary objects, keeping the Garbage Collector silent and avoiding mobile "hiccups".
  • isDirty CPU Shock Absorber: The internal heartbeat loop only notifies listeners if an update was actually triggered via store.update(). This saves massive CPU cycles during market "quiet" periods.
  • Global Heartbeat: Uses a single requestAnimationFrame loop for all active hooks. No matter how many components you have, there is only ever one sync loop running.
  • Backpressure Handling: If the device heats up or the CPU is throttled, the UI naturally drops from 60fps to 30fps, but the WebSocket logic continues at full speed in the background.

💡 Best Practices

  • Leaf Components: Use useSync in the smallest possible component. Instead of one large Dashboard hook, use small hooks in PriceLabel, DigitBox, and StatusIcon.
  • Simple Selectors: Keep your selectors simple (e.g., s => s.value). If you need complex derived math, perform it inside the store.update() phase, not in the UI hook.
  • Cleanup: PulseSync automatically stops its internal heartbeat when the last component unmounts, ensuring zero memory leaks.