Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

leavify

ddeltree7MIT0.3.0TypeScript support: included

Helper functions for manipulating and tracking changes to object leaf values

object, leaves, leaf, path, value, path-value, change, difference, tree

readme

Leavify 🍃

A package that provides some helper functions for implementing leaf value changes and change tracking functionality to javascript objects, including arrays and classes.

Functionality includes

  • ☘️ Accessors for leaf values, including iteration
  • 🌿 IntelliSense for leaf paths
  • 🌳 Conversion of tree to/from leaves
  • 🍂 Proposing, saving and reverting changes
  • 🍁 Listing the changes, both as a list or as an object fragment

Installation

npm install leavify

Examples

Suppose we have the following interfaces:

interface Book {
  title: string;
  author: string;
  year: number;
  chapters: Chapter[];
}
interface Chapter {
  title: string;
  number: number;
}

const book: Book = {
  title: 'The Golden Compass',
  author: 'Philip Pullman',
  year: 1995,
  chapters: [{ title: 'The Decanter of Tokay', number: 1 }],
};

propose and save a list of entries

import changes from 'leavify/changes';

changes.propose(book, [
  ['author', 'Pullman'],
  ['chapters[0].number', 0],
]);
changes.save(book);

changes.getOriginal(book).chapters?.[0].number; // 1

iterate the leaf entries of an object

import { walkLeaves, toTree } from 'leavify';

for (const [path, value] of walkLeaves(book)) {
  console.log(path, value); // ['title', 'new title']
}

// Leaves to/from tree
const tree = toTree([...walkLeaves(book)]);

set up getter methods for a class

import changes from 'leavify/changes';

class Book {
  title = 'default title';
  get original() {
    return changes.getOriginal(this, 'original', 'proposed');
  }
  get proposed() {
    return changes.getProposed(this, 'original', 'proposed');
  }
}

const book = new Book();
changes.propose(book, [['title', 'new title']]);
changes.save(book);

book.title; // 'new title'
book.original.title; // 'default title'

API

Here's a brief description of each function defined:

get: get the leaf value of a given path
set: set the leaf value of a given path
has: truthy for a path that refers to a leaf value that exists

toTree: create a new object from a list of path-value entries
walkLeaves: iterate the path-value entries inside an object
findDifference: compare two objects and return the entries by which they differ

changes:
  propose: push a list of entries to change
  discard: delete the list of proposed entries
  save: apply the proposed entries in-place
  undo: propose a list of paths back to the original values, without applying
  isSaved: truthy when there are no proposed (unsaved) changes
  getOriginal: make an object from the original entries
  getProposed: make an object from the proposed entries
  getSavedEntries: list the applied entries - proposed and saved
  cloneDeepAsOriginal: clone deep and undo changes

changelog

Changelog

All notable changes to this project will be documented in this file. See standard-version for commit guidelines.

0.3.0 (2024-06-26)

⚠ BREAKING CHANGES

  • update package exports
  • make set() dyad
  • rewrite parsePath()

Features

  • add searchStore() to look inside the prototype chain (de951f8)
  • ignore circular references in walkLeaves (1b5cf9a)
  • include getSaved() (d1e4e02)
  • interpret path hints (6d04dd9)
  • refactor asOriginal() to leverage new store logic (5f0c207)
  • rewrite parsePath() (73e78c6)
  • store changes in the prototype (#18) (d52985d)

Bug Fixes

  • deps: tsd's weird requirement for an index.d.ts file (31f5c07)
  • empty indices test case (6573cec)
  • LeafPath: add workaround for interpolated suggestions (8394527), closes #12
  • LeafPath: arrays inside objects (9246802)
  • LeafPath: check circular ref after primitive check and before object check (9212462)
  • LeafPath: check readonly arrays (6051de2)
  • LeafPath: handle Record type inside object (ae6070c)
  • LeafPath: handle non as-const array in object or object in array (e8367dd)
  • LeafPath: make undefined have no effect on LeafPath (0c1c19b)
  • LeafPath: mixture of leaf and object values inside an array (d76eff1)
  • remove original entries when proposing back to original values (a57b7a7)
  • types: prevent ts errors in accessor functions (e21e453)
  • update save function (5320994)
  • walkLeaves: return instead of throwing error on circular reference (d6b1c35)

  • make set() dyad (dee1b09)

  • update package exports (64f1fad)