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

@vaultys/peer-sdk

v1.0.1

Published

Decoupled, reusable SDK for peer-to-peer communication with Vaultys

Readme

Vaultys Peer SDK

A decoupled, reusable SDK for peer-to-peer communication built on WebRTC. This SDK provides a clean, interface-based architecture for building peer-to-peer applications with support for messaging, file sharing, audio/video calls, and group communication.

Features

  • 🔐 DID-based Identity: Use Decentralized Identifiers for peer identification
  • 💬 Messaging: Send text, files, images, and custom data between peers
  • 📞 Audio/Video Calls: Built-in support for WebRTC media streams
  • 👥 Group Management: Organize peers into groups for easier management
  • 💾 Pluggable Storage: Interface-based storage system supporting any backend
  • 🚌 Event-Driven Architecture: Decoupled communication via EventBus interface
  • 🔄 Auto-Reconnection: Automatic connection recovery with exponential backoff
  • 🏥 Health Monitoring: Built-in health checks and connection status tracking
  • 📦 TypeScript First: Full TypeScript support with comprehensive type definitions

Installation

npm install @vaultys/peer-sdk

or with yarn:

yarn add @vaultys/peer-sdk

or with pnpm:

pnpm add @vaultys/peer-sdk

Quick Start

import { setupVaultysPeerSDK, PeerService } from '@vaultys/peer-sdk';

// Create a peer service with default configuration
const peerService = setupVaultysPeerSDK({
  debug: true,
  relay: {
    host: 'your-relay-server.com',
    port: 443,
    path: '/myapp',
    secure: true
  }
});

// Initialize with your DID
await peerService.initialize('did:example:123456789');

// Add a contact
const peer = await peerService.addContact('did:example:987654321', {
  nickname: 'Alice',
  accepted: true
});

// Send a message
await peerService.sendMessage('did:example:987654321', 'Hello, Alice!');

// Listen for incoming messages
peerService.on('message-received', (message) => {
  console.log(`New message from ${message.from}: ${message.content}`);
});

Architecture

The SDK is built with a decoupled architecture using interfaces for maximum flexibility:

Storage Provider Interface

The SDK uses a StorageProvider interface that allows you to plug in any storage backend:

import { StorageProvider, MemoryStorageProvider } from '@vaultys/peer-sdk';

// Use the built-in memory storage (default)
const memoryStorage = new MemoryStorageProvider();

// Or implement your own storage provider
class CustomStorageProvider implements StorageProvider {
  async initialize(config?: StorageConfig): Promise<void> {
    // Initialize your storage
  }

  async read(path: string): Promise<Buffer | null> {
    // Read data from your storage
  }

  async write(path: string, data: Buffer | Uint8Array | string): Promise<void> {
    // Write data to your storage
  }

  // ... implement other methods
}

const peerService = setupVaultysPeerSDK({
  storageProvider: new CustomStorageProvider()
});

Event Bus Interface

The SDK emits events through an EventBus interface, allowing integration with external systems:

import { EventBus, StandardEvents, SimpleEventBus } from '@vaultys/peer-sdk';

// Use the built-in event bus (default)
const eventBus = new SimpleEventBus();

// Listen to SDK events
eventBus.on(StandardEvents.PEER_SERVICE_INITIALIZED, (data) => {
  console.log(`Service initialized with DID: ${data.did}`);
  // Trigger other services, like a room service
});

eventBus.on(StandardEvents.PEER_CONNECTED, (data) => {
  console.log(`Peer connected: ${data.did}`);
});

const peerService = setupVaultysPeerSDK({
  eventBus: eventBus
});

Core Concepts

DIDs (Decentralized Identifiers)

The SDK uses DIDs as unique identifiers for peers. Each DID is hashed to create a deterministic peer ID for the underlying PeerJS connection.

import { getPeerIdFromDid, isValidDid } from '@vaultys/peer-sdk';

