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

@skdevlabs/pharos-sdk

v0.0.3

Published

Official SDK for Pharos uptime and incident monitoring

Readme

Pharos SDK

Official TypeScript/JavaScript SDK for Pharos uptime and incident monitoring.

Installation

npm install pharos-sdk
# or
pnpm add pharos-sdk
# or
yarn add pharos-sdk

Getting Your API Key

Before using the SDK, you need to create an API key in the Pharos dashboard:

  1. Log in to your Pharos account
  2. Navigate to Settings > API Keys
  3. Click Create API Key
  4. Give your key a descriptive name (e.g., "Production Server", "CI/CD Pipeline")
  5. Copy the API key immediately - you won't be able to see it again!
  6. Store it securely in your environment variables

Security Best Practices:

  • Never commit API keys to version control
  • Store keys in environment variables (.env files)
  • Use different keys for different environments (dev, staging, production)
  • Rotate keys periodically
  • Revoke keys immediately if compromised

Quick Start

import { PharosClient } from 'pharos-sdk';

const pharos = new PharosClient({
  apiKey: process.env.PHAROS_API_KEY!, // Use environment variables
  serviceName: 'my-service',
  environment: 'production',
});

// Send a health ping
await pharos.health.ping();

Configuration

const pharos = new PharosClient({
  // Required
  apiKey: process.env.PHAROS_API_KEY!, // Get from Pharos dashboard

  // Optional
  baseUrl: 'https://usepharos.online',    // Default: https://usepharos.online (or your self-hosted URL)
  serviceName: 'my-service',           // Default: 'unknown'
  environment: 'production',           // Default: 'production'
  timeout: 5000,                       // Default: 5000ms
  maxRetries: 3,                       // Default: 3
  retryDelay: 1000,                    // Default: 1000ms (exponential backoff)
});

Environment Variables

Create a .env file in your project root:

PHAROS_API_KEY=phk_your_api_key_here
PHAROS_BASE_URL=https://usepharos.online  # Optional, defaults to https://usepharos.online

API Key Management

Creating API Keys

  1. Via Dashboard: Go to Settings > API Keys > Create API Key
  2. Name Convention: Use descriptive names that indicate the purpose
    • ✅ Good: production-web-server, staging-worker, ci-cd-pipeline
    • ❌ Bad: key1, test, mykey

Rotating API Keys

To rotate your API keys without downtime:

  1. Create a new API key in the dashboard
  2. Update your application to use the new key
  3. Deploy the changes
  4. Revoke the old key after confirming the new one works

Revoking API Keys

If a key is compromised or no longer needed:

  1. Go to Settings > API Keys
  2. Find the key you want to revoke
  3. Click the revoke button
  4. Confirm the action

Note: Revoking a key immediately blocks all API requests using that key.

Features

Health Endpoints

Create standardized, Pharos-compatible health endpoints with built-in dependency checking:

// Basic health endpoint (no checks)
const response = await pharos.createHealthResponse();
// Returns: { status: "ok", timestamp: "...", service: "...", environment: "...", uptimeSec: 123 }

// Health endpoint with dependency checks
const response = await pharos.createHealthResponse({
  version: "1.0.0",
  checks: {
    db: {
      fn: async () => {
        await db.ping();
        return { status: "ok", latencyMs: 12 };
      },
      critical: true,  // Service is "down" if this fails
      timeout: 2000,
    },
    redis: async () => {
      // Shorthand format (non-critical by default)
      await redis.ping();
      return { status: "ok", latencyMs: 5 };
    },
  },
});

Next.js App Router

// app/api/health/route.ts
import { PharosClient } from '@skdevlabs/pharos-sdk';
import { respondNextJs } from '@skdevlabs/pharos-sdk/adapters/nextjs';

const pharos = new PharosClient({
  apiKey: process.env.PHAROS_API_KEY!,
  serviceName: 'my-app',
});

export async function GET() {
  return await respondNextJs(pharos, {
    version: process.env.npm_package_version,
    checks: {
      db: async () => {
        await db.ping();
        return { status: 'ok' };
      }
    }
  });
}

Express

import express from 'express';
import { PharosClient } from '@skdevlabs/pharos-sdk';

const app = express();
const pharos = new PharosClient({
  apiKey: process.env.PHAROS_API_KEY!,
  serviceName: 'my-express-app',
});

app.get('/health', async (req, res) => {
  const { statusCode, headers, body } = await pharos.respond({
    checks: {
      db: async () => {
        await db.ping();
        return { status: 'ok', latencyMs: 12 };
      }
    }
  });

  res.status(statusCode).set(headers).send(body);
});

Fastify

import fastify from 'fastify';
import { PharosClient } from '@skdevlabs/pharos-sdk';

const app = fastify();
const pharos = new PharosClient({
  apiKey: process.env.PHAROS_API_KEY!,
  serviceName: 'my-fastify-app',
});

app.get('/health', async (request, reply) => {
  const { statusCode, headers, body } = await pharos.respond({
    checks: {
      db: async () => {
        await db.ping();
        return { status: 'ok' };
      }
    }
  });

  reply.code(statusCode).headers(headers).send(body);
});

