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

@open-knowledge/knowledge-bundle-api

v0.0.2

Published

TypeScript contracts for exposing read-only and editable knowledge bundles over RPC

Readme

Knowledge Bundle API

Type-only contracts for exposing a knowledge bundle through an RPC system such as Cap'n Web. KnowledgeBundle is the root read capability; use ReadonlyKnowledgeBundle or EditableKnowledgeBundle when the granted access is known.

Install

npm install @open-knowledge/knowledge-bundle-api

Import the contracts with import type so they are erased from emitted JavaScript:

import type { ReadonlyKnowledgeBundle } from '@open-knowledge/knowledge-bundle-api'

export function listRoot(bundle: ReadonlyKnowledgeBundle) {
	return bundle.list({ path: '/', depth: 1 })
}

Bundle metadata is generic and must be pass-by-value data supported by the chosen RPC transport. Entries, inputs, and mutation results are plain, acyclic RPC data. The change listener and returned subscription from the optional SubscribableKnowledgeBundle extension are capabilities instead. Methods return promises so implementations may be asynchronous; calls through a Cap'n Web stub return RpcPromise values and support promise pipelining. A Cap'n Web server implementation must extend RpcTarget, while a client uses these interfaces with Cap'n Web's RpcStub<T> and session generics. Do not copy the interfaces merely to replace Promise with RpcPromise; RpcStub<T> performs that type transformation.

KnowledgeBundle<Metadata, Access> is the common read surface. ReadonlyKnowledgeBundle and EditableKnowledgeBundle specialize its Access parameter, preserving the literal returned by getInfo(). A readonly bundle is not the supertype of an editable bundle; use KnowledgeBundle when either grant is accepted. Native TypeScript utilities such as Parameters, ReturnType, Awaited, Pick, and Omit can derive adapters from these contracts without repeating method signatures. Such utilities only change static types and never attenuate a runtime capability.

Remote Cap'n Web Endpoint

A remote bundle locator has this shape:

okb://hostname/path/to/bundle
okb://hostname/path/to/bundle?insecure=true

The authority and path identify one Cap'n Web endpoint. That single endpoint exposes the KnowledgeBundle target itself as the Cap'n Web main object; it does not wrap the bundle in a second root API or require a separate discovery request.

Clients translate okb: to https:. They use http: only when the URI contains the exact query parameter insecure=true. insecure is a transport control parameter and is removed before the HTTP request; all other query parameters are retained. Fragments are not valid endpoint locators. Clients should reject embedded username/password credentials rather than persist or display them; authentication material can use an intentional endpoint query parameter or an application-specific out-of-band mechanism. For example:

function capnWebEndpoint(locator: string): URL {
	const candidate = locator.trim()
	if (candidate.includes('#')) {
		throw new TypeError('Fragments are not allowed.')
	}
	const parsed = new URL(candidate)
	if (parsed.protocol !== 'okb:' || !parsed.hostname || parsed.username || parsed.password) {
		throw new TypeError('Expected an okb:// endpoint without a fragment.')
	}
	const insecure = parsed.searchParams.getAll('insecure')
	if (insecure.length > 1) {
		throw new TypeError('Only one insecure parameter is allowed.')
	}
	const protocol = insecure[0] === 'true' ? 'http:' : 'https:'
	const endpoint = new URL(parsed.href.replace(/^okb:/, protocol))
	endpoint.searchParams.delete('insecure')
	return endpoint
}

HTTP batch RPC is the interoperability baseline and is sufficient for every bounded operation:

import { newHttpBatchRpcSession, type RpcStub } from 'capnweb'
import type {
	EditableKnowledgeBundle,
	KnowledgeBundle,
	ReadonlyKnowledgeBundle
} from '@open-knowledge/knowledge-bundle-api'

type RemoteBundle = RpcStub<KnowledgeBundle>
type RemoteReadonlyBundle = RpcStub<ReadonlyKnowledgeBundle>
type RemoteEditableBundle = RpcStub<EditableKnowledgeBundle>

const endpoint = capnWebEndpoint('okb://knowledge.example.test/bundles/main')
const request = new Request(endpoint, {
	redirect: 'error',
	signal: AbortSignal.timeout(15_000)
})
using bundle: RemoteBundle = newHttpBatchRpcSession<KnowledgeBundle>(request)
const info = await bundle.getInfo()

Use newHttpBatchRpcSession<ReadonlyKnowledgeBundle>() when the grant is known to be readonly and newHttpBatchRpcSession<EditableKnowledgeBundle>() when it is known to be editable. A client that discovers access through getInfo() starts a correctly typed session for subsequent calls rather than casting the common stub.

Servers may omit subscription support by implementing only KnowledgeBundle, ReadonlyKnowledgeBundle, or EditableKnowledgeBundle. A server which supports it additionally implements SubscribableKnowledgeBundle and clients use that extension as their typed session contract. Do not probe an ordinary Cap'n Web stub for an optional method: proxies accept every property name at runtime. A retained listener requires a persistent bidirectional transport such as WebSocket, and the server must duplicate a callback stub before retaining it and dispose that duplicate when the returned subscription closes. Short-lived HTTP batch clients refresh explicitly.

Paths are canonical, bundle-scoped absolute paths. They begin with /; / is the root; empty, . and .. segments are invalid. The TypeScript template type only checks the leading slash, so implementations must validate every untrusted path before resolving it. IDs and revisions are opaque and scoped to one bundle.

Every listing and mutation includes a path and may include the stable ID learned from an earlier result. When an ID is supplied, it is authoritative. The backend follows a relocated entry and returns its canonical current path; it never falls back to a different entry which has since occupied the stale path. An unresolved supplied ID fails even if the stale path now exists.

The read capability covers metadata, bounded recursive listing, bounded file reads, and optional change subscriptions. The editable capability adds file and directory creation, full file replacement, entry moves (including renames), and entry deletion. Revisions and content hashes are optional mutation preconditions; every supplied precondition must match.

Readonly and editable interfaces describe separate grants, but TypeScript types are not an authorization boundary. A readonly Cap'n Web grant must expose a target without public mutation methods, or the target must enforce authorization on every mutation call. Merely typing an editable target as ReadonlyKnowledgeBundle does not hide its methods from an untyped peer.

This package contains declarations only and has no runtime or transport dependency.