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

@measuremetrics/measure-sdk

v1.0.1

Published

Official Node.js/TypeScript SDK for the Measure API

Readme

Measure Node.js SDK

Official Node.js client for the Measure API, so you can define custom metrics, record measurements, and query time series analytics from your server-side code.

Installation

bun add @measuremetrics/measure-sdk
npm install @measuremetrics/measure-sdk

Quick start

import { MeasureClient, QueryBuilder } from '@measuremetrics/measure-sdk';

const client = new MeasureClient({
  apiKey: process.env.MEASURE_API_KEY,
  organizationId: 'org_123',
  environmentId: 'env_456',
});

// Create a metric
const metric = await client.metrics.create({
  name: 'Monthly Recurring Revenue',
  unit: 'currency',
  precision_recorded: 2,
});

// Record a measurement
await client.metricAdjustments.create(metric.id, {
  timestamp: '2025-03-01T00:00:00Z',
  amount: 5000.00,
});

// Query the data
const result = await client.queries.execute(
  new QueryBuilder()
    .addMetric(metric.id, 'MRR')
    .timeRangePreset('Last30Days')
    .granularity('day')
    .build()
);

Configuration

Pass a MeasureClientConfig object when creating the client:

| Field | Type | Default | Description | |-------|------|---------|-------------| | apiKey | string | required | API key for authentication | | baseURL | string | https://measure.dev | Base URL for the API | | organizationId | string | -- | Organization ID for request context | | environmentId | string | -- | Environment ID for request context | | timeout | number | 30000 | Request timeout in milliseconds | | retry | Partial<RetryConfig> | see below | Retry configuration | | headers | Record<string, string> | -- | Additional headers for all requests | | fetch | typeof fetch | -- | Custom fetch implementation |

Resources

Every resource follows the same pattern: list, create, get, update, delete, and search where applicable. Some resources have additional methods.

// List with pagination
const metrics = await client.metrics.listPaginated({ limit: 50 });

// Create
const metric = await client.metrics.create({ name: 'Revenue', unit: 'currency' });

// Get by ID
const metric = await client.metrics.get('met_123');

// Update
await client.metrics.update('met_123', { name: 'Total Revenue' });

// Delete
await client.metrics.delete('met_123');

// Search
const results = await client.metrics.search({ search: { q: 'revenue' } });

Available resources

| Resource | Property | Description | |----------|----------|-------------| | Annotations | client.annotations | Time-based annotations for dashboards and charts | | API Keys | client.apiKeys | Manage API keys for authentication | | Business Reviews | client.businessReviews | Periodic business review snapshots | | Calculated Metrics | client.calculatedMetrics | Expression-based derived metrics | | Chat | client.chat | AI-powered metric insights | | Cohorts | client.cohorts | User and entity cohort definitions | | Dashboards | client.dashboards | Dashboard configuration and layout | | Entities | client.entities | Business object types (customers, products, etc.) | | Entity Members | client.entityMembers | Data instances of entity types | | Environments | client.environments | Workspace isolation (dev, staging, production) | | Event Definitions | client.eventDefinitions | Event schema definitions | | Event Topics | client.eventTopics | Event topic groupings | | Goals | client.goals | Metric targets and goal tracking | | Health | client.health | API health check | | Integrations | client.integrations | Third-party integration configuration | | Managed Entities | client.managedEntities | System-managed entity types | | Metric Adjustments | client.metricAdjustments | Record measurements with dimensional context | | Metrics | client.metrics | Measurable quantities to track over time | | Narratives | client.narratives | AI-generated metric narratives | | Organizations | client.organizations | Top-level tenant management | | People | client.people | User profiles and identity | | Public API Keys | client.publicApiKeys | Write-only keys for client-side tracking | | Queries | client.queries | Time series analytics queries | | System Logs | client.systemLogs | Audit and system event logs | | Teams | client.teams | Team management within organizations | | Tracking | client.tracking | High-volume event tracking | | Users | client.users | User account management |

Querying analytics

Use QueryBuilder to construct time series queries with a fluent API:

import { QueryBuilder } from '@measuremetrics/measure-sdk';

const query = new QueryBuilder()
  .addMetric('met_revenue', 'Revenue', 2)
  .addYearOverYear('met_revenue', 'Revenue YoY')
  .timeRange('2025-01-01', '2025-03-31')
  .granularity('month')
  .addDimension('ent_customer', 'prop_region', 'Region')
  .filterBy('ent_customer', 'prop_tier', 'Equals', { String: 'Enterprise' })
  .build();

const result = await client.queries.execute(query);

Temporal metric types

| Method | Description | |--------|-------------| | addMetric(id, name?, precision?) | Base metric value | | addYearOverYear(metricId, alias) | Year-over-year comparison | | addPeriodOverPeriod(metricId, alias, offset) | Custom period comparison | | addGrowthRate(metricId, alias, offset) | Growth rate calculation | | addMovingAverage(metricId, alias, granularity, windowSize) | Moving average | | addCumulative(metricId, alias, fromPeriod) | Cumulative total |

