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

@getfluxly/node

v0.2.1

Published

GetFluxly Node.js SDK for backend lifecycle events — batched ingest, automatic retries, idempotent delivery, and alias support.

Readme

@getfluxly/node

Official GetFluxly Node.js SDK for backend lifecycle events. Batched ingest, automatic retries with jittered backoff, idempotent delivery via X-Idempotency-Key, and support for the server-only alias endpoint.

  • Runtime: Node 18+.
  • Module: ESM.
  • Types: shipped in dist/index.d.ts.
  • Zero runtime dependencies.

Use this package from trusted backend code. Browser code should use @getfluxly/browser with a publishable key.

Install

npm install @getfluxly/node

Quick Start

import { initGFluxNode } from "@getfluxly/node";

const gflux = initGFluxNode({
  token: process.env.GFLUX_SERVER_TOKEN!,
  apiHost: "https://api.getfluxly.com",
});

await gflux.track("invoice_paid", {
  userId: "user_123",
  properties: {
    invoice_id: "inv_456",
    total_usd: 99.99,
  },
});

By default the client batches: events are queued until 20 are pending or 5 seconds elapse, then flushed in a single request. Customers who need synchronous per-event delivery can pass flushAt: 1.

Always call await gflux.shutdown() before your process exits if you are using batching; otherwise queued events on the last interval can be dropped.

API

initGFluxNode(config)

Create a server-side client.

const gflux = initGFluxNode({
  token: "gflux_secret_live_xxx",
});

Config:

| Key | Default | Description | | --- | --- | --- | | token | required | API key. Use a server key for backend code. | | apiHost | https://api.getfluxly.com | API origin. Validated with new URL(). | | flushAt | 20 | Number of queued events that triggers a flush. Set to 1 for per-event delivery. | | flushIntervalMs | 5000 | Background flush interval. 0 disables it. | | maxRetries | 2 | Retries after network errors, 408/425/429, and 5xx. | | timeoutMs | 5000 | Per-request timeout. 0 disables it. | | maxQueueSize | 1000 | Maximum queued events before new events are rejected with queue_overflow. | | defaultContext | {} | Context merged into every event before SDK audit fields are added. | | includeRuntimeContext | false | Opt-in: include node_version, platform, arch on every event. Off by default to avoid sending a runtime fingerprint to SaaS backends. | | fetch | global fetch | Custom fetch for tests or non-standard runtimes. | | logger | none | Logger invoked for retries (debug), HTTP rejections, flush failures, and exhausted retries (warn). |

gflux.track(eventName, input)

Send a backend event.

await gflux.track("subscription_started", {
  userId: "user_123",
  properties: {
    plan: "pro",
    subscription_id: "sub_456",
  },
});

Identity rules match the public ingest API:

  • Use userId or externalId for a known user.
  • Use anonymousId for anonymous backend events.
  • You can send both when you already know they belong together.
  • properties and context must be objects.

userId is a friendly alias for external_id. If you pass both, they must match.

gflux.identify(input)

Link anonymous activity to a known user.

await gflux.identify({
  anonymousId: "anon_abc",
  userId: "user_123",
  traits: {
    email: "[email protected]",
    plan: "pro",
  },
});

identify stitches earlier anonymous activity to the known user. It sends the same identify event shape used by the browser SDK: both anonymous_id and external_id are required, and traits are sent under properties.traits.

gflux.alias(input)

Call the server-only alias endpoint.

await gflux.alias({
  userId: "user_123",
  anonymousId: "anon_current",
  previousId: "anon_old",
});

Use a gflux_secret_... key. Publishable keys are rejected by the API. At least one of anonymousId or previousId is required.

gflux.flush()

Flush queued events.

const result = await gflux.flush();
console.log(result.accepted, result.rejected);

Batches are automatically split into chunks of 50 events because the API rejects larger batches. Every batch carries an X-Idempotency-Key header so a retried request will not double-write events on the backend.

gflux.shutdown()

Stop the background timer and flush queued events.

await gflux.shutdown();

Call this before a CLI, worker, or test process exits when you use batching.

Batching

const gflux = initGFluxNode({
  token: process.env.GFLUX_SERVER_TOKEN!,
  flushAt: 50,
  flushIntervalMs: 10_000,
});

With batching enabled, track() and identify() return null until a flush happens. flush() and shutdown() always return a FlushResult.

Idempotency

Every batch and every alias request carries X-Idempotency-Key: <uuid> so the backend can dedupe retries. The SDK retries 408, 425, 429, and 5xx responses, plus network failures, with exponential backoff and ±25% jitter. The same key survives a retry — the backend will see the second attempt as a duplicate of the first and respond accordingly.

Errors

The SDK throws GFluxNodeError for validation, HTTP, timeout, and network failures.

import { GFluxNodeError } from "@getfluxly/node";

try {
  await gflux.track("invoice_paid", { userId: "user_123" });
} catch (error) {
  if (error instanceof GFluxNodeError) {
    if (error.code === "queue_overflow") {
      // Apply your own backoff using error.retryAfterMs.
      await wait(error.retryAfterMs ?? 1000);
    } else if (error.retryable) {
      // Network/timeout/5xx — retry at your application boundary if the
      // event is business-critical.
    }
  }
}

GFluxNodeError fields:

| Field | Type | Description | | --- | --- | --- | | code | string | Stable error code (validation_error, queue_overflow, network_error, request_timeout, invalid_response, http_4xx, client_closed, ...). | | status | number? | HTTP status when applicable. | | retryable | boolean | true for transient transport errors and 408/425/429/5xx. | | retryAfterMs | number? | Suggested wait before re-enqueueing on queue_overflow. | | details | unknown | Backend error body when the server returned one. | | cause | unknown | Original error preserved when wrapping. |

Validation errors, 401, 403, and other client errors are not retried.

Event Context

Every event includes minimal SDK audit context:

{
  "library": "gflux-node/0.2.0",
  "runtime": "node"
}

Pass includeRuntimeContext: true to add node_version, platform, and arch. Add your own context with defaultContext (merged into every event) or per call with context.

SDK audit fields always win so backend logs can tell which package sent the event.

Logging

import { initGFluxNode } from "@getfluxly/node";

const gflux = initGFluxNode({
  token: process.env.GFLUX_SERVER_TOKEN!,
  logger: {
    debug: (msg, ctx) => myLogger.debug(msg, ctx),
    warn: (msg, ctx) => myLogger.warn(msg, ctx),
  },
});

Hooks invoked:

  • debug — every transient retry (HTTP and network).
  • warn — HTTP rejections, exhausted retries, scheduled flush failures, requeues after retryable flush errors.

License

MIT