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

@flightlog/sdk

v0.1.0-rc.1

Published

Runtime-neutral local-first reporting SDK for Flightlog

Readme

@flightlog/sdk

Runtime-neutral TypeScript reporting SDK for the local-first Flightlog server. It batches breadcrumbs, logs, errors, navigation, network, state, and custom events without turning reporting failures into application failures.

Flightlog is development tooling, not a hosted production observability service. Start a reachable local Flightlog server before instrumenting an application.

Install and start the server

bun add @flightlog/sdk
bun add --dev @flightlog/cli
bunx @flightlog/cli studio

Alternatively, run bunx @flightlog/cli init from the application root to detect the framework, preview and confirm dependencies/scripts, and generate a starter flightlog.ts/.js/.mjs module. The initializer preserves existing files and leaves the final framework entrypoint import under application control.

The CLI is optional when another developer-managed Flightlog server is already running. The default server listens at http://127.0.0.1:4319. Loopback is tokenless unless capabilities are explicitly configured. A device or remote runtime needs flightlog dev --lan, the machine's private LAN address, and the generated ingest token. Never put the admin token in an application or expose the local server to the public internet.

The SDK is ESM and uses portable fetch, timers, console, and Web Crypto APIs. It supports modern browsers, Bun, and Node.js 18+ by default; older or specialized runtimes can supply options.fetch. React, Next.js, TanStack, Hono, and Express do not require separate Flightlog adapters for explicit reporting.

Initialize once at the application root

import { Flightlog } from "@flightlog/sdk";

Flightlog.init({
  app: "checkout-web",
  endpoint: "http://127.0.0.1:4319",
  context: {
    feature: "checkout",
    release: "1.8.0",
    environment: "development",
  },
  captureConsole: true,
  captureWarnings: true,
  captureNetwork: true,
  captureUnhandledErrors: true,
  onDiagnostic: (value) => console.warn("Flightlog transport", value),
});

Initialize before work you want to observe. Reinitialization replaces capture hooks and discards queued events, so do not initialize on every render. At controlled shutdown, call await Flightlog.cleanup() to restore hooks and attempt a final flush.

Report useful evidence

Flightlog.breadcrumb("Checkout opened", { source: "cart" });
Flightlog.log("Payment submitted", { cartId: "cart-123" });
Flightlog.navigation("Checkout/Payment", { method: "card" });
Flightlog.event("state", "Cart recalculated", { itemCount: 3 });
Flightlog.error(error, { action: "submit-payment" });

Flightlog.setContext({ user: { id: "local-user-7" }, tags: { experiment: "fast-pay" } });
await Flightlog.withContextAsync({ feature: "refund" }, async () => refund());
Flightlog.clearContext(["user"]);

Use stable, low-cardinality values for app, release, environment, feature/action/route context, and tags. Put detailed values in event data rather than the message when you want related errors to fingerprint together. Breadcrumbs should explain what happened immediately before a failure; logs should describe meaningful state transitions, not every render. error() normalizes thrown values and records a fingerprint and stack when available.

captureNetwork wraps global fetch; use Flightlog.wrapFetch(customFetch) when a framework owns its transport. Console, warning, network, and unhandled-error capture are configurable. Capture is best-effort and runtime support varies; explicit breadcrumbs and errors remain the most portable signal.

Browser, React, and TanStack applications

Initialize once in the browser entry module before rendering the application—not inside a component render. This works for plain browser apps, React, and client-rendered TanStack applications:

import { Flightlog } from "@flightlog/sdk";

Flightlog.init({
  app: "storefront-web",
  endpoint: "http://127.0.0.1:4319",
  captureUnhandledErrors: true,
  captureNetwork: true,
});

SSR frameworks must run browser initialization only in client code. For Next.js, use its client instrumentation/bootstrap surface or a client-only module; initialize a separate server instance from server instrumentation when server evidence is also wanted. Do not import a browser-token module into a server bundle or initialize repeatedly during rendering/Fast Refresh.

Browser requests are subject to CORS. The server allows its own origin and common port 3000 loopback origins by default. Add exact Vite/TanStack/other development origins when starting the CLI, for example:

FLIGHTLOG_ALLOWED_ORIGINS=http://localhost:5173 bunx @flightlog/cli dev

Any environment variable intentionally exposed to browser code is public. Loopback normally needs no capability; when a write-only ingest capability is required, use the framework's public development configuration and never expose the admin capability.

Node.js, Bun, Hono, Express, and Next.js servers

Initialize one process-level client during server startup and report explicit request evidence from middleware. Avoid global console/network capture unless you deliberately want process-wide hooks.

import { Flightlog } from "@flightlog/sdk";

Flightlog.init({
  app: "checkout-api",
  endpoint: process.env.FLIGHTLOG_ENDPOINT ?? "http://127.0.0.1:4319",
  token: process.env.FLIGHTLOG_INGEST_TOKEN,
  runtime: "node",
  captureConsole: false,
  captureNetwork: false,
  captureUnhandledErrors: false,
  context: { environment: process.env.NODE_ENV ?? "development" },
});

A Hono middleware can record duration and failures without coupling Flightlog to Hono internals:

app.use("*", async (context, next) => {
  const started = performance.now();
  try {
    await next();
  } catch (error) {
    Flightlog.error(error, { method: context.req.method, path: context.req.path });
    throw error;
  } finally {
    Flightlog.event("performance", "HTTP request", {
      method: context.req.method,
      path: context.req.path,
      status: context.res.status,
      durationMs: performance.now() - started,
    });
  }
});

Express can use the same process-level client from normal and error middleware:

app.use((request, response, next) => {
  const started = performance.now();
  response.on("finish", () => Flightlog.event("performance", "HTTP request", {
    method: request.method,
    path: request.path,
    status: response.statusCode,
    durationMs: performance.now() - started,
  }));
  next();
});

app.use((error, request, _response, next) => {
  Flightlog.error(error, { method: request.method, path: request.path });
  next(error);
});

The shared singleton has mutable process context. Do not use setContext() or withContextAsync() for overlapping server requests because one request could observe another request's context. Put request-specific fields directly in event data, or create deliberately isolated new FlightlogClient() instances when separate sessions are appropriate. Standard Node does not expose browser addEventListener error hooks, so report framework/process errors explicitly. Flush during graceful shutdown where the host framework provides a controlled hook.

Privacy and reliability

Redaction is enabled by default for sensitive key/header patterns. Configure redaction when an application has additional identifiers, and inspect Studio during integration. Redaction is defense in depth: do not send passwords, authorization values, cookies, payment data, private request bodies, or unnecessary personal data. The write-only ingest capability is still sensitive development configuration.

Events queue in memory, flush in bounded batches, and retry transient transport failures. Queue overflow drops oldest events; terminal failures are reported through onDiagnostic. The runtime-neutral SDK does not durably persist native process crashes. React Native applications needing native crash persistence should use @flightlog/react-native.

Troubleshooting

  • Check the server and endpoint with curl http://127.0.0.1:4319/health and inspect onDiagnostic.
  • A browser may need allowed-origin/CORS configuration; a physical device cannot use the host's localhost.
  • A 401/403 usually means a missing or incorrect ingest capability. Do not substitute the admin token in shipped application configuration.
  • Call await Flightlog.flush() during a controlled test, then locate the session ID from Flightlog.getSessionId() in Studio.
  • Network interception does not cover native/framework transports that bypass global fetch.

See the protocol, privacy/network model, and React Native guide.