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

@joinremba/core

v0.5.0

Published

Shared SDK for Remba Infrastructure — HTTP client, types, and API key utilities.

Downloads

1,698

Readme

@joinremba/core

Zero‑dependency shared SDK for Remba Infrastructure.

npm version License: MIT Bun

The foundational package for every Remba project. Provides an HTTP client, shared TypeScript types, API‑key utilities, and webhook helpers. Used by @joinremba/beacon (monitoring), @joinremba/catalog (config & feature flags), and @joinremba/gate (rate‑limiting & idempotency) — and can be used standalone by any TypeScript / Bun application that talks to api.joinremba.com.


Features

  • createClient() — strongly‑typed HTTP client with retries, 429 back‑off, and automatic bearer‑token injection.
  • Shared typesVerifyKeyResult, ConfigEntry, FeatureFlag, LogEvent, AuditEvent, SecurityEvent, RateLimitCheckResult, IdempotencyCheckResult.
  • API‑key utilitiesparseApiKey() and isValidApiKey() for local validation and env‑var parsing.
  • Webhook helperssignPayload() / verifySignature() for HMAC‑SHA256.
  • Typed error classesNetworkError, AuthenticationError, RateLimitedError, ApiError, ApiKeyFormatError, ConfigError.
  • Zero dependencies — only built‑in node:crypto and Web fetch.
  • Strict TypeScriptstrict: true, full type exports.

Install

bun add @joinremba/core

Usage

createClient(options)

Creates a client that talks to your Remba infrastructure backend.

import { createClient } from "@joinremba/core";

const remba = createClient({
  apiKey: "api_core_live_abc123...",
  // baseUrl defaults to JOINREMBA_API_URL env var, then https://dev.remba.money
  // timeout defaults to 10_000
  // maxRetries defaults to 2
});

All methods are typed and return Promise<T>:

// Verify your own API key
const { valid, projectId, scopes } = await remba.verifyKey();

// Fetch remote configuration & feature flags
const config: ConfigEntry[] = await remba.getConfig();
const features: FeatureFlag[] = await remba.getFeatures();

// Submit local config for drift detection
await remba.submitConfig({ region: "us-east-1", ttl: 3600 });

// Ingest streaming events
await remba.ingestLogs(events);
await remba.ingestAudit(events);
await remba.ingestSecurity(events);

Client options

| Option | Default | Description | | ------------ | -------------------------------------------------------- | ------------------------ | | apiKey | required | API key for auth | | baseUrl | JOINREMBA_API_URL env var or https://dev.remba.money | API base URL | | timeout | 10_000 | Request timeout (ms) | | maxRetries | 2 | Retries on 429 / network |

The client automatically:

  • Injects Authorization: Bearer <apiKey> and User-Agent: @joinremba/core/<version> headers.
  • Retries on network errors / timeouts with exponential back‑off.
  • On 429 respects Retry-After, then throws RateLimitedError.
  • On 401 throws AuthenticationError immediately (no retry).
  • Times out individual requests after timeout ms.

Gate helpers (rate‑limiting & idempotency)

const { allowed, remaining, reset } = await remba.checkRateLimit("user:42");
const { exists, response } = await remba.checkIdempotency("order:uuid-123");
await remba.setIdempotency("order:uuid-123", { status: "created" });
await remba.verifyApiKey("api_core_live_other_key...");

API key utilities

import { parseApiKey, isValidApiKey } from "@joinremba/core";

// parse — throws ApiKeyFormatError on invalid format
const { prefix, hash } = parseApiKey("api_core_test_abc123...");
// prefix: "api_core_test", hash: "abc123..."

// validate — boolean check
if (isValidApiKey(process.env.JOINREMBA_API_KEY ?? "")) {
  // safe to parse
}

Keys must match /^(api_core_live|api_core_test)_[a-z0-9]{32,}$/.


Webhook signature helpers

import { signPayload, verifySignature } from "@joinremba/core";

const payload = JSON.stringify({ event: "deploy", status: "ok" });
const secret = "whsec_abc123...";

const sig = signPayload(payload, secret);
// 64‑character hex HMAC‑SHA256 string

const ok = verifySignature(payload, sig, secret);
// true — constant‑time comparison via crypto.timingSafeEqual

Error classes

All errors extend CoreError with a code string and optional status.

| Class | Thrown when | | --------------------- | -------------------------------------------- | | NetworkError | Connection failure or timeout | | AuthenticationError | 401 response | | RateLimitedError | 429 response (after retries exhausted) | | ApiError | Other HTTP error (err.status + err.body) | | ApiKeyFormatError | parseApiKey() malformed key | | ConfigError | Configuration error at client construction |

import { AuthenticationError, ApiError } from "@joinremba/core";

try {
  await remba.verifyKey();
} catch (err) {
  if (err instanceof AuthenticationError) console.error("Bad key", err.code);
  if (err instanceof ApiError) console.error(`HTTP ${err.status}: ${err.body}`);
}

Shared types

All types are exported from the package index:

import type {
  Client, // Interface implemented by HttpClient
  ClientOptions, // Options passed to createClient()
  VerifyKeyResult, // { valid, projectId, scopes }
  ConfigEntry, // { key, value, secret, updatedAt }
  FeatureFlag, // { name, enabled, rollout? }
  LogEvent, // { timestamp, level, service, message, data? }
  AuditEvent, // { timestamp, actor, action, resource, details? }
  SecurityEvent, // { timestamp, type, severity, source?, details? }
  RateLimitCheckResult, // { allowed, remaining, reset }
  IdempotencyCheckResult, // { exists, response? }
  ApiKeyScope, // string
} from "@joinremba/core";

Integration with other Remba packages

@joinremba/core is the shared foundation consumed by the Remba ecosystem:

  • @joinremba/beacon — monitoring & alerting. Ships LogEvent and SecurityEvent via createClient().
  • @joinremba/catalog — config & feature flags. Reads ConfigEntry / FeatureFlag and calls submitConfig() for drift detection.
  • @joinremba/gate — rate‑limiting & idempotency. Uses checkRateLimit(), checkIdempotency(), setIdempotency().
  • Standalone — any Bun/TS project can use createClient() to talk directly to the Remba API.

All packages share the same Client interface and error hierarchy.


Configuration

| Env var | Used by | Default | | ------------------- | ---------------- | -------------------------- | | JOINREMBA_API_URL | createClient() | https://dev.remba.money |

export JOINREMBA_API_URL=https://api.joinremba.com

TypeScript

Written with strict: true in tsconfig.json. All inputs and outputs are fully typed — no any or unchecked casts in the public API. The Client interface lets consumers write type‑safe wrappers or mocks.

import type { Client } from "@joinremba/core";

function monitor(client: Client) {
  client.ingestLogs([
    { timestamp: new Date().toISOString(), level: "info", service: "web", message: "started" },
  ]);
}

Requirements