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

@enc-protocol/services

v0.9.0

Published

Platform-agnostic generic protocol services that sit between per-app SDKs (@enc-protocol/<app>-sdk) and platform adapters: Registry, Profiles, PeerMessaging, Subscriber, EnclaveProvisioner, plus a legacy-shim + composeSdk one-liner that wires everything t

Readme

@enc-protocol/services

Platform-agnostic generic protocol services that sit between per-app SDKs and platform adapters. Provides identity & enclave registration, cross-enclave profiles, peer messaging, event subscription with decryption, and dynamic enclave provisioning.

Install

npm install @enc-protocol/services

API

Registry

Class for managing three independent registration sub-apps (identities, enclaves, nodes) that share one registry enclave. Delegates lookups to a RegistryStrategyFn plugin or falls back to HTTP dataview + event log traversal.

Registry constructor

new Registry(opts?: {
  adapter?: Adapter,
  identitiesAdapter?: Adapter,
  enclavesAdapter?: Adapter,
  nodesAdapter?: Adapter,
  plugins?: ClientPluginRegistry
})

registry.identities — Sub-app for identity records (pubkey → app enclaves map).

  • lookup(id_pub) → Promise resolves record or null; caches results
  • publish(record) → Promise submits identity event
  • list(opts?: {limit?}) → Promise resolves array of all identities
  • resolveEnclave(pubKey, appName) → Promise resolves {ok, enclave?, error?}

registry.enclaves — Sub-app for enclave directory.

  • lookup(enclave_id) → Promise resolves record or null
  • publish(record) → Promise submits enclave event
  • list(opts?: {limit?}) → Promise resolves array of all enclaves

registry.nodes — Sub-app for node directory.

  • lookup(seq_pub) → Promise resolves record or null
  • publish(record) → Promise submits node event
  • list(opts?: {limit?}) → Promise resolves array of all nodes

registry.setAdapter(adapter) — Point all three sub-apps at the same adapter.

registry.setPlugins(plugins) — Wire all three sub-apps to the RegistryStrategyFn plugin.

Profiles

Class for cross-enclave profile resolution. Profiles live in each user's Personal enclave under a Shared(profile) slot. Delegates to ProfileResolverFn plugin or falls back to synchronous cache lookup + HTTP dataview fetch.

Profiles constructor

new Profiles(opts?: {
  personalAdapter?: Adapter,
  dataviewUrl?: string,
  plugins?: ClientPluginRegistry
})

profiles.get(pubKey) — Promise resolves profile object for the given pubkey, or null if not found. Caches results.

profiles.set(profile) — Promise submits profile to the personal adapter's Shared(profile) slot.

profiles.nameFor(pubKey) — Synchronous lookup of profile name from cache. Returns first of name or display_name fields, or first 8 chars of pubkey as fallback.

profiles.setPersonalAdapter(adapter) — Point at a personal enclave adapter.

profiles.setDataviewUrl(url) — Set HTTP dataview base URL for profile queries.

PeerMessaging

Class for submitting events into a peer's enclave rather than the user's own. Routes via PeerRoutingFn plugin or falls back to registry lookup + optional encryption + adapter.toEnclave.

PeerMessaging constructor

new PeerMessaging(opts?: {
  adapter?: Adapter,
  registry?: Registry,
  encrypted?: string[],
  eventToDataType?: {[event: string]: string},
  sdk?: any,
  plugins?: ClientPluginRegistry
})

peer.submit(peerPub, targetAppName, event, content, cryptoOpts?) — Promise<{ok, error?, receipt?, target?}> submits an event to peer's enclave. Resolves peer's enclave_id via registry, optionally encrypts content, and routes through adapter.toEnclave.

Subscriber

Class wrapping adapter.subscribe with optional per-event decryption. Decrypts content for events in encrypted set using sdk._decrypt, sdk.crypto.decrypt, or EnvelopeDecryptFn plugin.

