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

@nocha/multiplayer-flow

v0.2.0

Published

Bounded ephemeral publication queues and timestamped multiplayer snapshot interpolation.

Readme

@nocha/multiplayer-flow

Extracted from the identical Canva Ultra and Canevas 2000 ephemeral queues. Create one flow per experience and share its publishers across features:

import { createMultiplayerFlow } from '@nocha/multiplayer-flow';
const flow = createMultiplayerFlow({ liveTransport: !import.meta.env.DEV });
const publisher = flow.createPublisher(send);
// Enable only after a connected event from the live transport.
flow.enableLiveTransport();
publisher.publish({ type: 'snapshot', position });
publisher.clear();

Preserves the existing 18 sends/1050 ms shared window, 750 ms legacy spacing, 32-entry queue, replacement of queued snapshots, 450 ms action expiry, 2500 ms snapshot expiry and 1500 ms delay after an uncertain send. A failed send is not replayed. clear() invalidates queued and not-yet-started sends; an already running send cannot be cancelled. It does not reset the shared budget.

SDK calls, connection health, snapshot vocabulary, capability checks and billing consent remain the experience's responsibility. This is neither delivery acknowledgment nor authoritative multiplayer state. Importing has no DOM effect. The built npm package has no runtime dependencies or sibling imports.

Latest values and observable queues (0.2.0)

const poses = flow.createLatestPublisher(sendPose, {
  key: pose => pose.entityId,
  maxAgeMs: 500,
  onOutcome: ({ outcome, error }) => recordPublication(outcome, error),
});
poses.publish({ entityId: 'avatar', x: 1, z: 2 });
poses.pause();
poses.resume();

Keys are local to one publisher; all publishers in one flow share the budget. createPublisher(send, { coalesceKey, maxAgeMs, onOutcome }) exposes the same policy for mixed traffic. Omit the policy to retain the existing Canevas defaults. An undefined key preserves an action instead of replacing it. Never coalesce commands whose effects must be acknowledged individually.

Outcomes are sent, replaced, overflow, expired, cleared, or uncertain. sent means only that the supplied send promise resolved, not that another player received or applied anything. Observers run in a microtask; observer failures do not interrupt the queue. Uncertain sends are never replayed. Pause clears pending work and inhibits dispatch; publications made while paused remain bounded and expire normally before dispatch on resume. Publish a fresh pose on reconnection. An in-flight send cannot be cancelled. clear() does not change pause state.

Timestamped interpolation (0.2.0)

import { createSnapshotBuffer } from '@nocha/multiplayer-flow';
const positions = createSnapshotBuffer<{ x: number; z: number }>({
  delayMs: 120,
  capacity: 32,
  interpolate: (previous, next, alpha) => ({
    x: previous.x + (next.x - previous.x) * alpha,
    z: previous.z + (next.z - previous.z) * alpha,
  }),
});
positions.push({ sequence: 1, time: performance.now(), value: { x: 0, z: 0 } });
const displayed = positions.sample(performance.now());
positions.clear();

Create one buffer per entity and sender incarnation. Sequences must be safe, nonnegative integers, and both sequence and timestamp must strictly increase. Duplicate, late or invalid samples are rejected (push returns false). Validate the payload before insertion and do not mutate stored values. Clear on a known scope/room/incarnation change; do not reset simply because a late sequence arrives. The buffer does not authenticate senders or infer authority from their payload.

sample(now) displays now - delayMs, interpolating two surrounding snapshots. The playback clock never moves backwards until clear. With too few snapshots, or a gap, it holds the nearest pose. Optional extrapolate(previous, latest, elapsedMs, intervalMs) receives elapsed time capped by maxExtrapolationMs (default zero). Extrapolation stays frozen at the cap, not indefinitely advancing. Capacity defaults to 32 and is constrained to 2–1024 snapshots.

All timestamps and sampling times must use the same clock. Monotonic local receipt times work without trusting a peer's wall clock, though transport bunching still affects that timeline. A server-timestamp timeline needs a separately estimated clock offset. A fixed delay is explicit configuration, not adaptive jitter control or proof of network latency. Start with a modest delay and tune using real frame and snapshot-age observations. Use shortest-arc interpolation for angles; never linearly interpolate wrapped yaw across a full turn. This package does not supply prediction, a room authority, reliable commands, or a persistence store.