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

@xplortech/insights-js

v0.1.8

Published

Insights API JavaScript SDK

Readme

Insights JavaScript SDK

JavaScript SDK for Snowflake REST API, a Node.js API that provides a clean interface for querying Snowflake data. Designed to simplify frontend data visualization with charts and tables, including support for filtering, sorting, and aggregations.

Installation

npm install @xplortech/insights-js

Usage

Basic Usage

import insights from "@xplortech/insights-js";
import jwt from "jsonwebtoken";
import "dotenv/config";

// Sign a JWT token with API AUTH_
const payload = {
  sub: "1234567890",
  iat: Math.floor(Date.now() / 1000),
  exp: Math.floor(Date.now() / 1000) + 60 * 15, // 15 minutes
};
const token = jwt.sign(payload, process.env.AUTH_SECRET);

// Initialize the client with an options object
const client = insights({
  apiUrl: "https://insights.example.com",
  token: token,
});

// Or without a token (when auth is handled elsewhere)
const clientWithoutToken = insights({
  apiUrl: "https://insights.example.com",
});

// Get a report
const result = await client.getReport("sales-summary", {
  columns: ["first_name", "last_name"],
  filters: [
    {
      member: "status",
      operator: "equals",
      values: ["active"],
    },
  ],
  order: {
    last_name: "asc",
    first_name: "asc",
  },
  limit: 10,
  offset: 0,
});

// Access the data
const data = result.getData();
console.log("Total records:", result.getCount());
console.log("Pagination:", result.getPagination());

Working with Result Sets

The SDK provides a ResultSet class for working with report data:

// Transform data for tabular display
const tableData = result.tablePivot(["date", "region", "revenue"]);

// Transform data for charts
const chartData = result.chartPivot("date", ["revenue", "orders"]);

Calculating Totals

// Get a report with totals calculation
const totalsResult = await client.getReport("sales-summary", {
  totals: [
    {
      fn: "sum",
      member: "amount",
    },
    {
      fn: "count",
      member: "*",
    },
    {
      fn: "avg",
      member: "amount",
    },
  ],
  filters: [
    {
      member: "status",
      operator: "equals",
      values: ["active"],
    },
  ],
});

// Access the calculated totals
const totals = totalsResult.getTotals();
// { sum_amount: 15000.0, count: 150, avg_amount: 100.0 }

Filtering Data

The API supports various filter operators:

| Operator | Description | Value Requirements | Compatible Types | | ---------------- | ------------------------------------ | -------------------- | ------------------------------ | | equals | Equal to (=) | Any number of values | All types | | notEquals | Not equal to (<>) | Any number of values | All types | | contains | Case-insensitive substring match | Any number of values | String types only | | notContains | Case-insensitive substring non-match | Any number of values | String types only | | startsWith | String starts with | Any number of values | String types only | | notStartsWith | String doesn't start with | Single value | String types only | | endsWith | String ends with | Any number of values | String types only | | notEndsWith | String doesn't end with | Single value | String types only | | gt | Greater than (>) | Single value | Numeric, Date, Time, Timestamp | | gte | Greater than or equal to (>=) | Single value | Numeric, Date, Time, Timestamp | | lt | Less than (<) | Single value | Numeric, Date, Time, Timestamp | | lte | Less than or equal to (<=) | Single value | Numeric, Date, Time, Timestamp | | set | IS NOT NULL | No values needed | All types | | notSet | IS NULL | No values needed | All types | | inDateRange | BETWEEN for dates | 1-2 values | Date, Timestamp | | notInDateRange | NOT BETWEEN for dates | 1-2 values | Date, Timestamp | | beforeDate | Before date (<) | Single value | Date, Timestamp | | afterDate | After date (>) | Single value | Date, Timestamp |

Logical Operators

By default, filters are combined with AND logic. For more complex filtering, you can use logical operators that can be nested:

const result = await client.getReport("employees", {
  columns: ["name", "department", "experience_years"],
  filters: [
    {
      or: [
        {
          member: "department",
          operator: "equals",
          values: ["sales"],
        },
        {
          and: [
            {
              member: "department",
              operator: "equals",
              values: ["marketing"],
            },
            {
              member: "experience_years",
              operator: "gte",
              values: [5],
            },
          ],
        },
      ],
    },
  ],
});

Aggregating Data

When using totals requests, the following aggregation functions are available:

| Function | Description | Compatible Types | | --------------- | ----------------------------- | ------------------------------- | | count | Counts rows | All types (allows wildcard *) | | countDistinct | Counts distinct values | Most types | | sum | Sums values | Numeric only | | avg | Calculates average | Numeric only | | min | Gets minimum value | Numeric, string, date/time | | max | Gets maximum value | Numeric, string, date/time | | median | Calculates median | Numeric only | | mode | Gets most frequent value | Most types | | stddev | Calculates standard deviation | Numeric only | | variance | Calculates variance | Numeric only |

Multiple result sets in a single call

The API can handle multiple query params in a single call.

This feature allows users to batch query requests, reducing the number of HTTP round-trips required when fetching data with different filter criteria, for instance.