Time range options

// Preset
.timeRangePreset('Last30Days')  // Last7Days, ThisMonth, ThisYear, etc.

// Custom dates
.timeRange('2025-01-01', '2025-03-31')

Granularity

.granularity('day')  // day, week, month, quarter, year

Filtering

Use FilterBuilder to construct type-safe property filters:

import { FilterBuilder } from '@measuremetrics/measure-sdk';

const filters = FilterBuilder.create()
  .in('ent_customer', 'prop_region', ['US-West', 'US-East'])
  .greaterThan('ent_customer', 'prop_mrr', 1000)
  .isNotNull('ent_customer', 'prop_company')
  .build();

Available operators

| Operator | Method | Value type | |----------|--------|------------| | Equals | .equals() | string, number, boolean, Date | | NotEquals | .notEquals() | string, number, boolean, Date | | GreaterThan | .greaterThan() | number | | GreaterThanOrEqual | .greaterThanOrEqual() | number | | LessThan | .lessThan() | number | | LessThanOrEqual | .lessThanOrEqual() | number | | Like | .like() | string (SQL pattern with %) | | ILike | .ilike() | string (case-insensitive) | | Contains | .contains() | string | | IContains | .icontains() | string (case-insensitive) | | In | .in() | string[] or number[] | | NotIn | .notIn() | string[] or number[] | | IsNull | .isNull() | -- | | IsNotNull | .isNotNull() | -- |

Combine multiple filter builders:

const combined = FilterBuilder.and([builder1, builder2]); // AND logic

Error handling

The SDK throws typed error classes for different failure scenarios:

import {
  MeasureClient,
  AuthenticationError,
  ValidationError,
  NotFoundError,
  RateLimitError,
  isRetryableError,
} from '@measuremetrics/measure-sdk';

try {
  await client.metrics.create({ name: 'Revenue', unit: 'currency' });
} catch (error) {
  if (error instanceof ValidationError) {
    console.log('Invalid input:', error.validationErrors);
  } else if (error instanceof AuthenticationError) {
    console.log('Bad API key');
  } else if (error instanceof NotFoundError) {
    console.log('Resource not found');
  } else if (error instanceof RateLimitError) {
    console.log('Rate limited, retry after:', error.retryAfter);
  } else if (isRetryableError(error)) {
    console.log('Server error, will retry');
  }
}

Error classes

| Class | Status | Description | |-------|--------|-------------| | BadRequestError | 400 | Malformed request | | AuthenticationError | 401 | Invalid or missing API key | | PermissionDeniedError | 403 | Insufficient permissions | | NotFoundError | 404 | Resource does not exist | | ConflictError | 409 | Duplicate resource | | UnprocessableEntityError | 422 | Semantically invalid request | | ValidationError | 422 | Field-level validation errors | | RateLimitError | 429 | Rate limit exceeded | | InternalServerError | 500 | Server error | | BadGatewayError | 502 | Bad gateway | | ServiceUnavailableError | 503 | Service temporarily unavailable | | GatewayTimeoutError | 504 | Gateway timeout | | APIConnectionError | -- | Connection failed | | APIConnectionTimeoutError | -- | Request timed out | | APINetworkError | -- | Network-level failure |

Type guards

  • isAPIError(error) -- any API error
  • isClientError(error) -- 4xx errors
  • isServerError(error) -- 5xx errors
  • isRetryableError(error) -- 5xx and network errors

Retry behavior

The SDK automatically retries failed requests for retryable errors (408, 429, 500, 502, 503, 504) with exponential backoff.

| Option | Type | Default | Description | |--------|------|---------|-------------| | maxRetries | number | 3 | Maximum retry attempts | | initialDelayMs | number | 500 | Delay before first retry | | maxDelayMs | number | 60000 | Maximum delay between retries | | jitter | JitterStrategy | 'full' | Jitter strategy |

Jitter strategies

  • full -- Random delay between 0 and the exponential delay (recommended)
  • equal -- Half deterministic, half random
  • decorrelated -- Each retry delay is independent (recommended for high concurrency)
  • none -- Pure exponential backoff

Rate limit errors (429) automatically respect the Retry-After header.

Context switching

Switch organization and environment context without creating a new client:

client.setContext('org_456', 'env_staging');
// All subsequent requests use the new context

TypeScript

The SDK is written in TypeScript with strict mode. All request and response types are exported:

import type {
  Metric,
  MetricCreateRequest,
  Entity,
  EntityCreateRequest,
  MeasureClientConfig,
  RetryConfig,
} from '@measuremetrics/measure-sdk';

Dual ESM and CommonJS output is provided.

Requirements

  • Node.js >= 18