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

@toktikhq/sdk-js

v0.3.0

Published

Typed JavaScript client for the TokTik Developer API (REST + realtime LIVE events)

Readme

TokTik JavaScript SDK

Typed client for the TokTik Developer API — REST data-plane + realtime LIVE event stream.

npm i @toktikhq/sdk-js

Quickstart

import { TokTikClient } from "@toktikhq/sdk-js";

const client = new TokTikClient({ apiKey: process.env.TOKTIK_API_KEY! });

// REST — provenance-enveloped responses expose `{ data, provenance }`, unchanged.
const creators = await client.creators.list({ q: "cooking", limit: 10 });
console.log(creators.provenance.freshness, creators.data.results);

const board = await client.rankings.official({ board: "hourly", region: "VN" });
console.log(board.provenance.freshness, board.data.board.entries);

// Realtime — three lines to a live event stream.
const stream = await client.live.stream(["@some.creator"], {
  onEvent: (frame) => console.log(frame.event, frame.data),
  onStatus: (frame) => console.log(frame.creatorId, "→", frame.status)
});

The client stays thin: it sends your bearer key only to the configured API origin and leaves REST retries, caching, and key storage to the calling application. (The realtime stream is the one exception — reconnection there is not optional, see below.)

Provenance is part of the answer

Most data methods return { data, provenance } and the SDK never strips the envelope. Much of this data is observed, not officially published, so freshness (near_realtime / stale / historical), source and coverageStatus tell you how much to trust a given answer.

A few shapes deliberately differ, matching the server: exports return the job / job list directly, account.usage() returns its own { period, balance, items } shape, and exports.download() returns the CSV as a string, not JSON. Everything else is enveloped.

Realtime

client.live.stream(creatorIds, handlers) handles the parts that are easy to get wrong:

  • Token lifetime — mints a short-lived handshake token per connection (via POST /v1/live/stream/token), so an expiry mid-stream costs a reconnect, not a dead socket.
  • Credential transport — the token travels in the Sec-WebSocket-Protocol subprotocol, never the URL, where it would leak into access logs and browser history.
  • Reconnect — exponential backoff with full jitter and a bounded ceiling, so a fleet does not stampede a restarted gateway.
  • Resume — the gateway keeps no per-connection memory, so the SDK re-subscribes everything after a reconnect. Subscribe/unsubscribe issued while disconnected is replayed on the next open.
const stream = await client.live.stream(["creator.one"], {
  onEvent: (f) => console.log(f.event, f.sequence, f.data),
  onStatus: (f) => console.log(f.status, f.reason),      // queued | active | offline | unavailable
  onError: (e) => console.error(e),
  onReconnect: () => console.log("resumed")
});

stream.subscribe("creator.two");
stream.unsubscribe("creator.one");
stream.close();                                          // final — stops reconnecting

Statuses are honest: a creator whose room is still being admitted/acquired reports queued, not active. active means events are actually flowing.

Node

Node 22+ has a global WebSocket, so nothing extra is needed. On older runtimes pass a factory:

import WebSocket from "ws";
client.live.stream(ids, handlers, {
  socketFactory: (url, token) => new WebSocket(url, ["bearer", token]) as any
});

The two subprotocol values must be the literal bearer followed by the token — the gateway selects and echoes the marker, and a client that offers subprotocols closes the socket if the server selects none.

Errors

Failures throw TokTikApiError, which keeps the status distinguishable rather than collapsing it:

try {
  await client.creators.get("someone");
} catch (error) {
  if (error instanceof TokTikApiError) {
    error.isUnauthorized;    // 401 — bad or expired key
    error.isForbidden;       // 403 — key lacks the scope this resource is sold under
    error.isPaymentRequired; // 402 — out of credits; retrying will not help
    error.isRateLimited;     // 429
    error.retryable;         // 429 + 5xx only
    error.requestId;         // quote this to support
  }
}

Coverage

| Namespace | Scope | Endpoints | |---|---|---| | client.live | live:read, live:stream | creator performance, stream token, stream() | | client.rankings | rank:read | official({ board }), movers({ board }), history({ board }), regions(), games({ region }) | | client.creators | creator:read | list, get, changes, analysis, following, followers | | client.content | content:read | creator videos (no params), video, video comments | | client.gifters | gifter:read | list, get, for creator | | client.trends | trend:read | list | | client.exports | export | list, create, get, download | | client.account | keys:manage | entitlements, usage |

Option names mirror the server schemas exactly. Those routes declare additionalProperties: false, so an invented parameter is a hard 400 — not an ignored extra.

The pre-D3.1 method listCreatorPerformance still works and is marked deprecated; it forwards to client.live.creatorPerformance.

0.3.0 (breaking): live.listSessions, live.getSession and the deprecated listLiveSessions / getLiveSession were removed — GET /v1/live/sessions is no longer part of the API. exports.create now takes the full export request: rankings (board + region), gifters (rangeDays, optional region / segment), creator_roster, creator_gifters (creatorUniqueId, optional window); live_sessions is gone.

Publishing

The npm artifact is self-contained: @v2/contracts is a build-only workspace dependency and the public declaration graph is bundled into dist/index.d.ts. npm run test:package imports the built ESM entry point and type-checks a clean consumer whose only dependency is this SDK.

Releases are tag-driven through .github/workflows/sdk-release.yml:

git tag sdk-js-v0.3.0
git push origin sdk-js-v0.3.0

The npm package must have a Trusted Publisher configured for this repository and that workflow. The package remains ESM-only ("type": "module"); a dual ESM/CJS build is not currently provided.

Known scope limits

  • Alert-rule (webhook:manage) and API-key (keys:manage) management endpoints are sellable but intentionally out of scope here; only usage/entitlements are exposed.