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

@apiheron/sdk

v0.2.0

Published

Browser capture for Apiheron: records which API response fields an app reads.

Readme

@apiheron/sdk

Browser capture for Apiheron: records which fields of your API responses the app actually reads. ESM only, no runtime dependencies.

npm i @apiheron/sdk

init() patches fetch and XMLHttpRequest, so requests made through axios, jQuery, Angular or plain fetch are captured automatically. Importing the package changes nothing; on the server init() is a no-op.

Next.js, instrumentation-client.ts:

import { init } from "@apiheron/sdk";

init({
  key: process.env.NEXT_PUBLIC_APIHERON_KEY!,
  endpoint: "https://app.apiheron.com/api/ingest",
  release: process.env.NEXT_PUBLIC_COMMIT_SHA,
});

Vite, first lines of main.ts:

import { init } from "@apiheron/sdk";

init({
  key: import.meta.env.VITE_APIHERON_KEY,
  endpoint: "https://app.apiheron.com/api/ingest",
});

TanStack Query (optional, needs @tanstack/query-core 5 or later, which @tanstack/react-query already installs):

import { instrumentQueryClient } from "@apiheron/sdk/tanstack";

instrumentQueryClient(queryClient); // before the first query

Options

| Option | Type | Default | Meaning | | ----------------- | ---------- | -------- | ------------------------------------------------------------------------ | | key | string | required | Ingest key from Workspace → Projects, e.g. ah_ingest_…. | | endpoint | string | required | The collector's ingest URL. | | flushIntervalMs | number | 2000 | How often buffered events are sent. | | ignore | string[] | [] | URL substrings to skip, e.g. ["/health", "analytics."]. | | release | string | none | Build of the app, e.g. a commit SHA; links findings and source maps. | | sampleRate | number | 1 | Share of page loads to record, 0 to 1. Decided once per page load. | | captureRequests | boolean | false | Also send each request's URL and body as sent, for "Copy as cURL". |

What leaves the page

  • Field paths of JSON responses and which of them the app read, e.g. items[].price. Response values are never sent.

  • Method, status, timing, response size, a hash of the request body, the code location that made the request, and the route. Id-like path segments (numbers, uuids, tokens, email addresses) and query values are hashed; other path segments and field names stay readable.

  • TanStack query keys as random, page-scoped aliases; scenario names as typed.

  • Only with captureRequests: true (script tag: data-capture-requests): the request URL and body as sent, so the dashboard can copy a runnable cURL. Query and body fields whose names look like credentials (password, token, …_key, …) are replaced with ***; FormData, files and bodies over 8 KB are not sent. Headers are never read, so the cURL carries a $TOKEN placeholder.

Use ignore for URLs that should not be recorded at all.

Browser capture

The script build exposes window.apiheron. With data-badge, the local panel shows captured/untracked/incomplete request counts, delivery failures, dropped or queued events, and installed adapters. Its scenario controls label requests started during a workflow; repeating a name creates a new run ID.

const runId = window.apiheron.startScenario("checkout");
// Exercise the workflow, then:
const run = window.apiheron.endScenario();
const health = window.apiheron.getCaptureHealth();

The same three functions are exported from @apiheron/sdk. fetch and XMLHttpRequest are patched when capture starts, so axios, jQuery and Angular need no wiring: a body read as text is tracked when that exact text reaches JSON.parse within a second, and stays untracked (no field-usage claim) when nobody parses it. instrumentAxios(instance) is optional. Install the TanStack adapter with instrumentQueryClient(client) before issuing queries. Adapter readiness means the adapter was installed; captured requests and reads provide the evidence that it is working. Per-query overrides of TanStack structural sharing should retain the adapter's sharing function if field tracking is required.

Scenario names are transmitted: use workflow labels rather than customer names or other sensitive data. The badge's Copy telemetry preview copies the last ten local request events and health counters without an ingest key or response values. Id-like path segments (numbers, uuids, tokens, email addresses) and query values are hashed; other path segments and field names are still visible; inspect them when deciding which URL substrings to exclude with ignore.

Query keys use random, page-scoped aliases; raw key arguments never leave the page. Equality is preserved within that page, and cache-split detection compares within a session. After 5,000 distinct keys, additional keys are not linked.

Requests include tracking, truncated, sdkVersion, and optional scenario and scenarioRunId. Untracked or truncated captures are excluded from field usage advice. The collector's existing schema accepts older SDK events too.

Delivery is bounded and best effort. Explicit 429 responses pause immediately and retry at most three times. Unsent work is held within 1,000 events / 4 MB; oldest events are dropped beyond that. Ambiguous network and server failures are not replayed because usage operations are not idempotent. Inspect getCaptureHealth() for counts, lastStatus, and pausedUntil; a failed event is not silently reported as sent. Beacon acceptance means queued by the browser, not confirmed by the collector.

Source and issues

The source of this package lives at github.com/egebilge/apiheron-sdk; report problems in its issue tracker. Releases are published from that repository with npm trusted publishing, so every version carries a provenance statement linking it to the commit it was built from. The repository is exported from Apiheron's private monorepo: pull requests are welcome and are applied upstream, then exported again.