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

@collecteverything/service-registry-client

v1.1.0

Published

Client TypeScript pour Service Registry multi-tenant

Readme

Service Registry Client

Modern TypeScript client for service discovery with automatic registration. Perfect for microservice architectures on Kubernetes with multi-tenancy, intelligent load balancing and automated lifecycle management.

Installation

npm install @collecteverything/service-registry-client

Main Features

  • Auto-registration via environment variables (zero config)
  • Service discovery with intelligent load balancing
  • Database discovery multi-tenant (MongoDB, Redis)
  • Automatic JWT authentication
  • Automatic heartbeat to keep services alive
  • Robust error handling with automatic retry
  • Intelligent caching for performance optimization
  • Real-time events for monitoring
  • Kubernetes compatible out-of-the-box
  • TypeScript with complete types

Quick Start

Auto-register in 2 lines of code

// In your Express/Fastify/NestJS service
import { createAutoRegisterClient, createK8sConfig } from '@collecteverything/service-registry-client';

app.listen(3000, async () => {
  console.log('Server started on port 3000');
  
  // Automatic auto-register!
  await createAutoRegisterClient(createK8sConfig());
  console.log('Service registered automatically');
});

That's it! Your service is now visible to all other services in the cluster.

Required environment variables

# Required variables
AUTO_REGISTER=true
SERVICE_NAME=user-api

# Variables with intelligent defaults
SERVICE_PORT=3000           # Your service port
SERVICE_VERSION=1.0.0       # Semver version
SERVICE_TYPE=service        # "service" or "database"

# Optional variables for enrichment
SERVICE_TAGS=api,users,v1   # Tags for discovery
TENANT_ID=production        # Multi-tenant isolation
REGISTRY_URL=http://service-registry.kube-system:8084  # Registry URL

Kubernetes Deployment

Service Registry (deploy once)

# registry-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: service-registry
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: service-registry
  template:
    spec:
      containers:
      - name: service-registry
        image: votre-registry:latest
        ports:
        - containerPort: 8084
---
apiVersion: v1
kind: Service
metadata:
  name: service-registry
  namespace: kube-system
spec:
  selector:
    app: service-registry
  ports:
  - port: 8084
    targetPort: 8084
  type: ClusterIP

Your services (with auto-register enabled)

# user-api-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-api
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: user-api
        image: votre-user-api:latest
        env:
        # Auto-register configuration
        - name: AUTO_REGISTER
          value: "true"
        - name: SERVICE_NAME
          value: "user-api"
        - name: SERVICE_PORT
          value: "3000"
        - name: SERVICE_VERSION
          value: "1.2.0"
        - name: SERVICE_TAGS
          value: "api,users,authentication"
        - name: TENANT_ID
          value: "production"
        
        # Automatic Kubernetes variables
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: HOSTNAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace

Advanced Usage Guide

Manual client configuration

import { ServiceRegistryClient } from '@collecteverything/service-registry-client';

const client = new ServiceRegistryClient({
  baseUrl: 'http://service-registry.kube-system:8084',
  authToken: process.env.JWT_TOKEN,
  timeout: 5000,
  heartbeatInterval: 30000, // 30 secondes
  retries: 3
});

Manual service registration

import { generateInstanceId } from '@collecteverything/service-registry-client';

const serviceInfo = await client.registerService({
  instanceId: generateInstanceId(),
  name: 'payment-api',
  version: '2.1.0',
  host: process.env.POD_IP || 'localhost',
  port: 3001,
  protocol: 'http',
  path: '/api/v2',
  tenantId: 'production',
  tags: ['api', 'payments', 'critical'],
  metadata: {
    environment: 'production',
    region: 'eu-west-1'
  }
}, {
  autoStart: true // Start heartbeat automatically
});

console.log('Service registered:', serviceInfo.url);

Discover and use other services

// Find all email services
const emailServices = await client.discoverServices({
  name: 'email-service',
  tags: ['notifications']
});

// Select a service with load balancing
const selectedService = await client.selectService({
  name: 'email-service',
  strategy: 'health-based' // 'round-robin', 'random', 'health-based'
});

if (selectedService) {
  console.log('Selected service:', selectedService.url);
  
  // Use the discovered service
  const response = await fetch(`${selectedService.url}/send-email`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ to: '[email protected]', subject: 'Hello' })
  });
}

Discover databases

// Register a MongoDB database (in a DB pod)
await client.registerDatabase({
  instanceId: process.env.HOSTNAME,
  name: 'user-database',
  databaseName: 'users_prod',
  version: '1.0.0',
  host: process.env.POD_IP,
  port: 27017,
  protocol: 'mongodb',
  databaseType: 'mongodb',
  tenantId: 'production',
  tags: ['primary', 'users'],
  maxConnections: 100
});

// Dans un autre service, récupérer la connection string
const connection = await client.getDatabaseConnection({
  databaseName: 'user-database',
  databaseType: 'mongodb'
});

if (connection) {
  console.log('MongoDB connection:', connection.connectionString);
  // mongodb://10.244.1.15:27017/users_prod
  
  // Use with mongoose
  await mongoose.connect(connection.connectionString);
}

Complete Architecture

import express from 'express';
import { createAutoRegisterClient, createK8sConfig } from '@collecteverything/service-registry-client';

class OrderService {
  private app = express();
  private registryClient?: ServiceRegistryClient;

  async initialize() {
    // Setup routes
    this.setupRoutes();
    
    // Start server
    this.app.listen(3000, async () => {
      console.log('Order Service started');
      
      // Auto-register
      this.registryClient = await createAutoRegisterClient(createK8sConfig());
      console.log('Service registered in registry');
      
      // Discover infrastructure
      await this.discoverDependencies();
    });
  }

