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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@casterradev/differify

v1.0.1

Published

Differify allows you to get the diff between two entities (objects diff, arrays diff, date diff, functions diff, number diff, etc) very easily, quickly and in a friendly way. This fork adds the KeepKeys parameter allowing you to easily keep certain keys i

Downloads

2

Readme

Differify

One of the Fastest deep object/array diff

  • Benchmarks with other popular packages on the same category: (This benchmark is using the original repo Here)

    @netilon/differify x 1,045,377 ops/sec ±1.42% (93 runs sampled)

    deep-object-diff x 184,838 ops/sec ±2.55% (85 runs sampled)
    
    recursive-diff x 108,276 ops/sec ±1.93% (94 runs sampled)
    
    Fastest is @netilon/differify

What this fork adds?

  • KeepKeys - Allows you to keep certain keys in the returned object. Useful for database objects to keep the unique IDs, usernames, or emails to use in a find request then use the rest of the object for the update request.
  • isObjectValueEmpty(obj, keepKeys) - Tells you if the object is empty skipping over keepKeys.
  • Migrated from jest to vitest - Jest had a lot of config and ran slower. Vitest is faster & is a more streamlined, out-of-the-box testing package.
  • Fixed Typescript signature issues - When this was forked the original had issues with typescript class signatures and some type exports.

This fork was made to easily keep certain keys in an object AND get the differences/additions/deletions for use in updating databases using those kept keys. If you need a pure JS object difference tool. Check out the original repo Here

Whats new?

  • Completely rewritten
  • The new version 4.x is x2 faster than the older versions (version < 3.0.0) and is now one of the Fastests deep object/array comparators.
  • Typescript support added.
  • Support for Node.js and Browsers (it works on both)
  • Just 7.6K (gzipped 2K) weight (import)
  • No dependencies
  • New features were added! Now you can easily do more things with differify!
    • new config option added. Now, you can decide whether you prefer to compare arrays, either in an ordered or in an unordered way. Remember that, by default, you have an ordered comparison.
    • you can apply changes (merge) from left to right (applyRightChanges) or right to left (applyLeftChanges)
    • you can just keep the differences between two entities It's very useful indeed! (see more in the Documentation about the diffOnly option of apply[Right|Left]Changes methods).
    • you can filter the diff result of compare() method by an specific status (ADDED, MODIFIED, DELETED, EQUAL).

Synopsis

Differify allows you to get the diff between two entities (objects diff, arrays diff, date diff, functions diff, number diff, etc) very easily, quickly and in a friendly way.

Your contribution is appreciated (thanks!)

Donate to the original author here! Check out the original repo Here

alt text


Index

  1. Installation
  2. How to use
  3. Documentation
  4. Configuration
  5. Typescript
  6. Examples

Installation

npm install @casterradev/differify

How to use it

Comparing things with differify is very simple!

> Compare objects

const Differify = require('@casterradev/differify')

const differify = new Differify({mode: {object: 'DIFF', array: 'DIFF'}});

const A = {
    id: 1,
    role: 'developer',
    name: 'Person1',
    birthdate: 440305200000
}

const B = {
    id: 2,
    role: 'developer',
    name: 'Person2',
    birthdate: 533444400000
}

const diff = differify.compare(A,B);

> Object diff output

{
    "_": {
        "id": {
            "original": 1,
            "current" 2,
            "status": "MODIFED",
            "changes": 1
        },
        "role": {
            "original": "developer",
            "current" "developer",
            "status": "EQUAL",
            "changes": 0
        },
        "name": {
            "original": "Person1",
            "current" "Person2",
            "status": "MODIFIED",
            "changes": 1
        },
        "birthdate": {
            "original": 440305200000,
            "current" 533444400000,
            "status": "MODIFIED",
            "changes": 1
        },
    },
    "status": "MODIFIED",
    "changes": 3
}

> Easy access and use

const diff = differify.compare(A,B);

