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

@cero-base/core

v1.17.0

Published

cero p2p primitives — identity, storage, network, database, blobs, rpc, pairing.

Readme

@cero-base/core

The building blocks cero is made of. Use them when cero is too high-level — when you want just an autobee, just a swarm, or just signed pairing.

Each subpath is a small, independent primitive. ReadyResource-shaped where it makes sense (.ready() + .close()).

// Barrel import — everything in one place
import {
  Identity,
  Storage,
  Network,
  Database,
  Blobs,
  Pairing,
  Invite,
  RPCServer,
  RPCClient,
  t,
  schema,
  CeroError
} from '@cero-base/core'

// Or by subpath when you want a smaller graph
import { Identity } from '@cero-base/core/identity'

Ships with TypeScript declarations (.d.ts) generated from JSDoc. Plain JS source — no TS in the tree, no compile step for runtime.

Identity

A keypair backed by a 12- or 24-word phrase. Signs and verifies. Derives a topic for swarm discovery.

import { Identity } from '@cero-base/core/identity'

const me = await Identity.generate() // fresh random
const me2 = await Identity.fromPhrase('twelve words …') // restore
const sig = me.sign(message)
Identity.verify(me.publicKey, message, sig) // → true / false
me.id // z32-encoded public key
me.topic // 32-byte buffer for swarm.join(...)
me.toPhrase() // back to words

Storage

Hyperbee or Rocks-backed local table store with a uniform put/set/get/del/count/watch surface.

import { Storage } from '@cero-base/core/storage'

const s = Storage.bee('./data', { spec: { database, meta } })
await s.ready()
await s.put('drafts', { text: 'hi' })
const { data } = await s.get('drafts', 'some-id')

Network

Hyperswarm + Wakeup. join(topic) returns a managed Discovery that auto-closes with the network.

import { Network } from '@cero-base/core/network'

const net = new Network({ bootstrap })
await net.ready()
const discovery = net.join(identity.topic)
await discovery.flush() // bounded peer announce
net.attach(myCore) // start replicating

Database

Autobee + HyperDB view with dispatch routing, hooks, and writer admission (bootstrap, claim).

import { Database } from '@cero-base/core/database'

const db = new Database({ store, identity, network, spec })
await db.ready()
await db.bootstrap({ name: 'this-device' }) // mint a per-device writer
await db.put('messages', { text: 'hi' }) // memberId stamped automatically
db.before('put', (ctx) => {
  /* mutate or veto */
})

db.bootstrap(...) swaps from the identity keypair to a fresh per-device writer. For a second device sharing the same identity, use db.bootstrap({ recovering: true }) — it waits for the first peer append, then swaps off the identity-keyed bootstrap-writer slot so autobee correctly applies remote appends.

db.claim() is an alternative path: a second device claims its existing local writer; the host admits it via add-writer once it sees the claim.

Blobs

Content-addressed Hyperblobs store. put(bytes) returns a blob id you hand back to get (or clear to reclaim space).

import { Blobs } from '@cero-base/core/blobs'

const blobs = new Blobs({ store, identity, network })
await blobs.ready()
const id = await blobs.put(Buffer.from('hello'))
const bytes = await blobs.get(id)

Pairing

BlindPairing wrapper with signed invites. createInvite() mints, join(invite) consumes. The host gets a candidate event; call candidate.confirm({ key, encryptionKey }) to admit.

import { Pairing } from '@cero-base/core/pairing'

const pair = new Pairing({ network, identity, topic: myBeeKey })
await pair.ready()

const invite = await pair.createInvite({ role: 'write' })
// host side:
pair.on('candidate', async (c) => {
  await c.confirm({ key: bee.key, encryptionKey: bee.encryptionKey })
})

// joiner side:
const { key, encryptionKey } = await pair.join(invite, { userData, timeout: 30000 })

RPC

Framed bare-rpc over any duplex stream. bindCodec(spec) attaches encode/decode helpers for hyperschema-typed envelopes.

import { RPCServer, RPCClient, bindCodec } from '@cero-base/core/rpc'

class MyServer extends RPCServer {
  async _open() {
    await super._open()
    this.rpc.onPing(async (m) => `pong:${m}`)
  }
}
const server = new MyServer(ipc, spec)
const client = new RPCClient(ipc2, spec)
await server.ready()
await client.ready()
await client.rpc.ping('hi') // → 'pong:hi'

Utils

import { toId, toKey, isKeyId, genId, subscribe } from '@cero-base/core/utils'

toId(bee.key) // 32-byte buffer → z32 string (validates length)
toKey('a1b2…') // string → 32-byte buffer
isKeyId('foo') // → false
genId() // short z32 of 16 random bytes (for ids)

subscribe({ get, watch }) builds a Readable that re-emits the latest get() on every watch(fn) tick — the primitive Database.watch is built on.

Errors

CeroError is what the library itself throws. It's diagnostic — your app should still wrap calls in its own try/catch and decide what's user-facing, retryable, fatal, etc. The codes are stable so you can branch on them safely.

import { CeroError } from '@cero-base/core/errors'

try {
  await cero.open(me.room, invite)
} catch (e) {
  if (!CeroError.isCeroError(e)) throw e
  switch (e.code) {
    case 'INVALID_INVITE':
      return showToast('Bad invite link')
    case 'EXPIRED':
      return showToast('This invite has expired')
    case 'DENIED':
      return showToast(`Denied${e.reason ? `: ${e.reason}` : ''}`)
    case 'TIMEOUT':
      return retry()
    default:
      return reportError(e)
  }
}

Codes

Generic:

| Code | Thrown when | | ------------------ | ------------------------------------------------------------------------------ | | REQUIRED | A constructor or function arg is missing (store, identity, spec, …) | | INVALID | Arg has the wrong shape/type (publicKey must be a 32-byte buffer) | | CLOSED | You called a method on a closed Database, Storage, Network, Pairing, … | | NOT_READY | You called a method before await x.ready() | | DESTROYED | A Discovery is destroyed | | UNKNOWN | Asked for a ref, handle, or other thing that doesn't exist | | NOT_WRITABLE | Tried to write to a Database whose local writer isn't admitted yet | | TIMED_OUT | A bounded wait elapsed (until(...) etc.) | | UNSUPPORTED | Feature not yet wired (nested handles, …) | | CHANNEL_MISMATCH | Storage stamped with one channel reopened under another (or none) | | CONFLICT | The operation raced an existing state (e.g. double init) |

Pairing-specific:

| Code | Thrown when | Extra fields | | ---------------- | ----------------------------------------------------------- | ------------ | | INVALID_INVITE | Invite string is malformed, wrong version, or signature bad | — | | EXPIRED | Invite past its expiresIn | — | | DENIED | Host rejected the candidate | reason | | TIMEOUT | Pairing didn't complete in time | — | | NETWORK_ERROR | Underlying swarm/blind-pairing failure | — |

Every factory produces a CeroError with name === 'CeroError', isCeroError === true, the listed .code, and (where applicable) the extra fields above. Pattern-match on .code, not on the message.

Tests

cd packages/core && npm test

Runs brittle-node test/*.test.js (brittle v4). npm run build:test regenerates the test fixture spec.

Types

npm run build:types

Emits .d.ts from JSDoc into types/. Runs automatically on npm publish via prepublishOnly.