Health Response Schema

All health endpoints return a standardized response:

{
  status: "ok" | "degraded" | "down",
  timestamp: "2025-12-31T12:00:00.000Z",
  service: "my-service",
  environment: "production",
  version: "1.0.0",              // optional
  uptimeSec: 123.45,
  checks: {                      // optional
    db: { status: "ok", latencyMs: 12 },
    redis: { status: "ok", latencyMs: 5 }
  },
  meta: {                        // optional
    region: "us-west-2",
    instanceId: "i-123"
  }
}

HTTP Status Codes:

  • 200: Service is "ok" or "degraded"
  • 503: Service is "down" (critical check failed)

Health Checks (Legacy)

Send lightweight health pings from your application's health endpoints:

// In your Express health endpoint
app.get('/health', async (req, res) => {
  await pharos.health.ping();
  res.json({ status: 'ok' });
});

// With metadata
await pharos.health.ping({
  metadata: {
    version: '1.0.0',
    uptime: process.uptime(),
  },
});

Job Tracking

Track background jobs, cron tasks, and scheduled workers:

// Track a job lifecycle
const jobName = 'daily-backup';
const startTime = Date.now();

try {
  await pharos.jobs.start({ jobName });

  // ... perform your job ...

  await pharos.jobs.complete({
    jobName,
    duration: Date.now() - startTime,
    metadata: { filesProcessed: 1000 },
  });
} catch (error) {
  await pharos.jobs.fail({
    jobName,
    error: error.message,
    duration: Date.now() - startTime,
  });
}

Incident Management

Create incidents programmatically when critical errors occur:

// System-wide incident (no endpoint required)
await pharos.incidents.create({
  title: 'High memory usage detected',
  severity: 'medium',
  description: 'Application memory usage exceeded 80% threshold',
  metadata: {
    currentMemory: '850MB',
    threshold: '800MB',
  },
});

// Endpoint-specific incident (optional endpointId)
await pharos.incidents.create({
  title: 'Database connection failed',
  severity: 'high',
  description: 'Unable to connect to primary database after 3 retries',
  endpointId: 'your-endpoint-uuid', // Optional - only if incident relates to specific endpoint
  metadata: {
    region: 'us-east-1',
    errorCode: 'ECONNREFUSED',
  },
});

Note: endpointId is optional. Use it only when the incident relates to a specific monitored endpoint. Most SDK use cases (memory issues, database problems, etc.) don't require an endpoint.

Severity levels: 'low' | 'medium' | 'high' | 'critical'

Reliability

The SDK includes built-in reliability features:

  • Automatic Retries: Failed requests are automatically retried with exponential backoff
  • Timeout Handling: Requests timeout after 5 seconds by default (configurable)
  • 5xx Error Handling: Automatically retries on server errors (5xx)
  • Network Error Handling: Retries on network failures

Error Handling

try {
  await pharos.incidents.create({
    title: 'Critical error',
    severity: 'critical',
  });
} catch (error) {
  console.error('Failed to create incident:', error);
  // Your fallback logic here
}

TypeScript Support

The SDK is written in TypeScript and provides full type definitions out of the box.

import type {
  PharosConfig,
  IncidentSeverity,
  JobStartOptions,
} from 'pharos-sdk';

Examples

Express.js Health Endpoint

import express from 'express';
import { PharosClient } from 'pharos-sdk';

const app = express();
const pharos = new PharosClient({
  apiKey: process.env.PHAROS_API_KEY!,
  serviceName: 'api-server',
});

app.get('/health', async (req, res) => {
  try {
    await pharos.health.ping();
    res.json({ status: 'healthy' });
  } catch (error) {
    res.status(500).json({ status: 'unhealthy' });
  }
});

Cron Job Monitoring

import { PharosClient } from 'pharos-sdk';

const pharos = new PharosClient({
  apiKey: process.env.PHAROS_API_KEY!,
  serviceName: 'cron-worker',
});

async function runDailyBackup() {
  const jobName = 'daily-backup';
  const startTime = Date.now();

  await pharos.jobs.start({ jobName });

  try {
    // Perform backup
    await performBackup();

    await pharos.jobs.complete({
      jobName,
      duration: Date.now() - startTime,
    });
  } catch (error) {
    await pharos.jobs.fail({
      jobName,
      error: error instanceof Error ? error.message : 'Unknown error',
      duration: Date.now() - startTime,
    });
    throw error;
  }
}

Critical Error Alerting

import { PharosClient } from 'pharos-sdk';

const pharos = new PharosClient({
  apiKey: process.env.PHAROS_API_KEY!,
  serviceName: 'payment-processor',
});

async function processPayment(amount: number) {
  try {
    // Process payment logic
    await chargeCustomer(amount);
  } catch (error) {
    // Create incident for payment failures
    await pharos.incidents.create({
      title: 'Payment processing failed',
      severity: 'critical',
      description: `Failed to process payment of $${amount}`,
      metadata: {
        amount,
        errorMessage: error.message,
        timestamp: new Date().toISOString(),
      },
    });
    throw error;
  }
}

License

MIT