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

@bandeira-tech/b3nd-core

v0.26.0

Published

B3nd Core — framework foundation: types, encoding, clients, rig, network, hash, encrypt

Readme

B3nd Core

Framework foundation for B3nd. Types, encoding, clients, Rig, Identity, network primitives -- everything needed to run a decentralized network without any protocol-specific logic.

GitHub

The Rig

The Rig wires clients, validation, and behavior into a single object that speaks the ProtocolInterfaceNode (PIN) interface.

import {
  connection,
  FunctionalClient,
  Rig,
} from "@bandeira-tech/b3nd-core";

const store = new Map<string, unknown>();
const client = new FunctionalClient({
  receive: (msgs) => {
    for (const [uri, payload] of msgs) store.set(uri, payload);
    return Promise.resolve(msgs.map(() => ({ accepted: true })));
  },
  read: (urls) =>
    Promise.resolve(
      urls.flatMap((u) => (store.has(u) ? [[u, store.get(u)]] : [])),
    ),
});

const rig = new Rig({
  routes: {
    receive: [connection(client, ["**"])],
    read: [connection(client, ["**"])],
  },
});

await rig.receive([["mutable://open/users/alice", { name: "Alice" }]]);
const [profile] = await rig.read(["mutable://open/users/alice"]);
profile?.[1]; // { name: "Alice" }

Locators

read and observe take locators — opaque addressing strings. The rig matches them against route patterns by segment-glob and hands them to the executing client unchanged. The framework defines no locator grammar; the client on the other end decides what it accepts (a bare uri, a uri plus request-time directives, a pattern with wildcards — its choice).

receive takes Output[] where the first element is a uri — the canonical resource identifier the payload is written under.

Errors and content

The framework speaks one shape — Output[] — end-to-end. There is no explicit failure channel and no framework opinion on payload content:

  • Transport / programmer errors throw: network down, no route accepts, malformed locator the executing client rejects — they propagate as exceptions.
  • Anything else lives in the payload by client convention. Miss representation, auth refusals, domain errors, binary encoding — chosen and documented by the executing client, not by the framework.

Observe (INV-style)

observe yields readonly string[] batches of uris that fired — INV-style. Default emission is one uri per yield; backends with cheap batching can coalesce. Which subscription locator matched is not surfaced (cheap to re-derive locally if you need that routing). Read each uri to learn its current state.

const ac = new AbortController();
for await (const uris of pin.observe(["mutable://app/**"], ac.signal)) {
  const outputs = await pin.read(uris);
  for (const [uri, payload] of outputs) console.log(uri, payload);
}

Connections

Connections bind clients to locator patterns. The rig routes per operation:

  • receive — broadcast to every matching connection.
  • read — for each locator, the first connection that accepts wins. No fall-through, no aggregation. Compose a memcache + shards aggregator as its own client and route to that if you want layered storage.
  • observe — locators are grouped by the first matching connection; per-connection streams are merged into one.
const rig = new Rig({
  routes: {
    receive: [connection(primaryClient, ["mutable://**", "hash://**"])],
    read: [connection(primaryClient, ["mutable://**", "hash://**"])],
    observe: [connection(primaryClient, ["mutable://**", "hash://**"])],
  },
});

Pattern syntax

One grammar across connection, observe, and reactions:

  • literal segments must match exactly,
  • * matches exactly one non-empty segment (no /),
  • ** matches zero or more remaining segments (only as the last segment).

If a reaction needs a segment value, extract it from the URI — patterns are bool-only, no captures. Patterns compile once: pure literals to ===, **-prefix patterns to String.startsWith, anything with * to a cached RegExp. :param segments are rejected at compile time.

Programs and Handlers

Programs are pure functions that classify messages by URI prefix. Handlers decide what each classification code means operationally.

const rig = new Rig({
  routes: {/* ... */},
  programs: {
    "store://balance": balanceProgram,
  },
  handlers: {
    "balance:valid": async (msg) => [msg], // persist as-is
  },
});

Identity

Ed25519 signing + X25519 encryption, seed-deterministic or generated.

const id = await Identity.fromSeed("my-secret");
const auth = await id.sign({ action: "transfer", amount: 100 });
const valid = await id.verify(
  { action: "transfer", amount: 100 },
  auth.signature,
);

Hooks, Events, Reactions

const rig = new Rig({
  routes: {/* ... */},
  hooks: {
    beforeReceive: (ctx) => {/* throw to reject */},
    beforeRead: (ctx) => {
      // ctx is { url }; locators are opaque — if you need to inspect
      // the grammar, bring your own parser. Return `{ ctx: { url } }`
      // to rewrite. For invasive transforms, wrap the executing client.
    },
    afterRead: (ctx, result) => {/* observe */},
    onError: (ctx) => {/* handle errors */},
  },
  on: {
    "receive:success": [(e) => notifyPeers(e)],
    "*:error": [(e) => alertOps(e)],
  },
  reactions: {
    "mutable://app/users/*": async (output) => {/* triggered on write */},
  },
});
  • Hooks -- synchronous gates (throw to reject, observe after, catch errors)
  • Events -- async fire-and-forget (never block the caller)
  • Reactions -- URI-pattern triggers on successful writes

Network

Peer-to-peer replication with pluggable policies.

import { flood, network, peer } from "@bandeira-tech/b3nd-core";

const stop = network(localRig, [
  peer(remoteClient),
], [flood()]);

Modules

| Module | What's in it | | ------------------ | ----------------------------------------------------------------------- | | types | ProtocolInterfaceNode, Output, B3ndError, Errors, … | | encoding | Base64 / hex primitives | | hash | SHA-256 | | encrypt | Ed25519 signing, X25519 encryption, AES-GCM, PBKDF2 | | rig | Rig, Identity, connections, hooks, events, reactions | | identity | Identity (re-export of rig/identity) | | network | network(), peer(), flood, path-vector, tell-and-read | | client-console | Console output client (write-only, debug sink) |

Subpath Exports

import { ... } from "@bandeira-tech/b3nd-core";              // everything
import type { ... } from "@bandeira-tech/b3nd-core/types";    // types only
import { ... } from "@bandeira-tech/b3nd-core/encoding";      // base64 / hex primitives
import { ... } from "@bandeira-tech/b3nd-core/hash";          // sha256
import { ... } from "@bandeira-tech/b3nd-core/encrypt";       // signing, encryption
import { ... } from "@bandeira-tech/b3nd-core/rig";           // Rig + connections
import { ... } from "@bandeira-tech/b3nd-core/identity";      // Identity
import { ... } from "@bandeira-tech/b3nd-core/network";       // network primitives
import { ... } from "@bandeira-tech/b3nd-core/client-console"; // console client
import { RecordingClient } from "@bandeira-tech/b3nd-core/testing"; // PIN test double

Testing

b3nd-core ships a first-party PIN test double for use in your own tests:

import { RecordingClient } from "@bandeira-tech/b3nd-core/testing";
import type { RecordedCall, RecordedCallOf, RecordingClientFixtures } from "@bandeira-tech/b3nd-core/testing";

RecordingClient records every receive, read, observe, and status call so you can assert on interactions without a real transport. Use it to test rigs, programs, and code handlers in-process.

Development

deno task test        # Run tests
deno task check       # Type check
deno fmt --check mod.ts src/
deno lint mod.ts src/

Project Structure

mod.ts          # Main entry point + subpath re-exports
src/            # One folder per module (types, rig, network, …)
scripts/        # Build tooling (build-npm.ts)

License

MIT