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/app-sdk-base

v0.9.0

Published

Platform-agnostic base SDK for per-app ENC protocol clients. AppSdk + AppClient + DataView. Manifests + adapter injected by caller.

Readme

@enc-protocol/app-sdk-base

Platform-agnostic base SDK for per-app ENC protocol clients. Provides the AppSdk class that every per-app SDK extends, with AppClient multi-enclave coordination, plugin registry wiring, and cross-enclave read views.

Install

npm install @enc-protocol/app-sdk-base

API

AppSdk (main export)

new AppSdk(opts) — Initialize the app SDK.

  • opts.manifests (required): { app, schema, infra?, enclaves: {...} }
  • opts.adapter: Single shared adapter (shorthand for single-enclave apps)
  • opts.adapters: Map of { EncleaveName: adapter } for multi-enclave apps
  • opts.plugins: ClientPluginRegistry instance (defaults to defaultClientPluginRegistry())

Resolves data_types and read views to enclave events via schema.tableMap, dispatching to the appropriate enclave's adapter.

await appSdk.init()this — Initialize the SDK. Currently a no-op; reserved for future async setup.

await appSdk.submit(name, args) → result — Submit a write event. name may be a data_type or enclave event; resolved and routed to the owning enclave's adapter.

await appSdk.query(name) → rows — Query a read view or enclave event. Cross-enclave reads route to the DataView; single-enclave queries dispatch to the adapter.

whoami(){ appId, pubHex, schemaName, dataTypes, reads, enclaves } — Introspection: app identity, schema name, declared data types and reads, and enclave roster.

raw() → AppClient — Access the underlying AppClient for primitive operations.

AppClient

new AppClient(opts) — Initialize the multi-enclave coordinator.

  • opts.manifests (required): { app, schema, infra?, enclaves: {...} }
  • opts.adapter or opts.adapters: Adapter(s) for each enclave
  • opts.identity: Optional { pubHex } identity
  • opts.plugins: ClientPluginRegistry (defaults to defaultClientPluginRegistry())

await appClient.init()this — Symmetry hook; currently a no-op.

await appClient.submit(enclaveName, event, args) → result — Submit to a specific enclave. Automatically ingests into DataView if cross-enclave reads are configured.

await appClient.query(enclaveName, event, opts) → result — Query a specific enclave event.

await appClient.grant(enclaveName, target, role) → result — Grant a role to a target.

await appClient.revoke(enclaveName, target, role) → result — Revoke a role.

await appClient.move(enclaveName, target, from, to) → result — Move a target between states.

await appClient.transfer(enclaveName, target, trait) → result — Transfer a trait.

await appClient.queryMembers(enclaveName) → array — List enclave members (if adapter supports it).

whoami(){ appId, pubHex, enclaves: [...] } — Introspection: app and enclave identity.

DataView

new DataView(crossReads, opts) — Initialize cross-enclave read view storage.

  • crossReads: Object mapping view names to { from, via, key, access } (from infra.json's cross_enclave_reads)
  • opts.ingestFn: IngestStrategyFn override (default: plugin-client-base/ingest)
  • opts.initStorageFn: Storage initialization override

dataview.query(viewName) → array | null — Query a cross-enclave read. Returns rows in reverse chronological order (append-only) or as a Map snapshot (for UPSERT views).

dataview.ingest(enclaveName, event) — Internal: ingest an event from a watched enclave. Delegates to the IngestStrategyFn plugin.

dataview.watchedEnclaves() → Set — Return the set of source enclaves this view consumes.

dataview.has(viewName) → boolean — Check if a view is configured.

dataViewFromInfra(infraManifest, opts) → DataView — Factory: build a DataView from an infra manifest.

Plugin Registry & Encryption

defaultClientPluginRegistry() → ClientPluginRegistry — Create a registry pre-bound with protocol-level client slots from @enc-protocol/plugin-client-base.

await registerDmRatchetEncryption(plugins, { getEpochSecret }) → plugins — Wire the ENC protocol's Ratchet_DM encryption (secp256k1 + HKDF-SHA256 + XChaCha20-Poly1305) into a ClientPluginRegistry. Replaces the pass-through EnvelopeEncryptFn/DecryptFn defaults. Lazy-imports @enc-protocol/plugin-dm-ratchet.

Protected Methods (for subclass overrides)

await sdk._encrypt(dataType, args, opts) → args — Envelope-encrypt hook. Default: pass-through via EnvelopeEncryptFn plugin. Subclasses override for real encryption.

await sdk._decrypt(eventType, content, fromPub) → content — Envelope-decrypt hook. Pairs with _encrypt. Default: pass-through.

Example

import { AppSdk, defaultClientPluginRegistry } from '@enc-protocol/app-sdk-base'

// Load manifests (typically baked into per-app SDK)
const manifests = {
  app: { id: 'hello', enclaves: ['Hello'] },
  schema: { name: 'HelloSchema', data_types: {...}, reads: {...}, tableMap: {...} },
  enclaves: {
    Hello: { manifest: {...} }
  }
}

// Create adapter (e.g., relay, local enclave simulation, etc.)
const adapter = {
  submit: async (event, args) => ({ id: '123', ...args }),
  query: async (event, opts) => []
}

// Initialize and use
const sdk = new AppSdk({
  manifests,
  adapter,
  plugins: defaultClientPluginRegistry()
})

await sdk.init()

// Submit a write
const result = await sdk.submit('message', { text: 'Hello' })

// Query a read
const rows = await sdk.query('messages')

// Introspect
console.log(sdk.whoami())
// { appId: 'hello', pubHex: null, schemaName: 'HelloSchema', dataTypes: [...], reads: [...], ... }