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

@spigell/my-nodejs-libs

v0.2.0

Published

Shared Node.js TypeScript utilities for workers, HTTP, logging, metrics, and messaging.

Readme

@spigell/my-nodejs-libs

Shared Node.js and TypeScript helpers for small services and workers.

This package currently groups together:

  • app worker primitives for periodic, queue-based, and WebSocket-driven jobs
  • HTTP server and client helpers
  • Prometheus and OpenTelemetry metric helpers
  • Winston-based logging and request middleware
  • utility helpers such as retry, chunking, and coin amount conversion
  • a Telegram sender wrapper

Installation

From npm

Install the package:

yarn add @spigell/my-nodejs-libs

Local development

Build the package locally:

yarn install
yarn build

Link it into another repository in one of these ways:

  1. yarn link

In this repository:

yarn link

In the consumer repository:

yarn link "@spigell/my-nodejs-libs"
  1. file: dependency
{
  "dependencies": {
    "@spigell/my-nodejs-libs": "file:../my-nodejs-libs"
  }
}
  1. Monorepo workspace dependency
{
  "dependencies": {
    "@spigell/my-nodejs-libs": "workspace:*"
  }
}

Exported modules

The package root exports everything from src/index.ts, including:

  • app: Worker, PeriodicWorker, QueueWorker, WebSocketWorker, CircularBuffer
  • HTTP: Server, JsonAxiosInstance
  • logging: Logging, createMiddleware
  • metrics: MetricRegistry, CounterMetric, GaugeMetric, HistogramMetric, PromClient, and typed metrics errors
  • messaging: TelegramSender
  • utils: RetryError, simple, chunk, Coin

Consumers should import from the package root:

import {
  Logging,
  MetricRegistry,
  PromClient,
  Server,
} from '@spigell/my-nodejs-libs';

Do not import from src/ in consumers. Published output comes from dist/.

Prometheus metrics

MetricRegistry owns an isolated OpenTelemetry meter provider and a Prometheus exporter. Construction does not start a server or register a route.

import { MetricRegistry } from '@spigell/my-nodejs-libs';

const metrics = new MetricRegistry({
  subsystem: 'vlad',
  meterName: 'vlad-control-api',
  defaultLabels: {
    installation: 'uspio-workbench',
    component: 'control-api',
  },
  defaultHistogramBoundaries: [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5],
  seriesLimit: 100,
});

const requests = metrics.counter({
  name: 'api_requests_total',
  help: 'Completed control API requests',
  labelNames: ['method', 'route', 'status_class'],
});
const dutyActive = metrics.gauge({
  name: 'duty_active',
  help: 'Whether an unexpired duty period is active',
});
const duration = metrics.histogram({
  name: 'api_request_duration_seconds',
  help: 'Control API request duration',
  unit: 's',
  labelNames: ['method', 'route', 'status_class'],
});

const labels = {
  method: 'GET',
  route: '/v1/status',
  status_class: '2xx',
};
requests.add(1, labels);
dutyActive.set(1);
duration.record(0.042, labels);

const snapshot = await metrics.collect();
// Fastify: reply.type(snapshot.contentType).send(snapshot.body)

await metrics.shutdown();

Metric and label names use Prometheus naming rules. Every observation must provide exactly the declared labels, and label values are strings. Default labels cannot be overridden by observations. Counter names always emit one _total suffix: the library adds it when omitted and preserves it when given.

The default active-series limit is 100 per metric. New series over the limit are dropped and counted in prom_client_observations_rejected_total{reason="series_limit"}. Set seriesLimitBehavior: 'throw' on the registry or an instrument to receive a MetricSeriesLimitError instead. Gauge remove(), clear(), and atomic replace() retire stale series and release their cardinality slots.

shutdown() is asynchronous and idempotent. Observations and collections after shutdown throw MetricsShutdownError. The old PromClient methods and the MetricRegistry(subsystem, promClient) constructor remain available as deprecated compatibility APIs for the 0.2.x release line.

Isolated Claude execution

Use createClaudeIsolation to give each Claude role its own prompt, settings, skills, and MCP configuration while sharing only the Claude Code OAuth credentials required for authentication. For Claude, promptPath is copied into the isolated config directory and passed to the CLI with --append-system-prompt-file; it is not installed as CLAUDE.md memory context.