console.log(
    `Property name
     status is: ${diff._.name.status}
     prev value is: ${diff._.name.original}
     current value is: ${diff._.name.current}

// OUTPUT:
// Property name
// status is: MODIFIED
// prev value is: Person1
// current value is: Person2

> Compare arrays

const Differify = require('@casterradev/differify');

const differify = new Differify({mode: {object: 'DIFF', array: 'DIFF'}});

const A = [1, 2, 3];
const B = [1, 2, 4, 5];

const diff = differify.compare(A, B);

// OUTPUT
{
    "_": [
        {
            "original": 1,
            "current": 1,
            "status": "EQUAL",
            "changes": 0
        },
        {
            "original": 2,
            "current": 2,
            "status": "EQUAL",
            "changes": 0
        },
        {
            "original": 3,
            "current": 4,
            "status": "MODIFIED",
            "changes": 1
        },
        {
            "original": null,
            "current": 5,
            "status": "ADDED",
            "changes": 1
        },
    ],
    "status": "MODIFIED",
    "changes": 2

Simple Structure

As you can see, there are two different kinds of structures that you can get from compare method call.

  1. For objects and arrays only, you will get this structure:

         {
             "_": ...,
             "status": "MODIFIED",
             "changes": 3
         }
    • The _ property contains the detailed diff information (it's an underscore to improve the readability in complex nested objects property accesses)
    • The status property contains the global status of the comparison ('EQUAL', 'MODIFIED', 'DELETED', 'ADDED')
    • The changes property is the total changes found when the comparison was performed.
  2. For anything that Object.prototype.toString.call() does NOT return [object Array] or [object Object] (functions, dates, numbers, etc), you will get this structure:

         {
             "original": 1,
             "current": 2,
             "status": "MODIFIED",
             "changes": 1
         }
    • The original property has the original value (left parameter in compare method).
    • The current property has the current value (right parameter in compare method).
    • The status property contains the current status of the comparison ('EQUAL', 'MODIFIED', 'DELETED', 'ADDED')
    • The changes property will be 1 or 0 depending if there was a change or not.

> Apply changes

const differify = new Differify({mode: { object: 'DIFF', array: 'DIFF' }});

const A = {
    id: 1,
    role: ['developer', 'admin'],
    name: 'Person1',
    color: 'red',
    birthdate: 440305200000
    another: 'property from A'
}

const B = {
    id: 2,
    role: ['developer'],
    name: 'Person2',
    color: 'red',
    birthdate: 533444400000
}

const diff = differify.compare(A, B);
console.log(differify.applyRightChanges(diff));

/* OUTPUT:
{
    id: 2,
    role: ['developer', 'admin'],
    name: 'Person2',
    color: 'red',
    birthdate: 533444400000
    another: 'property from A'
}
*/

console.log(differify.applyLeftChanges(diff));

/* OUTPUT:
{
    id: 1,
    role: ['developer', 'admin'],
    name: 'Person1',
    color: 'red',
    birthdate: 440305200000
    another: 'property from A'
}
*/

console.log(differify.applyLeftChanges(diff, true));

/*
JUST the diff (note that there is NO color property and NO 'developer' role, because both properties has the same value in both entities.

OUTPUT:
{
    id: 1,
    role: ['admin'],
    name: 'Person1',
    birthdate: 440305200000
    another: 'property from A'
}
*/

Documentation

Methods

Method:

setConfig(object);

Description: It sets the configuration options that will be applied when compare() method is called.

Params:

Configuration Object (see the Configuration section).

Return: void


Method:

getConfig();

Description: It returns a copy of the current configuration object.

Return: Object


Method:

compare(any, any, keepKeys);

Description: It returns the difference between two entities.

Params:

Both parameters indicate the entities to be compared.

keepKeys?: string[] - Array of keep keys. Return object will mark these keys with status of 'KEPT'. If not given uses config.keepKeys. if config.keepKeys is not set uses empty array [].

Return: Object.


Method:

applyRightChanges(diffResult, diffOnly);

Description: It will apply the changes (merge both entities) and will keep the modified values from the right.

Params:

diffResult: Object - It is the Object returned by the compare() method call.

diffOnly: boolean - (default: false) It returns just the difference (only the !== EQUAL properties).

Return: Object.


Method:

applyLeftChanges(diffResult, diffOnly);

Description: It will apply the changes (merge both entities) and will keep the modified values from the left.

Params:

diffResult: Object - It is the Object returned by the compare() method call.

diffOnly: boolean - (default: false) It returns just the difference (only the !== EQUAL properties).

Return: Object.


Method:

filterDiffByStatus(diffResult, status, extendedInformation);

Description: It will return the changes that match the specified property status (second parameter) using the DIFF_MODES.DIFF in the configuration. IMPORTANT: If you use another diff mode (different than DIFF_MODES.DIFF), then you will get the corresponding value from original/current property (based on the status) without any filtering (you will get the raw value).

Params:

diffResult: Object - It is the Object returned by the compare() method call.

status: string - one of the following (ADDED || MODIFIED || DELETED || EQUAL || KEPT).

extendedInformation: boolean - if true, it will add more detail about the elements to the given output. Defaults to false.

Return: any || null - it depends on the input type. If there is no status matching, then null will be returned.


Method:

isObjectValuesEmpty(obj, keepKeys?);

Description: Tells if an object is empty not counting keepKeys keys.

Params:

obj: Object - Object to see if it's empty.

keepKeys?: string[] - Array of keep keys. If not given uses config.keepKeys. if config.keepKeys is not set uses empty array [].

Return: boolean - Returns true if empty. False if not empty.


Configuration

You can pass a config to the setConfig() method to change the behavior and adjust it to fit your needs. If you prefer, you can set it once and use it everywhere or you can change it when you need it.

| key | value | default | description | | ---------------------- | ------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | mode.array | string | DIFF | DIFF: it will iterate over each element in the array A, and will compare each element against the element in the same index in the array B.REFERENCE: just compare the references of each array.STRING: only will check the array length and will do a toString comparison if necessary. | | mode.object | string | DIFF | DIFF: it will iterate over each property in the object A and will compare each value with the same property value in the object B.REFERENCE: just compare the references of each object.STRING: only do a toString comparison. | | mode.function | string | REFERENCE | REFERENCE: just compare the references of each function.STRING: only do a toString comparison (useful to compare the function bodies). | | compareArraysInOrder | boolean | true | if it is true, it will compare each element in both arrays one by one in an ordered way, assuming that each element, in the same index in both arrays, should be the same element that can have changes or not (see an example of this case). If the option is set to false, then it will compare each element in both arrays and it will check if they are EQUAL, ADDED or DELETED without keeping in mind the appearence order (there won't be details about the MODIFIED status, it's only available if the option is set to true, since in that case, the order matters and we know that each element in the same index (but in different arrays), should be the same element that could have been changed or not) (see an example of this case). | | keepKeys | string[] | [] | Array of keys to keep. Useful for keeping database IDs. The differify.compare function also has a keepKeys parameter that will overwrite this setting.|

Configuration example:

const Differify = require('@casterradev/differify');

differify = new Differify({ mode: { object: 'DIFF', array: 'DIFF' } });

const diff = differify.compare(a, b);

if you dont specify any configuration, the default options are the following:

{
    mode: {
        array: 'DIFF',
        object: 'DIFF',
        function: 'REFERENCE',
    },
    compareArraysInOrder: true,
    keepKeys: []
}

Typescript

To use the differify library with Typescript, you have to configure your tsconfig.json file and enable the following properties:

tsconfig.json

{
	"compilerOptions": {
		"allowJs": true,
		"esModuleInterop": true,
	}
}

then in your .ts file, you can import Differify this way:

import Differify, { DIFF_MODES } from '@casterradev/differify';

// See the examples section.

Examples

You have to know that the configuration you provide will change the behavior of the comparators and it will result in different outputs.

Just play around with it and use the configuration that fits your needs.

The following image, just represents the idea of what each option does, but is not the real implementation:

Eg:

with the option DIFF:

const testA = [1,2];
const testB = [1,3];

you will get this output (note that there is a detail for each element in the array A and B):

{
	"_": [{
		"original": 1,
		"current": 1,
		"status": "EQUAL",
		"changes": 0
	}, {
		"original": 2,
		"current": 3,
		"status": "MODIFIED",
		"changes": 1
	}],
	"status": "MODIFIED",
	"changes": 1
}

with the option STRING or REFERENCE:

const testA = [1,2];
const testB = [1,3];

you will get this output (just a string comparison):

{
	"original": [1,2],
	"current": [1,3],
	"status": "MODIFIED",
	// always will be 1 or 0 because there is no
	// deep checking (use the DIFF option if you want more information)
	"changes": 1
}

Array comparison example, keeping the order (compareArraysInOrder: true)

const differify = new Differify({
	compareArraysInOrder: true, //default value
	mode: { object: 'DIFF', array: 'DIFF' },
});

const diff = differify.compare(['a', 'b'], ['a', 'z', 'b']);

/*
	OUTPUT

	{
		"_": [{
			"original": "a",
			"current": "a",
			"status": "EQUAL",
			"changes": 0
		}, {
			"original": "b",
			"current": "z",
			"status": "MODIFIED",
			"changes": 1
		}, {
			"original": null,
			"current": "b",
			"status": "ADDED",
			"changes": 1
		}],
		"status": "MODIFIED",
		"changes": 2
	}

*/

Array comparison example, without having the order in mind (compareArraysInOrder: false)..

NOTE: In case you have Object elements inside the array and you are using compareArraysInOrder to false and array mode to true, then it will compare the objects as serialized strings to know if they are equal or not.

const differify = new Differify({
	compareArraysInOrder: false,
	mode: { object: 'DIFF', array: 'DIFF' },
});

const diff = differify.compare(['a', 'b'], ['a', 'z', 'b']);

/*
	OUTPUT


	{
		"_": [{
			"original": "a",
			"current": "a",
			"status": "EQUAL",
			"changes": 0
		}, {
			"original": "b",
			"current": "b",
			"status": "EQUAL",
			"changes": 0
		}, {
			"original": null,
			"current": "z",
			"status": "ADDED",
			"changes": 1
		}],
		"status": "MODIFIED",
		"changes": 1
	}

*/

Your contribution is appreciated (thanks!)

Donate to the original author here! Check out the original repo Here

alt text