const did = 'did:example:123456789';
if (isValidDid(did)) {
  const peerId = getPeerIdFromDid(did); // Generates deterministic peer ID
}

Messaging

Send various types of messages between peers:

// Text message
await peerService.sendMessage(did, 'Hello!', 'text');

// File message
const fileData = {
  name: 'document.pdf',
  size: 1024000,
  type: 'application/pdf',
  data: arrayBuffer // ArrayBuffer of file contents
};
await peerService.sendMessage(did, 'Sending a file', 'file', fileData);

// Custom JSON message
await peerService.sendMessage(did, JSON.stringify({ custom: 'data' }), 'json');

Audio/Video Calls

Make and receive audio/video calls:

// Get user media
const localStream = await navigator.mediaDevices.getUserMedia({
  audio: true,
  video: true
});

// Make a call
const call = await peerService.makeCall(did, localStream, 'video');

// Handle incoming calls
peerService.on('call-incoming', async (call) => {
  const localStream = await navigator.mediaDevices.getUserMedia({
    audio: true,
    video: call.type === 'video'
  });

  await peerService.answerCall(localStream);
});

// End a call
await peerService.endCall();

Group Management

Organize contacts into groups:

// Create a group
const group = await peerService.createGroup('Family', 'Family members');

// Add peers to group
await peerService.addPeerToGroup(did, group.id);

// Get peers in a group
const familyPeers = peerService.getPeersByGroup(group.id);

// Update group
await peerService.updateGroup(group.id, {
  name: 'Close Family',
  metadata: { color: '#ff0000' }
});

Health Monitoring

The SDK automatically monitors peer connection health:

peer.on('health-status', (status) => {
  console.log(`Peer health: ${status.isHealthy ? 'healthy' : 'unhealthy'}`);
  console.log(`RTT: ${status.rtt}ms`);
});

// Get current health status
const health = peer.connectionHealth;

API Reference

PeerService

The main service class for managing peer connections.

Methods

  • initialize(did?: string): Promise<string> - Initialize the service with a DID
  • disconnect(): Promise<void> - Disconnect from relay
  • addContact(did: string, metadata?: any): Promise<VaultysPeer> - Add a new contact
  • removeContact(did: string): Promise<void> - Remove a contact
  • getPeers(): VaultysPeer[] - Get all peers
  • getContacts(): VaultysPeer[] - Get accepted contacts
  • getPeer(did: string): VaultysPeer | undefined - Get a specific peer
  • sendMessage(did: string, content: string, type?: MessageType, fileData?: FileData): Promise<Message> - Send a message
  • makeCall(did: string, localStream: MediaStream, type?: CallType): Promise<Call> - Make a call
  • answerCall(localStream: MediaStream): Promise<void> - Answer incoming call
  • rejectCall(): Promise<void> - Reject incoming call
  • endCall(): Promise<void> - End current call

Events

  • relay-connected - relay connected
  • relay-disconnected - relay disconnected
  • peer-status - Peer connection status changed
  • message-received - Message received from peer
  • message-sent - Message sent to peer
  • call-incoming - Incoming call
  • call-status-changed - Call status changed
  • contact-online - Contact came online
  • contact-offline - Contact went offline
  • error - Error occurred

VaultysPeer

Individual peer connection management.

Properties

  • did: string - Peer's DID
  • peerId: string - Generated peer ID
  • status: PeerStatus - Current connection status
  • metadata?: PeerMetadata - Peer metadata
  • lastSeen?: Date - Last seen timestamp

Methods

  • connect(): Promise<void> - Connect to peer
  • disconnect(): void - Disconnect from peer
  • sendMessage(content: string, type?: MessageType, fileData?: FileData): Promise<Message> - Send message
  • makeCall(localStream: MediaStream, type?: CallType): Promise<Call> - Make call
  • loadMessages(limit?: number): Promise<Message[]> - Load message history
  • updateMetadata(metadata: Partial<PeerMetadata>): void - Update metadata

Advanced Usage

Custom Storage Provider for IndexedDB