import {
  claudeAdapter,
  CliRunner,
  createClaudeIsolation,
  getClaudeUsage,
} from '@spigell/my-nodejs-libs';

const isolation = await createClaudeIsolation({
  toolName: 'investigator',
  promptPath: '/app/prompts/investigator.md',
  settings: {
    model: 'claude-opus-4-8',
  },
  mcpConfig: {
    mcpServers: {
      'github-mcp': {
        type: 'http',
        url: 'http://github-mcp:8080/mcp',
      },
    },
  },
  skillSources: [
    {
      rootDir: '/app/skills',
      dirNames: ['repo-reader'],
    },
  ],
  agentSource: {
    rootDir:
      '/spigell-reforge-ai/my-shared-infra/my-agents/agents/claude/agents',
    names: ['researcher'],
  },
});

try {
  const runner = new CliRunner({
    command: 'claude',
    adapter: claudeAdapter,
    cwd: '/workspace',
    env: isolation.env,
  });

  const firstRun = await runner.run('Investigate the failing workflow.', {
    mcpConfigPath: isolation.mcpConfigPath,
    strictMcpConfig: false,
    permissionMode: 'dontAsk',
    tools: ['Read', 'Glob', 'Grep', 'mcp__github-mcp__search_code'],
    allowedTools: ['Read', 'Glob', 'Grep', 'mcp__github-mcp__search_code'],
  });
  console.log(firstRun.text, firstRun.tokenUsage, firstRun.permissionDenials);

  const resumedRun = await runner.run('Check the proposed fix.', {
    sessionId: firstRun.sessionId,
    mcpConfigPath: isolation.mcpConfigPath,
    permissionMode: 'dontAsk',
    tools: ['Read', 'Glob', 'Grep', 'mcp__github-mcp__search_code'],
    allowedTools: ['Read', 'Glob', 'Grep', 'mcp__github-mcp__search_code'],
  });
  console.log(resumedRun.text, resumedRun.tokenUsage);

  const quotaUsage = await getClaudeUsage({
    credentialsPath: isolation.credentialsPath,
  });
  console.log(quotaUsage.five_hour, quotaUsage.seven_day);
} finally {
  await isolation.cleanup();
}

getClaudeUsage() reads the Claude Code OAuth credential document. When claudeAiOauth.expiresAt is near expiry, or when the usage endpoint returns HTTP 401, it refreshes with claudeAiOauth.refreshToken, atomically persists rotated tokens to the real shared credential file behind the isolation symlink, and retries usage once. Concurrent refreshes for the same credential file are coalesced within the process. Passing an explicit accessToken disables credential-file refresh and persistence.

Isolation is ephemeral by default. cleanup() recursively removes its unique config directory and can be called more than once. Set persistent: true when the same tool must resume Claude sessions across separate isolation lifetimes; in persistent mode the path is stable and cleanup() intentionally preserves its state.

For untrusted classifier input, do not configure MCP servers, skills, or subagents, and run with tools: [] plus permissionMode: 'dontAsk'. Supplying an empty tool list emits --tools "", which disables Claude's built-in tools. Investigators should receive an explicit allowlist of read-only built-in and MCP tool names. Permission bypass is available only through the explicit dangerouslySkipPermissions: true option and must not be used for untrusted content. Claude MCP configuration is strict by default; set strictMcpConfig: false only when configured subagents need access to MCP servers outside the supplied configuration. Claude execution results expose the terminal event's normalized permissionDenials, including the denied tool name, tool-use ID, and structured input.

Development commands

yarn install
yarn typecheck
yarn lint
yarn build
yarn test

Release flow

This repository is configured to publish to the public npm registry via the shared workflow in spigell/my-shared-workflows.

Release steps:

  1. Push your changes to the default branch.
  2. Create and push a tag.
  3. GitHub Actions publishes the package to registry.npmjs.org.

The release workflow is defined in .github/workflows/tags-package-release.yaml.

Notes and caveats

  • This library is a shared internal toolkit, not a polished public SDK.
  • Some worker abstractions assume long-running Node.js processes and do not yet expose lifecycle shutdown hooks.
  • src/fuel/wallet/wallet.ts is currently a compatibility stub because the referenced wallet implementation is not present in this repository.