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

@vantage-ui/client

v0.6.0

Published

A vantage-ui project as a typed, live object graph: lazy references and collections, optimistic edits, server-side actions, React bindings.

Readme

@vantage-ui/client

The TypeScript client for a Vantage API. It turns the API into typed models. Reads are lazy and stay current: the server pushes changes, and a React component re-renders on exactly the fields it read. Writes are optimistic and roll back when the server refuses them.

It runs in the browser and in Node 22 or later, and has no runtime dependencies. The React bindings need React 18 or later.

npm install @vantage-ui/client

Generate the models

The models come from the API's schema at /v1/schema:

npx vantage-client generate --from http://127.0.0.1:8090/v1/schema --out src/vantage.gen.ts

--from also takes a saved copy of the schema (schema.json). Regenerate after the API changes; never edit the generated file. Per entity it has XFields (the record), XInput (what create() takes) and the model X, with typed columns, lazy references, has-many collections and a method per row action.

Connect

A page served by the API connects to /v1/ws on its own origin:

import { createVantage } from "@vantage-ui/client";
import { schema, type Schema } from "./vantage.gen";

const db = createVantage<Schema>({ schema, token: () => sessionStorage.getItem("vantage.token") ?? undefined });

Outside a browser, pass url: "ws://127.0.0.1:8090/v1/ws". db.ready resolves once the API's instant entities have loaded, and db.connection reports connecting, open, closed (reconnecting), refused or protocol_mismatch.

Read

const open = db.issues.where({ status: "open" }).sort("created_at", "desc");
await open.load();
const titles = open.map((issue) => issue.title);

const page = await db.issues.window(0, 50).whenLoaded(); // one window of a long list

const issue = await db.issues.ref("JIR-12").load();
const project = await issue?.project; // references load on first read

The server filters, sorts and pages; the API decides which columns may be filtered and sorted. A refused query never throws: the collection's error holds the server's message.

Write

const result = await issue.patch({ status: "done" });
if (!result.ok) console.warn(result.error.message, issue.$errors);

const draft = issue.edit();
draft.title = "Login fails on Safari";
await draft.$flash();

await db.issues.create({ title: "Export to CSV", project: "JIR", status: "open" });

Actions and runs

Row actions are methods on the model, and $actions lists the ones the row allows right now. Every action runs as a run, with shared state and messages, that survives a reconnect or a page reload without running twice:

if (issue.$actions.includes("close_issue")) await issue.close_issue({ resolution: "fixed" });

const run = db.run.triage.start({ project: "JIR" });
run.on("flagged", (m) => console.warn(`${m.issue} has no assignee`));
const outcome = await run.done;

React

import { VantageProvider, observer, useCollection, useVantage } from "@vantage-ui/client/react";

const OpenIssues = observer(() => {
  const db = useVantage<Schema>();
  const { items, error } = useCollection(db.issues.where({ status: "open" }));
  if (error) return <p role="alert">{error}</p>;
  return <ul>{items.map((issue) => <li key={issue.id}>{issue.title}</li>)}</ul>;
});

<VantageProvider db={db} fallback={<p>Connecting…</p>}>
  <OpenIssues />
</VantageProvider>;

There are also hooks for windows (useWindow), records, actions, runs (useRun, useShared, useRunMessage) and the connection (useConnection).

Testing

@vantage-ui/client/testing has MockServer, an in-memory server with no network, for unit tests and Storybook:

import { createTestVantage } from "@vantage-ui/client/testing";

const { db, server } = createTestVantage<Schema>(schema, {
  tables: { issues: [{ id: "JIR-1", title: "Login fails", status: "open", project: "JIR" }] },
  actions: { "issues.close_issue": () => ({ status: "done" }) },
});

Full documentation

The package ships an agent skill that is also its reference documentation: skills/vantage-client/SKILL.md, with references/react.md, references/testing.md and references/protocol.md. Every example in it is type-checked and run in this package's tests.

License

MIT