CodeVetter
← All unpacks
CodeVetter · Repo Unpack evidence

immerjs/immer

Scanned commit 061c2425e1 dated 2026-08-19 — last upstream commit. Generated by codevetter 1.15.0 on 2026-10-02.

github.com/immerjs/immer ↗ · 155 files · 1.6 MB

Immer Create the next immutable state tree by simply modifying the current tree Winner of the "Breakthrough of the year" React open source award and "Most impactful contribution" JavaScript open source award in 2019 Contribute using one-click online setup You

Deep analysis by cli:codex via the codex CLI on 2026-10-02 (342s) — every claim below links to its cited source files. Source inspection; upstream code and tests were not executed.

Overview

Immer is a JavaScript and TypeScript library that turns mutations inside a recipe callback into immutable state updates with structural sharing. It serves application developers using plain objects, arrays, and optionally Maps, Sets, or marked classes, including React and Redux state workflows. At commit 061c2425e1c9dff89e4e4189d42af1b7839dfe0a, its implementation combines revocable proxies, scope-owned finalization callbacks, optional patch generation, and an opt-in array-method interception plugin; separate packages provide documentation and performance tooling.

System map

The principal runtime is an in-process state transformation library whose public entrypoint is src/immer.ts. Core modules manage proxies, execution scopes, snapshots, and finalization, while three optional plugins supply collection, patch, and array-method behavior. Distribution includes multiple JavaScript module formats and declarations; documentation and benchmarking have separate manifests and execution boundaries.

Feature catalog

The user-facing surface is primarily a library API for creating and examining immutable updates. Recipes support direct and curried calls, explicit replacement, manual draft lifecycles, and optional reversible patches. Collection support, class draftability, type helpers, configurable copying, and array interception extend that surface, while the website explains their usage.

Data flow

Inputs enter as application-owned state and executable recipes, then become scope-owned drafts with lazily allocated copies. Writes record assignments and propagate modification flags toward parents; finalization substitutes ordinary values and preserves unchanged base references. Results and optional patch arrays leave through returns and listeners, with persistence delegated to the calling application in these inspected API paths.

Behavior traces

Source inspection followed ordinary production, manual drafting, and patch replay end-to-end, plus startup, snapshots, collections, and array reordering. These traces describe execution order and meaningful branches rather than observed runtime results. They show where drafts are created, how outputs are finalized, and when user callbacks execute.

Testing signals

Tests and CI were inspected, not executed; test existence is not a passing result. The inspected suite uses Vitest in Node, repeats core behavior across configuration combinations, and has a separate production-CJS test configuration. Coverage includes structural sharing, manual lifecycles, patch replay, collection behavior, and array regressions, but inspected scripts and configurations leave specific verification limits.

Risk map

These are source observations and maintenance risks, not confirmed vulnerabilities. Sensitive boundaries include executable recipes and accessors, externally supplied patch paths, documentation scripts, and release permissions. Core correctness depends on coupled scope, callback, and array-reference bookkeeping; the inspection is bounded and does not establish whole-repository security or test completeness.

Extension points

Extension mechanisms are concrete and mostly internal rather than a general third-party plugin API. The public library supports configurable instances and three enable functions, while internal typed interfaces connect implementations to scope behavior. Additional seams exist in draftable classes, producer abstractions, declaration mappings, packaging, documentation routing, and benchmark comparisons.

Contributor handoff

Begin with public exports and the scope/proxy/finalization chain, then inspect the plugin and tests relevant to the requested behavior. Tests and CI were inspected, not executed, and this bounded inventory supplies no passing result or measured speedup. Future implementation work should preserve the existing Yarn, formatting, packaging, and lifecycle conventions, with execution performed only under separate authorization.

Languages

LanguageFilesShare of source
Markdown54docs/config
TypeScript2953%
JavaScript2647%
JSON11docs/config
YAML6docs/config
HTML3docs/config
CSS1docs/config

Start reading here

Probable source entrypoint: src/ — inferred from the directory tree and manifest, not the upstream docs.

Source roots

src/ (18 files)

Source layout — src/

PathFiles
src/core/5
src/plugins/3
src/types/4
src/utils/4
src/immer.ts1
src/internal.ts1

Repository structure

Top-level pathFiles
website/57
__tests__/41
src/18
.github/8
perf-testing/7
__performance_tests__/6
_site/3
.codesandbox/1

Docs found: readme.md

Package

package.json — immer v10.0.3-beta, 23 declared dependencies.

@babel/core@types/node@vitest/coverage-v8coverallscpx2deep-freezeflow-binhuskyimmutableimport-sizelodashlodash.clonedeep

CI & config entrypoints

Structural health signals

Average score 8.5/10 across 48 analyzed source files; 2 hotspots surfaced.

These are deterministic review leads — size, churn, and structural signals — not proof of a bug in this project.

Recent history