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

@laioutr/valtio-json-patch

v0.1.1

Published

Convert valtio proxy operations to RFC 6902 JSON Patch

Readme

@laioutr/valtio-json-patch

Convert valtio state changes to RFC 6902 JSON Patch operations.

When you mutate a valtio proxy, valtio tracks exactly which properties changed. This package turns those changes into standard JSON Patch operations (add, remove, replace, move), so you can send them over the wire and feed them into any system that speaks JSON Patch.

Install

pnpm add @laioutr/valtio-json-patch

Usage

import { proxy } from 'valtio/vanilla';
import { subscribeWithPatches } from '@laioutr/valtio-json-patch';

const state = proxy({
  user: { name: 'Alice', role: 'admin' },
  items: ['a', 'b'],
});

const unsubscribe = subscribeWithPatches(state, (patches) => {
  console.log(patches);
});

state.user.name = 'Bob';
// [{ op: 'replace', path: '/user/name', value: 'Bob' }]

state.items.push('c');
// [{ op: 'add', path: '/items/2', value: 'c' }]

state.items.splice(0, 1);
// [{ op: 'remove', path: '/items/0' }]

API

subscribeWithPatches(proxy, callback, options?)

Subscribe to a valtio proxy and receive JSON Patch arrays on every change. Returns an unsubscribe function.

const unsubscribe = subscribeWithPatches(
  state,
  (patches) => {
    // patches is an Operation[] with one or more JSON Patch operations
  },
  {
    notifyInSync: false, // default
  }
);

Options:

  • notifyInSync (default: false): By default, valtio batches rapid mutations and delivers them together in one callback (via microtask). Set to true to receive each mutation immediately as it happens. See Batching and notifyInSync for trade-offs.

opsToJsonPatch(ops)

Convert an array of valtio change tuples to JSON Patch operations. This is the core conversion function with zero dependencies.

Mapping rules:

| Change | Condition | JSON Patch | | ---------------- | ---------------------------------------- | ---------- | | Property set | Old value was undefined (new property) | add | | Property set | Old value existed (update) | replace | | Property deleted | | remove | | Delete + set | Same object reference in both | move |

Array support: Array mutations (push, pop, shift, unshift, splice) are automatically coalesced from valtio's low-level per-index changes into the correct JSON Patch operations.

pathToPointer(path)

Convert a property path array to an RFC 6901 JSON Pointer string. Useful if you need to build pointers from valtio paths outside of opsToJsonPatch.

import { pathToPointer } from '@laioutr/valtio-json-patch';

pathToPointer(['pages', 'p1', 'title']);
// '/pages/p1/title'

pathToPointer(['keys/with/slashes', 'tildes~here']);
// '/keys~1with~1slashes/tildes~0here'

Batching and notifyInSync

By default, valtio collects all synchronous mutations and delivers them as a single batch (via microtask). This is the recommended mode because:

  • Move detection requires the delete and set to arrive in the same batch.
  • Array coalescing requires all ops from a single array method (e.g., splice emits multiple internal changes) to arrive together.
  • Fewer callbacks means less overhead when mutations happen in rapid succession.

Setting notifyInSync: true delivers each mutation immediately as a separate callback. This is useful when you need synchronous patch delivery, but patches will be more granular: moves become separate remove + add, and array methods may produce multiple patches instead of single operations.

Limitations

sort() and reverse() produce per-index replace ops. Technically we can't identify these from the raw valtio ops. The patches are correct but verbose.

add vs replace distinction relies on whether the old value was undefined. If a property is explicitly set to undefined and later reassigned, the package emits add instead of replace. In practice, this is fine, as most JSON Patch libraries treat add on an existing object key the same as replace.

License

MIT