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

@ptolemy2002/immutability-utils

v2.1.0

Published

A TypeScript library that wraps mutable values and makes them immutable using proxies and cloning. This library allows you to work with classes designed with a mutable API while automatically maintaining immutability through copy-on-write semantics.

Readme

Immutability Utils

A TypeScript library that wraps mutable values and makes them immutable using proxies and cloning. This library allows you to work with classes designed with a mutable API while automatically maintaining immutability through copy-on-write semantics.

The library, for performance and simplicity purposes, assumes that any object with a callable clone method is one where that method takes exactly one optional parameter (the clone depth), returns the same type as the object itself, and does not perform any mutations on the original object. If these assumptions are not met, the library may not work correctly.

Type Reference

type CloneDepth = number | "max";
type WithCustomClone<T> = { clone(depth?: CloneDepth): T };
type ImmutableRef<T> = {
    readonly current: T, enabled: boolean, depth: CloneDepth, respectCustom: boolean,
    nonMutatingKeys: PropertyKey[],
    cloneListeners: Array<(imRef: ImmutableRef<T>) => void>
};

Functions

The following functions are exported by the library:

satisfiesDepth

function satisfiesDepth(depth: CloneDepth, value: number): boolean

A simple function that checks if a given value satisfies the specified clone depth. If the depth is less than 0, it will be clamped to 0. If the depth is "max", the function will always return true. Otherwise, it checks if the value is less than or equal to the depth.

Parameters

  • depth (CloneDepth): The clone depth to check against.
  • value (number): The value to check against the clone depth.

depthIncrement

function depthIncrement(depth: CloneDepth, value: number = 1): CloneDepth

Increments the given clone depth by the specified value. If the depth is "max", it will remain "max". If the resulting depth is less than 0, it will be clamped to 0.

Parameters

  • depth (CloneDepth): The current clone depth.
  • value (number, optional): The value to increment the depth by. Defaults to 1.

depthDecrement

function depthDecrement(depth: CloneDepth, value: number = 1): CloneDepth

Decrements the given clone depth by the specified value. If the depth is "max", it will remain "max". If the resulting depth is less than 0, it will be clamped to 0.

Parameters

  • depth (CloneDepth): The current clone depth.
  • value (number, optional): The value to decrement the depth by. Defaults to 1.

extClone

function extClone<T>(value: T, depth: CloneDepth = "max", respectCustom = true): T

Extends the two lodash cloning functions by adding support for custom clone methods and clone depth. If the value has a callable clone method and respectCustom is true, it will use that method to clone the value. Otherwise, it will use lodash.clone directly if the depth is 0, lodash.clonedeep if the depth is "max", or repeated lodash.clone calls if the depth is a positive number.

Parameters

  • value (T): The value to clone.
  • depth (CloneDepth, optional): The depth to clone. Defaults to "max".
  • respectCustom (boolean, optional): Whether to respect custom clone methods. Defaults to true.

isGetter

function isGetter(target: unknown, prop: PropertyKey): boolean

Checks if the given property is a getter on the target object. Used internally to determine if a property access could potentially mutate the object.

Parameters

  • target (unknown): The object to check for the getter property.
  • prop (PropertyKey): The property key to check.

immutableMut

function immutableMut<T>(value: T, cb: (v: T) => void, respectCustom = true): T

A utility function that allows you to perform mutations on a value while maintaining immutability. It clones the value, passes the clone to the provided callback for mutation, and then returns the mutated clone.

Parameters

  • value (T): The value to clone and mutate.
  • cb ((v: T) => void): A callback function that receives the cloned value for mutation.
  • respectCustom (boolean, optional): Whether to respect custom clone methods. Defaults to true.

immutable

function immutable<T extends object>(
    obj: T, depth: CloneDepth = "max",
    nonMutatingKeys: PropertyKey[] = [],
    respectCustom=true
): ImmutableRef<T>

Wraps the given object in a proxy that enforces immutability by cloning the object whenever a mutation is expected. That is:

  • Whenever a property is set, if the reference is enabled, the object will be cloned, the property will be set on the clone, and ref.current will be updated to the clone.
  • Whenever a property is accessed, if the reference is enabled, the property is not in the nonMutatingKeys list (or is not clone), and the property is a getter, the object will be cloned and ref.current will be updated to the clone.
  • Whenever a property is accessed, if the reference is enabled, the property is not in the nonMutatingKeys list (or is not clone), and the property value is a function, the function will be wrapped in another function that clones the object and updates ref.current to the clone before making the call with the same arguments.

Note that the reference will be disabled during the execution of any getter, setter, or function call, so the reference to this remains correct for the duration of that operation and any mutations that occur during that operation will be batched.

After any operation is done, all listeners in ref.cloneListeners will be called with the reference as an argument, so you can subscribe to changes by adding a listener to that array.

Parameters

  • obj (T): The initial object to wrap in the immutable proxy.
  • depth (CloneDepth, optional): The initial clone depth to use for the reference. Defaults to "max".
  • respectCustom (boolean, optional): The initial value for whether to respect custom clone methods. Defaults to true.
  • nonMutatingKeys (PropertyKey[], optional): An initial array of property keys that should be considered non-mutating, meaning that accessing them will not trigger cloning. Defaults to an empty array. Note that the clone property is always considered non-mutating regardless of whether it is included in this array or not.

All of these parameters (except for obj) are also mutable properties of the returned reference, so you can change them at any time after the fact.

Peer Dependencies

  • is-callable: ^1.2.7
  • lodash.clone: ^4.5.0
  • lodash.clonedeep: ^4.5.0

Commands

The following commands exist in the project:

  • npm run uninstall - Uninstalls all dependencies for the library
  • npm run reinstall - Uninstalls and then Reinstalls all dependencies for the library
  • npm run example-uninstall - Uninstalls all dependencies for the example app
  • npm run example-install - Installs all dependencies for the example app
  • npm run example-reinstall - Uninstalls and then Reinstalls all dependencies for the example app
  • npm run example-start - Starts the example app after building the library
  • npm run build - Builds the library
  • npm run release - Publishes the library to npm without changing the version
  • npm run release-patch - Publishes the library to npm with a patch version bump
  • npm run release-minor - Publishes the library to npm with a minor version bump
  • npm run release-major - Publishes the library to npm with a major version bump