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

@byre/signet

v1.0.0

Published

Protocol-based data transport harness

Readme

@byre/signet

Protocol-based data transport harness for web applications.

Overview

Signet is a minimal, protocol-based data transport library that provides:

  • Immutable handler registry keyed by URL protocol
  • Handler resolution from URL strings or URL objects
  • Operation routing to registered handlers
  • Multi-endpoint coordination for store, retrieve, remove, and exists operations

Installation

npm install @byre/signet

Quick Start

import { 
  emptyRegistry, 
  register, 
  store, 
  retrieve 
} from '@byre/signet';
import { createRamHandler } from '@byre/signet/handlers';

// Create a registry with the RAM handler
let registry = emptyRegistry;
registry = register(registry, 'ram:', createRamHandler());

// Store data
await store(registry, {
  endpoints: ['ram:///user/settings'],
  data: { theme: 'dark', fontSize: 16 }
});

// Retrieve data
const results = await retrieve(registry, {
  endpoints: ['ram:///user/settings']
});

console.log(results[0].data);
// { theme: 'dark', fontSize: 16 }

Core Concepts

Registry

The registry is an immutable Map-like object that maps protocols to handlers:

import { emptyRegistry, register, resolve } from '@byre/signet';

// Start with empty registry
let registry = emptyRegistry;

// Register handlers (returns a new registry)
registry = register(registry, 'ram:', createRamHandler());
registry = register(registry, 'local:', createLocalHandler());

// Resolve a handler from a URL
const handler = resolve('ram:///path', registry);

Handlers

Handlers are frozen objects that implement the Signet interface:

// Required methods
handler.$store(url, data, options)   // Store data
handler.$retrieve(url, options)      // Retrieve data
handler.$remove(url, options)        // Remove data
handler.$exists(url, options)        // Check existence

// Optional methods
handler.$subscribe(url, callback, options)  // Subscribe to changes
handler.$clear(url, options)                // Clear all data
handler.$keys(url, options)                 // List keys

Operations

Operations work on arrays of endpoints and return results:

// Store to multiple endpoints
const results = await store(registry, {
  endpoints: ['ram:///a', 'local:///b'],
  data: { value: 42 }
});

// Each result has: endpoint, status, data?, reason?
results.forEach(r => {
  if (r.status === 'fulfilled') {
    console.log(`Stored to ${r.endpoint}`);
  } else {
    console.error(`Failed: ${r.reason.message}`);
  }
});

Result Shape

All operations return an array of result objects:

interface Result {
  endpoint: string;               // The endpoint string
  status: 'fulfilled' | 'rejected';
  data?: any;                     // Present if fulfilled
  reason?: Error;                 // Present if rejected
}

Handlers

RAM Handler

In-memory key-value store. Data is lost on page refresh.

import { createRamHandler } from '@byre/signet/handlers';

const handler = createRamHandler();
registry = register(registry, 'ram:', handler);

URL Format: ram:///<path>

Capabilities: subscribe, clear, keys

Local Storage Handler

Browser localStorage persistence.

import { createLocalHandler } from '@byre/signet/handlers';

const handler = createLocalHandler({
  prefix: 'myapp:'  // Optional namespace prefix
});
registry = register(registry, 'local:', handler);

URL Format: local:///<path>

Capabilities: clear, keys

Session Storage Handler

Browser sessionStorage (tab-scoped).

import { createSessionHandler } from '@byre/signet/handlers';

const handler = createSessionHandler({
  prefix: 'myapp:'
});
registry = register(registry, 'session:', handler);

URL Format: session:///<path>

Capabilities: clear, keys

Echo Handler

Testing utility that returns stored data with metadata.

import { createEchoHandler } from '@byre/signet/handlers';

const handler = createEchoHandler();
registry = register(registry, 'echo:', handler);

// Retrieve returns { value, storedAt, accessCount }

URL Format: echo:///<path>

Delay Handler

Testing utility that wraps another handler with configurable delays.

import { createDelayHandler, createRamHandler } from '@byre/signet/handlers';

const delayed = createDelayHandler(createRamHandler(), {
  delay: 100,        // Base delay in ms
  storeDelay: 50,    // Override for $store
  retrieveDelay: 25, // Override for $retrieve
  jitter: 10         // Random +/- jitter
});

Advanced Usage

Merge Function

Use merge in retrieve to combine results from multiple endpoints:

const theme = await retrieve(registry, {
  endpoints: ['ram:///user/theme', 'ram:///defaults/theme'],
  merge: (results) => {
    // Return first successful result
    const success = results.find(r => 
      r.status === 'fulfilled' && r.data !== undefined
    );
    return success?.data ?? 'light';
  }
});

Subscriptions

Subscribe to changes at an endpoint:

import { subscribe } from '@byre/signet';

const unsubscribeFns = subscribe(registry, {
  endpoints: ['ram:///'],  // Empty path for all changes
  callback: (event) => {
    console.log(event.event); // 'store' | 'remove' | 'clear'
    console.log(event.key);   // The key that changed
    console.log(event.data);  // The new data (or undefined)
  }
});

// Later: unsubscribe
unsubscribeFns.forEach(fn => fn());

API Reference

Registry Functions

emptyRegistry                      // Empty frozen registry
register(registry, protocol, handler)  // Returns new registry
resolve(url, registry)                 // Returns handler for URL

Operations

// Core (always available)
store(registry, { endpoints, data, options? })
retrieve(registry, { endpoints, merge?, options? })
remove(registry, { endpoints, options? })
exists(registry, { endpoints, options? })

// Optional (handler must support)
subscribe(registry, { endpoints, callback, options? })
clear(registry, { endpoints, options? })
keys(registry, { endpoints, options? })

Error Types

SignetError           // Base class
SignetResolutionError // No handler for protocol
SignetHandlerError    // Handler operation failed

Running the Demo

cd examples
npm install
npm run dev

License

MIT