// Request multiple queries example
const queryActive = {
  totals: [
    { fn: "sum", member: "revenue" },
    {
      fn: "count",
      member: "*",
    },
    {
      fn: "avg",
      member: "revenue",
    },
  ],
  filters: [
    {
      member: "status",
      operator: "equals",
      values: ["active"],
    },
  ],
};

const queryInactive = {
  totals: [
    { fn: "sum", member: "revenue" },
    {
      fn: "count",
      member: "*",
    },
    {
      fn: "avg",
      member: "revenue",
    },
  ],
  filters: [
    {
      member: "status",
      operator: "equals",
      values: ["inactive"],
    },
  ],
};

// Request both queries in a single call
const [activeTotalsResult, inactiveTotalsResult] = await client.getReport(
  reportName,
  [queryActive, queryInactive],
);

// Get calculated totals
console.log("Active totals:", activeTotalsResult.getTotals());
console.log("Inactive totals:", inactiveTotalsResult.getTotals());

Retries and request throttling

The client automatically retries API pushback (429 and 503 responses) with a delay, and always dispatches requests through a request queue that caps how many run at once.

Retries

By default, getReport, getReportMeta, listReports and exportReport retry up to 3 times when the API responds with 429 or 503:

const client = insights(token, {
  apiUrl: "https://insights.example.com",
  // These are the defaults - you don't need to pass `retry` to get this behaviour
  retry: {
    maxRetries: 6,
    baseDelayMs: 500,
    maxDelayMs: 10000,
  },
});
  • If the response includes a Retry-After header (either a number of seconds or an HTTP-date), the client waits that long before retrying, capped at maxDelayMs.
  • Otherwise, the client waits using exponential backoff: baseDelayMs * 2^attempt, plus up to 20% random jitter, capped at maxDelayMs.
  • Only 429 and 503 are retried; any other error status (e.g. 401, 404, 500) throws immediately.
  • Network errors (e.g. the request failing before a response is received) are never retried.
  • After maxRetries attempts, the original error is thrown as an InsightsRequestError (see below).

To disable retries entirely, pass retry: false:

const client = insights(token, {
  apiUrl: "https://insights.example.com",
  retry: false,
});

To observe retries (e.g. for logging), pass retry.onRetry:

const client = insights(token, {
  apiUrl: "https://insights.example.com",
  retry: {
    onRetry: ({ attempt, delayMs, status, url }) => {
      console.warn(
        `retry ${attempt} for ${url} in ${delayMs}ms (status ${status})`,
      );
    },
  },
});

Request throttling

Every request (including retries) is dispatched through a request queue that caps how many run at once and, optionally, enforces a minimum delay between request starts:

const client = insights(token, {
  apiUrl: "https://insights.example.com",
  maxConcurrentRequests: 4, // this is the default - at most 4 requests in flight at once
  minRequestIntervalMs: 0, // this is the default - no minimum spacing between request starts
});

By default, this queue is shared module-wide by every client constructed with the same apiUrl - so several client instances used on one page (e.g. multiple elements or export helpers all pointed at the same API) throttle through a single limiter rather than each opening their own burst of requests. Pass sharedQueue: false to give a client its own private queue instead:

const client = insights(token, {
  apiUrl: "https://insights.example.com",
  sharedQueue: false,
});

InsightsRequestError

Failed requests (after retries, if any) reject with an InsightsRequestError, which extends the built-in Error:

import { InsightsRequestError } from "@xplortech/insights-js";

try {
  await client.getReport("sales-summary");
} catch (err) {
  if (err instanceof InsightsRequestError) {
    console.error(err.status); // HTTP status code, e.g. 429
    console.error(err.retryAfter); // seconds from the Retry-After header, if present
    console.error(err.body); // raw response body text
  }
  // err.message keeps the historical format, e.g. "API request failed: 429 Too Many Requests. ..."
  throw err;
}

API Reference

Client Methods

  • getReport(reportName, query, options) - Get a report by name with query parameters
  • getReport(reportName, [query1, query2], options) - Get multiple result sets from a report in a single call
  • getReportMeta(reportName) - Get metadata for a specific report
  • listReports() - Get a list of all available reports

Options

The getReport method accepts an optional options object as the third parameter:

  • sql - When true, includes the generated SQL in the response
// Get a report with the generated SQL included
const result = await client.getReport(
  "sales-summary",
  { columns: ["first_name", "last_name"] },
  { sql: true },
);

// The ResultSet will include the SQL that was executed
console.log(result.getRawSQL());

Query Parameters

  • columns - Array of column names to include
  • filters - Array of filter criteria
  • order - Object with field names as keys and sort direction as values (asc or desc)
  • limit - Maximum number of records to return
  • offset - Number of records to skip
  • totals - Array of aggregation specifications (each with fn and member properties)

ResultSet Methods

  • getData() - Get all data rows as an array
  • getCount() - Get total count of records
  • getTotals() - Get calculated totals
  • getPagination() - Get pagination information
  • getRawData() - Get raw response data
  • getRawSQL() - Get the generated SQL query (if requested)
  • tablePivot(columns) - Convert data to a tabular format
  • chartPivot(xAxis, yAxes) - Convert data to series format for charting
  • exportReport(reportName, query, type) - Export a report in a specific format (default is CSV)

DEVELOPMENT AND PUBLISHING

See README_DEV.md for development and publishing instructions.

License

Xpl License