Subscriber constructor

new Subscriber(opts?: {
  adapter?: Adapter,
  encrypted?: string[],
  eventToDataType?: {[event: string]: string},
  sdk?: any,
  plugins?: ClientPluginRegistry
})

subscriber.subscribe(callback) — Returns unsubscribe function. Calls callback with each event from adapter, auto-decrypting encrypted event types. Callback receives {type, content, from, _encrypted?, ...}.

EnclaveProvisioner

Class for minting enclaves on demand with timeout. Delegates to ProvisionerFn plugin or falls back to adapter.createEnclave with configurable timeout.

EnclaveProvisioner constructor

new EnclaveProvisioner(opts?: {
  adapter?: Adapter,
  timeoutMs?: number,
  plugins?: ClientPluginRegistry
})

provisioner.mint(rbacManifest) — Promise resolves enclave creation result. Throws on timeout (default 5000ms) or if adapter has no createEnclave method.

Schema

flattenEnclaveManifest(raw, opts?) — Transforms authored enclave JSON manifest into normalized {schema, states, traits, initEntries, ...} shape expected by adapters. Delegates to ManifestNormalizerFn plugin (default from @enc-protocol/plugin-client-base/normalizer).

setManifestNormalizer(fn) — Swap the active normalizer implementation. Pass null to restore the default.

Legacy Shim

createLegacyShim(opts) — Bridges typed SDK + protocol services to legacy impl-web renderer surface. Returns an object with:

  • Dynamic submit_<event>(content, cryptoOpts?) methods for each write event
  • Dynamic query_<table>(queryOpts?) methods for each read table
  • submit_to_peer(peerPub, targetAppName, event, content, cryptoOpts?) — delegates to peer.submit
  • create_enclave(rbac) — delegates to provisioner.mint
  • subscribe(cb) — delegates to subscriber.subscribe
  • identities, enclaves, nodes — direct sub-app access
  • profiles — direct profiles access
  • query_events(eventType, opts?) — raw event query
  • _events, _queries, _encrypted — metadata arrays for renderers

Composition

composeSdk(opts) — Construct typed SDK + all protocol services + legacy shim in one call.

composeSdk({
  SdkClass: HelloSdk,
  adapter: myAdapter,
  crypto?: {encrypt, decrypt},
  infra?: manifestWithEndpoints,
  identity?: overrideFromAddress,
  plugins?: ClientPluginRegistry
})

Returns the legacy-shim wrapper. All SDK + services share one plugin registry, so plugin overrides apply consistently across encryption, routing, provisioning, etc. Throws if adapter is missing; returns null if SdkClass is null.

Example

import { composeSdk, Registry, Profiles, PeerMessaging } from '@enc-protocol/services'
import { HelloSdk } from '@enc-protocol/hello-sdk'
import { MemoryAdapter } from '@enc-protocol/adapters'

const adapter = new MemoryAdapter()
const registryAdapter = new MemoryAdapter()

// Option 1: Compose everything at once
const sdk = composeSdk({
  SdkClass: HelloSdk,
  adapter,
  crypto: { encrypt, decrypt }
})

// Option 2: Assemble services separately
const registry = new Registry({ adapter: registryAdapter })
const profiles = new Profiles({ personalAdapter: adapter })
const peer = new PeerMessaging({ adapter, registry })

// Use the registry
const identity = await registry.identities.lookup('0x1234...')
await registry.identities.publish({ id_pub: '0x1234...', enclaves: { hello: 'encl_xyz' } })

// Cross-enclave profiles
const profile = await profiles.get('0x5678...')
await profiles.set({ name: 'Alice', display_name: 'alice.eth' })

// Send to peer's enclave
const result = await peer.submit('0x9abc...', 'hello', 'message', {body: 'hi'})

// Subscribe to events
const unsubscribe = sdk.subscribe(event => console.log(event))