Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

human-object-diff

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

human-object-diff

Human Readable Difference Between Two Objects

  • 3.0.0
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
2K
decreased by-16.92%
Maintainers
1
Weekly downloads
 
Created
Source

human-object-diff

build status code coverage code style styled with prettier made with lass license npm downloads

Configurable Human Readable Difference Between Two Plain Objects

Table of Contents

Install

npm:

npm install human-object-diff

yarn:

yarn add human-object-diff

Usage

Common JS

const HumanDiff = require('human-object-diff')

const lhs = { foo: 'bar' }
const rhs = { foo: 'baz' }
const options = {}

const { diff } = new HumanDiff(options)

console.log(diff(lhs, rhs))
// -> ['"Foo", with a value of "bar" (at Obj.foo) was changed to "baz"']

Options

human-object-diff supports a variety of options to allow you to take control over the output of your object diff.

OptionTypeDefaultDescription
objectNameString'Obj'This is the object name when presented in the path. ie... "Obj.foo" ignored if hidePath is true
prefilter[String]FuncSee prefiltering
dateFormatString'MM/dd/yyyy hh:mm a'dateFns format string, see below
ignoreArraysBoolfalseIf array differences aren't needed, set to true and skip processing
templatesObjectsee templatesCompletely customize the output
sensitivePaths[String]Paths that will use the sensitive field templates if they are defined, use [] as any index

Custom Templates

human-object-dff let's you fully customize your sentences by allowing you to pass custom sentence templates.

The default template looks like the following:

const templates = {
  N: '"FIELD", with a value of "NEWVALUE" (at DOTPATH) was added',
  D: '"FIELD", with a value of "OLDVALUE" (at DOTPATH) was removed',
  E: '"FIELD", with a value of "OLDVALUE" (at DOTPATH) was changed to "NEWVALUE"',
  I: 'Array "FIELD" (at DOTPATH), had a value of "NEWVALUE" inserted at index INDEX',
  R: 'Array "FIELD" (at DOTPATH), had a value of "OLDVALUE" removed at index INDEX',
  AE: 'Array "FIELD" (at DOTPATH), had a value of "OLDVALUE" changed to "NEWVALUE" at index INDEX',
  NS: '"FIELD" (at DOTPATH) was added',
  DS: '"FIELD" (at DOTPATH) was removed',
  ES: '"FIELD" (at DOTPATH) was changed',
  IS: 'Array "FIELD" (at DOTPATH), had a value inserted at index INDEX',
  RS: 'Array "FIELD" (at DOTPATH), had a value removed at index INDEX',
  AES: 'Array "FIELD" (at DOTPATH), had a value changed at index INDEX',
}

Where N is a new key, D is a deleted key, E is an edited key, I is an inserted array value, R is a removed array value, and AE is an edited array property.

We also expose a sensitiveFields array option which will cause a path to use the S option template.

You can define each sentence in the templates to be whatever you'd like. The following tokens can be used to replace their diff values in the final output.

The available tokens that can plug in to your sentence templates are FIELD, DOTPATH,NEWVALUE,OLDVALUE, INDEX, POSITION. Position is just index+1. Be aware that not all sentence types will have values for each token. For instance, non-array changes will not have a position or an index.

Support for Dates

human-object-diff uses date-fns format function under the hood to show human readable date differences. We also supply a dateFormat option where you can supply your own date formatting string. Please note, that date-fns format strings are different from moment.js format strings. Please refer to the documentation here and here

Prefiltering

There may be some paths in your object diffs that you'd like to ignore. You can do that with prefiltering. As a convenience, you can add this option as an array of strings, which are the keys of the root paths of the objects.

for instance

const lhs = { foo: 'bar', biz: { foo: 'baz' } }
const rhs = { foo: 'bar', biz: { foo: 'buzz' } }

const { diff } = new HumanDiff({ prefilter: ['foo'] })

diff(lhs, rhs)

You would still see the diffs for biz.foo but you would ignore the diff for foo.

You can also pass a function for this option which will be directly passed to the underlying diff library.

The prefilter function takes a signature of function(path, key). Here path is an array that represents the path leading up to the object property. The key is the key, or what would be the final element of the path. The function returns true for any paths you would want to ignore.

For instance, in the object below:

const obj = { foo: { bar: [1, 2, { baz: 'buzz' }] } }

The path and key for foo would be path [] and key 'foo'.

The path and key for foo.bar would be path ['foo'] key 'bar'

for foo.bar[2].baz it would be path: ['foo', 'bar', 2] and key 'baz'

To ignore changes in foo.bar you could pass a functions like

const prefilter = (path, key) => path[0] === 'foo' && key === 'bar'

A Note On Arrays

**There are known bug related to arrays of objects. We plan to release different array processing algorithms in the future that can handle more complex objects. As of the latest version it is reccomended to only diff between flat arrays of strings and numbers. Otherwise there isn't guarantee of accuracy or if diffs won't be duplicated in some ways.

human-object-diff parses arrays in an opinionated way. It does it's best to resolve Arrays into groups of insertions and removals. Typical diff libraries look at arrays on an element by element basis and emit a difference for every changes element. While this is benefical for many programatic tasks, humans typically don't look at arrays in the same way. human-object-diff attempts to reduce array changes to a number of insertions, removals, and edits. An example can better describe the difference.

const lhs = [1, 2, 3, 4]
const rhs = [0, 1, 2, 3, 4]

Consider the above arrays and their differences. A typical array diff would behave like this and output something like the following.

  1. A change at index 0 from 1 to 0
  2. A change at index 1 from 2 to 1
  3. A change at index 2 from 3 to 2
  4. A change at index 3 from 4 to 3
  5. An addition of 4 at index 4

human-object-diff attempts to reduce these differences to something like the following.

  1. An insertion of 0 at index 0. ("Array 'lhs' had a value of 0 inserted at index 0")

This is much more understandable to a human brain. We've simply inserted a number at an index.

Diff Memory

The diff engine object created when new HumanDiff() is invoked contains a sentences property which you can use to recall the last diff that was computed.

const diffEngine = new HumanDiff()
diffEngine.diff(lhs, rhs)

diffEngine.sentences // -> same as the output of the last diff

Contributors

NameWebsite
Spencer Snyderhttps://spencersnyder.io/

License

MIT © Spencer Snyder

Real world example I selected open source package and decided to add dual support for it.

Keywords

FAQs

Package last updated on 27 Mar 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc