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

@neon/realtime-tanstack

v0.3.0

Published

TanStack DB integration for live queries.

Readme

@neon/realtime-tanstack

TanStack DB integration for @neon/realtime. It consumes raw live-query events while TanStack DB owns collection materialization and local reactive queries.

Status: Realtime is experimental. Its APIs may change before a stable release.

Install

npm install @neon/realtime @neon/realtime-tanstack \
  @tanstack/db @standard-schema/spec

Requirements: Node.js >= 20.19, @neon/realtime 0.2, and TanStack DB 1.x starting with 1.0.0-rc.1. All three supporting libraries are peer dependencies.

Usage

Create a collection from a shared Realtime client and a sealed query returned by the application backend:

import { createRealtimeClient } from "@neon/realtime/client";
import { realtimeCollectionOptions } from "@neon/realtime-tanstack";
import { createCollection } from "@tanstack/db";

const client = createRealtimeClient({
  url: "wss://live.neon.tech/...",
});
const query = await sealTodos();

export const todos = createCollection(realtimeCollectionOptions({
  id: "todos",
  client,
  query,
  refreshQuery: sealTodos,
  getKey: (todo) => todo.id,
}));

client, query, and getKey are required. getKey must return a stable unique string or number for every row. Standard collection options such as id, schema, garbage collection, collation, and mutation handlers are forwarded to TanStack DB.

The sealed query preserves its live row type, including values such as Date, through JSON-aware RPC typing.

The integration synchronizes eagerly. It applies each complete-row replacement or incremental change batch as one TanStack sync transaction. Realtime connecting maps to a loading collection until the first complete result and live maps to ready. Once ready, a collection retains its usable rows while a subscription is connecting or stale and reports the interruption through collection.health.failureReason. A later live state clears that recoverable failure.

A terminal error before the first result puts the collection into its error state. After the collection is ready, a terminal error keeps the last rows and the ready status while exposing the failure through collection.health.error. Framework live-query hooks report the latter as isSyncError.

This adapter represents an unordered keyed collection. It synchronizes membership and values and explicitly ignores move operations. TanStack's local queries can establish their own order; collection iteration does not preserve the server sequence, including for a query with ORDER BY or LIMIT. Use the core materialized API or React integration when server order is required. Upgrade core and this adapter together to 0.2.0 after deploying a server that accepts neon.realtime.v2.

Optimistic mutations

Use TanStack DB mutation handlers normally. Have the application mutation endpoint return the PostgreSQL transaction ID captured inside the write transaction, then explicitly wait for the live query to observe it:

const todos = createCollection(realtimeCollectionOptions({
  id: "todos",
  client,
  query,
  getKey: (todo) => todo.id,
  onUpdate: async ({ transaction, collection }) => {
    const todo = transaction.mutations[0].modified;
    const response = await fetch(`/api/todos/${todo.id}`, {
      method: "PATCH",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ completed: todo.completed }),
    });
    if (!response.ok) throw new Error("Could not update todo");

    const { txid } = (await response.json()) as { txid: string };
    await collection.utils.awaitTxId(txid);
  },
}));

awaitTxId() also handles the race where the live batch arrives before the HTTP response. It resolves after covered row changes enter TanStack DB's causal sync queue and waits indefinitely by default. Pass an optional timeout in milliseconds to bound the wait. Pending and subsequent waits reject if synchronization stops terminally; collection cleanup also rejects an outstanding wait.

awaitTxId() does not determine whether a transaction committed, so pass only the ID of a transaction known to have committed.

For SSR, use TanStack DB's normal DbClient, dehydration, and HydrationBoundary APIs with stable collection IDs. The server seeds a request-scoped collection with the initial rows; the browser hydrates it and starts ordinary Realtime synchronization. Do not pass initialData to realtimeCollectionOptions() because TanStack DB owns collection hydration. Ensure the application's serializer or decoder restores values such as Date before hydrating. The live row type describes decoded values, not their JSON representation; the adapter does not deserialize HTTP or SSR payloads.

API

realtimeCollectionOptions(config) returns ordinary TanStack DB collection options with a Realtime-owned sync implementation and an additional utils.awaitTxId() method. The package also exports the corresponding config, options, and utilities types for reusable collection factories.

The sealed query determines the row type. Refresh callbacks and collection options are checked against it rather than weakening it.