import { StorageProvider, StorageConfig, StorageMetadata } from '@vaultys/peer-sdk';

class IndexedDBStorageProvider implements StorageProvider {
  private db: IDBDatabase | null = null;
  private dbName = 'vaultys-peer-sdk';

  async initialize(config?: StorageConfig): Promise<void> {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.dbName, 1);

      request.onerror = () => reject(request.error);
      request.onsuccess = () => {
        this.db = request.result;
        resolve();
      };

      request.onupgradeneeded = (event) => {
        const db = (event.target as IDBOpenDBRequest).result;
        if (!db.objectStoreNames.contains('files')) {
          db.createObjectStore('files', { keyPath: 'path' });
        }
      };
    });
  }

  async read(path: string): Promise<Buffer | null> {
    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction(['files'], 'readonly');
      const store = transaction.objectStore('files');
      const request = store.get(path);

      request.onsuccess = () => {
        const result = request.result;
        resolve(result ? Buffer.from(result.data) : null);
      };
      request.onerror = () => reject(request.error);
    });
  }

  async write(path: string, data: Buffer | Uint8Array | string): Promise<void> {
    const buffer = Buffer.isBuffer(data) ? data :
                   data instanceof Uint8Array ? Buffer.from(data) :
                   Buffer.from(data, 'utf-8');

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction(['files'], 'readwrite');
      const store = transaction.objectStore('files');
      const request = store.put({ path, data: buffer });

      request.onsuccess = () => resolve();
      request.onerror = () => reject(request.error);
    });
  }

  // Implement other required methods...
}

Integration with Room Service

import { EventBus, StandardEvents } from '@vaultys/peer-sdk';

class RoomServiceIntegration {
  constructor(private eventBus: EventBus) {
    // Listen for peer service initialization
    this.eventBus.on(StandardEvents.PEER_SERVICE_INITIALIZED, (data) => {
      this.initializeRoomService(data.did);
    });

    // Listen for room data from peers
    this.eventBus.on(StandardEvents.ROOM_DATA_RECEIVED, (data) => {
      this.handleRoomData(data);
    });
  }

  private initializeRoomService(did: string) {
    // Initialize your room service with the DID
    console.log(`Initializing room service for DID: ${did}`);
  }

  private handleRoomData(data: any) {
    // Handle room data received from peers
    console.log(`Room data received:`, data);
  }
}

// Use with the SDK
const eventBus = new SimpleEventBus();
const roomIntegration = new RoomServiceIntegration(eventBus);

const peerService = setupVaultysPeerSDK({ eventBus });

Message Persistence and Caching

// Load message history for a peer
const messages = await peerService.loadMessages(did, 100);

// Group messages by date
const groupedMessages = messages.reduce((groups, message) => {
  const date = new Date(message.timestamp).toDateString();
  if (!groups[date]) {
    groups[date] = [];
  }
  groups[date].push(message);
  return groups;
}, {} as Record<string, Message[]>);

// Implement message search
function searchMessages(messages: Message[], query: string): Message[] {
  return messages.filter(msg =>
    msg.content.toLowerCase().includes(query.toLowerCase())
  );
}

Migration from Coupled Implementation

If you're migrating from a tightly coupled implementation, here are the key changes:

Before (Coupled)

// Direct dependency on roomService
roomService.initialize(did, vaultId);

// Direct FileSystem usage
this.fileSystem = new FileSystem();
this.vaultOperations = new VaultOperations();

// Hard-coded paths
const path = PATH.PEERS + '/messages';

After (Decoupled)

// Event-based initialization
eventBus.emit(StandardEvents.PEER_SERVICE_INITIALIZED, { did, peerId });

// Storage provider interface
const storageProvider = new CustomStorageProvider();
await storageProvider.write('peers/messages', data);

// Configurable paths
const path = config.storagePath || 'peers/messages';

Contributing

We welcome contributions! Please see our Contributing Guide for details.

License

MIT License - see LICENSE file for details.

Support