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

@sylphx/zen-craft

v5.0.35

Published

Craft immutable state updates with JSON Patches for Zen

Readme

@sylphx/zen-craft

npm version

Craft-powered immutable state updates for Zen - Built with Craft, our high-performance immer replacement.

This package allows you to work with immutable state in Zen atoms using a convenient mutation-style API on draft objects, while automatically producing the next immutable state with structural sharing and optional JSON patch generation.

Installation

# Using bun (recommended)
bun add @sylphx/zen-craft @sylphx/zen

# Using npm
npm install @sylphx/zen-craft @sylphx/zen

# Using pnpm
pnpm add @sylphx/zen-craft @sylphx/zen

# Using yarn
yarn add @sylphx/zen-craft @sylphx/zen

Usage

craftZen()

The main API for Zen integration. Updates a Zen atom immutably using a recipe function.

import { craftZen } from '@sylphx/zen-craft';
import { zen, get } from '@sylphx/zen';

const myStore = zen({
  user: { name: 'Alice', age: 30 },
  tags: ['a', 'b']
});

// Basic usage - update atom with draft mutations
craftZen(myStore, (draft) => {
  draft.user.age++;
  draft.tags.push('c');
});

console.log(get(myStore));
// Output: { user: { name: 'Alice', age: 31 }, tags: ['a', 'b', 'c'] }

// Advanced: Enable patch generation for undo/redo support
const [patches, inversePatches] = craftZen(
  myStore,
  (draft) => {
    draft.user.age++;
  },
  { patches: true, inversePatches: true }
);

console.log(patches);
// Output: [{ op: 'replace', path: ['user', 'age'], value: 32 }]

produce()

Low-level API for non-Zen use cases. Takes a base state and recipe function, returns new state with patches.

import { produce } from '@sylphx/zen-craft';

const currentState = {
  user: { name: 'Alice', age: 30 },
  tags: ['a', 'b']
};

const [nextState, patches, inversePatches] = produce(
  currentState,
  (draft) => {
    draft.user.age++;
    draft.tags.push('c');
  },
  { patches: true, inversePatches: true }
);

console.log(nextState);
// Output: { user: { name: 'Alice', age: 31 }, tags: ['a', 'b', 'c'] }

applyPatches()

Apply JSON patches to a base state to produce a new state.

import { applyPatches } from '@sylphx/zen-craft';

const baseState = { user: { name: 'Alice' } };
const patches = [
  { op: 'replace', path: ['user', 'name'], value: 'Bob' },
  { op: 'add', path: ['user', 'age'], value: 40 },
];

const nextState = applyPatches(baseState, patches);

console.log(nextState);
// Output: { user: { name: 'Bob', age: 40 } }

nothing

Use the nothing symbol to delete properties:

import { craftZen, nothing } from '@sylphx/zen-craft';
import { zen } from '@sylphx/zen';

const store = zen({ name: 'Alice', age: 30 });

craftZen(store, (draft) => {
  draft.age = nothing; // Delete age property
});

// Result: { name: 'Alice' }

Features

  • 🚀 1.4-35x faster than immer - Powered by Craft
  • 🎯 Structural sharing - Unchanged parts maintain references
  • 📝 JSON Patches (RFC 6902) - Track changes for undo/redo
  • 🗺️ Map/Set support - Full support for ES6 collections
  • Zero dependencies - Except Craft and Zen
  • 🔒 Type-safe - Full TypeScript support

Why Craft?

zen-craft is powered by Craft, our in-house high-performance immer replacement:

  • 1.4-35x faster than immer across all operations
  • 2.9 KB gzipped - 39% smaller than immer
  • 100% API compatible - Drop-in replacement
  • Built by us - Same team, same performance obsession

Learn more about Craft →

License

MIT