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

dsh-patchouli-protocol

v0.1.8

Published

Harness-neutral JSON-RPC contracts for Patchouli storage

Readme

Patchouli Protocol

This package defines the harness-neutral JSON-RPC contract between Patchouli clients and the database backend. Entity kinds such as knowledge, relations, or future records are values of the generic type parameter; they do not create separate RPC method families.

This TypeScript package is the client-side binding. The database backend is implemented in Rust under crates/backend.

The language-neutral source of truth is openrpc.json. Exact transaction, idempotency, consistency, error, and subscription behavior is defined in SPEC.md. TypeScript and Rust tests check their method identities against the OpenRPC document.

Scope

Version 1 contains:

  • generic entity create, read, retrieve, update, and delete methods;
  • chunked upload and download for backend-managed Artifact bytes;
  • an open meta envelope plus strict CRUD business data;
  • configuration-selected preconditions, consistency, causal metadata, and an optional conflict-strategy request;
  • resumable change subscriptions through opaque cursors;
  • cluster and node identity in the connection handshake.

The generic OpenRPC methods do not specialize entity payloads. This package also publishes the optional, harness-neutral ArtifactValue, KnowledgeValue, and KnowledgeRelationValue bindings plus their versioned JSON Schemas. Storage tables, replication, conflict-resolution algorithms, and Harness bindings stay outside the wire contract.

Methods

patchouli.protocol.handshake@1
patchouli.control.status@1
patchouli.control.checkpoint@1
patchouli.control.shutdown@1
patchouli.artifact.upload.begin@1
patchouli.artifact.upload.chunk@1
patchouli.artifact.upload.commit@1
patchouli.artifact.download.chunk@1
patchouli.entity.create@1
patchouli.entity.read@1
patchouli.entity.retrieve@1
patchouli.entity.update@1
patchouli.entity.delete@1
patchouli.changes.subscribe@1
patchouli.changes.unsubscribe@1
patchouli.changes.event@1

Mutations are JSON-RPC requests and always receive a response. The change event is a server notification and has no JSON-RPC id.

Except for the protocol handshake, every method uses params: { meta, data } and every successful result uses { meta, data }. data contains only the method's business fields. meta is an open JSON object whose recognized fields are selected by backend configuration.

meta.deadline_unix_ms is reserved by the protocol as an optional unsigned Unix-millisecond acceptance deadline. Expiry before a database acceptance commit returns DEADLINE_EXCEEDED and rolls the operation back. Version 1 does not support request cancellation.

Each create, update, or delete is accepted atomically by the Rust backend controller. Configuration determines whether the accepted version is published immediately or as part of a logical batch. Only published versions produce change notifications.

Artifact upload is a three-step operation: begin, send ordered chunks, then commit. Commit publishes bytes to the backend-managed content-addressed store and creates the corresponding artifact entity through the same configured controller path as generic CRUD. Download first reads that entity in the caller's configured scope, then returns only bytes owned by the serving node. External indexed Artifacts remain generic entities and are read through their declared source provider.

Generic entities

An adapter supplies its own entity type and JSON payload vocabulary:

type EntityType = 'artifact' | 'knowledge' | 'knowledge_relation'
type EntityValue = ArtifactValue | KnowledgeValue | KnowledgeRelationValue
type Contract = PatchouliProtocol<EntityType, EntityValue>

The protocol treats type as an opaque string. Authorization and schema validation belong to the backend configuration for that type.

Named identity fields and mixed consistency rules also belong to backend configuration. See backend configuration. The frontend plugin does not evaluate these rules or maintain transaction state.

Concurrency

Every stored version is an opaque string. A deployment may configure a metadata field containing the versions on which an update or delete is based. A single-primary backend normally expects one base version; a multi-node backend may accept several heads without changing the CRUD data schema.

Clients must not parse version or causal tokens. When configured, causal input and output live in meta alongside channel, transaction, plugin-route, and other deployment-specific identities. The controller retains causal progress for configured identities; CRUD requests do not select a consistency mode. A configured metadata field may request merge, mvcc, or reject conflict handling. Its absence uses the backend-configured default.

Reactive delivery

Subscriptions deliver ordered, at-least-once change notifications. The cursor is the replay position and is distinct from the causal token. Clients dedupe by cursor, persist the last applied cursor, and pass it as after_cursor after a reconnect.

The server may reject a cursor outside its retention window with CURSOR_EXPIRED. Disconnecting removes the connection-local subscription but does not invalidate the cursor.

Transport binding

The first binding is a UTF-8 NDJSON stream over local IPC. macOS and Linux use a Unix domain socket; Windows uses a named pipe. One line contains one complete JSON-RPC object. The same connection carries responses and server notifications. Batch requests are not part of protocol version 1.