  private setupRoutes() {
    this.app.get('/health', (req, res) => {
      res.json({ status: 'healthy', timestamp: new Date().toISOString() });
    });

    this.app.post('/orders', async (req, res) => {
      try {
        // Discover payment service
        const paymentService = await this.registryClient!.selectService({
          name: 'payment-api',
          strategy: 'health-based'
        });

        if (!paymentService) {
          return res.status(503).json({ error: 'Payment service unavailable' });
        }

        // Call payment service
        const paymentResponse = await fetch(`${paymentService.url}/process-payment`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(req.body)
        });

        const result = await paymentResponse.json();
        res.json(result);

      } catch (error) {
        res.status(500).json({ error: 'Order processing failed' });
      }
    });
  }

  private async discoverDependencies() {
    // Discover all infrastructure
    const infrastructure = await this.registryClient!.discoverAll();
    
    console.log(`Infrastructure discovered:`);
    console.log(`- ${infrastructure.summary.totalServices} services`);
    console.log(`- ${infrastructure.summary.totalDatabases} databases`);

    // Configure database connections
    for (const db of infrastructure.databases) {
      if (db.databaseType === 'mongodb' && db.name === 'orders-db') {
        await mongoose.connect(db.connectionString);
        console.log('Connected to orders database');
      }
    }
  }

  async shutdown() {
    if (this.registryClient) {
      await this.registryClient.close();
    }
  }
}

// Startup
const orderService = new OrderService();
orderService.initialize();

// Graceful shutdown
process.on('SIGTERM', () => orderService.shutdown());

API Reference

Main methods

createAutoRegisterClient(config)

Creates a client and performs auto-register in one step.

client.autoRegisterFromEnv()

Registers the service based on environment variables.

client.discoverServices(request)

Discover services based on criteria.

client.selectService(request)

Select a service with load balancing.

client.discoverDatabases(request)

Discover databases by tenant.

client.getDatabaseConnection(request)

Get a connection string.

Configuration helpers

// For local development
import { createDevConfig } from '@collecteverything/service-registry-client';
const config = createDevConfig('http://localhost:8084');

// For Kubernetes
import { createK8sConfig } from '@collecteverything/service-registry-client';
const config = createK8sConfig(jwtToken);

Error Handling

import { 
  isConnectionError, 
  isAuthenticationError, 
  isValidationError 
} from '@collecteverything/service-registry-client';

try {
  const client = await createAutoRegisterClient(config);
} catch (error) {
  if (isConnectionError(error)) {
    console.error('Registry unreachable:', error.message);
    // Service can continue to function without registry
  } else if (isAuthenticationError(error)) {
    console.error('Invalid JWT token:', error.message);
  } else if (isValidationError(error)) {
    console.error('Invalid service configuration:', error.response);
  }
}

Monitoring and Events

client.on('service:registered', ({ service }) => {
  console.log(`Service registered: ${service.name}`);
});

client.on('service:discovered', ({ services }) => {
  console.log(`Discovered ${services.length} services`);
});

client.on('heartbeat:failed', ({ instanceId, error }) => {
  console.error(`Heartbeat failed for ${instanceId}`);
});

// Registry statistics
const stats = await client.getStats();
console.log(`Registry stats: ${stats.healthy.services} healthy services`);

Multi-tenant

The client automatically handles tenant isolation:

// JWT must contain tenantId in 'websiteId' or 'tenantId' claim
const client = new ServiceRegistryClient({
  baseUrl: 'http://registry:8084',
  authToken: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...' // { tenantId: "company-abc" }
});

// All discoveries are automatically filtered by tenant
const services = await client.discoverServices({ name: 'user-api' });
// Only returns services from tenant "company-abc"

Complete examples

Simple Express service

import express from 'express';
import { createAutoRegisterClient } from '@collecteverything/service-registry-client';

const app = express();

app.get('/health', (req, res) => res.json({ status: 'ok' }));
app.get('/api/users', (req, res) => res.json({ users: [] }));

app.listen(3000, async () => {
  // Required environment variables:
  // AUTO_REGISTER=true
  // SERVICE_NAME=user-api
  // SERVICE_PORT=3000
  
  await createAutoRegisterClient({
    baseUrl: process.env.REGISTRY_URL || 'http://localhost:8084'
  });
  
  console.log('User API ready and registered');
});

MongoDB Database

// In a MongoDB pod with your client
import { createAutoRegisterClient } from '@collecteverything/service-registry-client';

// Environment variables:
// AUTO_REGISTER=true
// SERVICE_TYPE=database
// SERVICE_NAME=user-db
// DATABASE_TYPE=mongodb
// DATABASE_NAME=users_production
// SERVICE_PORT=27017

await createAutoRegisterClient({
  baseUrl: 'http://service-registry.kube-system:8084'
});

console.log('MongoDB registered in service registry');

Changelog

v1.0.0

  • Automatic auto-registration via environment variables
  • Complete Kubernetes support with POD_IP, HOSTNAME
  • Service and database discovery
  • Smart load balancing (round-robin, random, health-based)
  • Automatic heartbeat with MongoDB TTL
  • Multi-tenant JWT authentication
  • Robust error handling with retry
  • Smart cache with TTL
  • Complete TypeScript types

Usage in your projects

  1. Install the library : npm install @collecteverything/service-registry-client
  2. Add 2 lines in your service startup
  3. Configure environment variables in your K8s deployments
  4. Deploy: auto-register works automatically

That's it! Services automatically discover each other.