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

tree-changes

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tree-changes - npm Package Compare versions

Comparing version 0.5.0 to 0.5.1

lib/index.js.map

16

lib/index.d.ts

@@ -1,14 +0,14 @@

interface IObject {
interface IPlainObject {
[key: string]: any;
}
export declare type TypeInput = string | boolean | number | string[] | boolean[] | number[] | IObject;
export declare type IData = IObject | IObject[];
export declare type TypeInput = string | boolean | number | IPlainObject | Array<string | boolean | number | IPlainObject>;
export declare type IData = IPlainObject | IPlainObject[];
export interface ITreeChanges {
changed: (key?: string) => boolean;
changedFrom: (key: string, previous: TypeInput, actual?: TypeInput) => boolean;
changedTo: (key: string, actual: TypeInput) => boolean;
increased: (key: string) => boolean;
decreased: (key: string) => boolean;
changed: (key?: string | number) => boolean;
changedFrom: (key: string | number, previous: TypeInput, actual?: TypeInput) => boolean;
changedTo: (key: string | number, actual: TypeInput) => boolean;
increased: (key: string | number) => boolean;
decreased: (key: string | number) => boolean;
}
export default function treeChanges(data: IData, nextData: IData): ITreeChanges;
export {};
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var deep_diff_1 = __importDefault(require("deep-diff"));
var nested_property_1 = __importDefault(require("nested-property"));
var deep_diff_1 = require("deep-diff");
// @ts-ignore
var nested_property_1 = require("nested-property");
function isPlainObj() {

@@ -18,4 +16,4 @@ var args = [];

var prototype = Object.getPrototypeOf(d);
return Object.prototype.toString.call(d)
.slice(8, -1) === 'Object' && (prototype === null || prototype === Object.getPrototypeOf({}));
return (Object.prototype.toString.call(d).slice(8, -1) === 'Object' &&
(prototype === null || prototype === Object.getPrototypeOf({})));
});

@@ -28,3 +26,3 @@ }

}
return args.every(function (d) { return Array.isArray(d); });
return args.every(Array.isArray);
}

@@ -44,7 +42,6 @@ function isNumber() {

changed: function (key) {
var left = nested_property_1.default.get(data, key);
var right = nested_property_1.default.get(nextData, key);
if ((isArray(left, right)) || (isPlainObj(left, right))) {
var diff = deep_diff_1.default.diff(left, right);
return !!diff;
var left = nested_property_1.get(data, key);
var right = nested_property_1.get(nextData, key);
if (isArray(left, right) || isPlainObj(left, right)) {
return !!deep_diff_1.diff(left, right);
}

@@ -54,9 +51,11 @@ return left !== right;

changedFrom: function (key, previous, actual) {
if (!key) {
if (typeof key === 'undefined') {
throw new Error('Key parameter is required');
}
var useActual = typeof previous !== 'undefined' && typeof actual !== 'undefined';
var left = nested_property_1.default.get(data, key);
var right = nested_property_1.default.get(nextData, key);
var leftComparator = Array.isArray(previous) ? previous.indexOf(left) >= 0 : left === previous;
var left = nested_property_1.get(data, key);
var right = nested_property_1.get(nextData, key);
var leftComparator = Array.isArray(previous)
? previous.indexOf(left) >= 0
: left === previous;
var rightComparator = Array.isArray(actual) ? actual.indexOf(right) >= 0 : right === actual;

@@ -66,7 +65,7 @@ return leftComparator && (useActual ? rightComparator : !useActual);

changedTo: function (key, actual) {
if (!key) {
if (typeof key === 'undefined') {
throw new Error('Key parameter is required');
}
var left = nested_property_1.default.get(data, key);
var right = nested_property_1.default.get(nextData, key);
var left = nested_property_1.get(data, key);
var right = nested_property_1.get(nextData, key);
var leftComparator = Array.isArray(actual) ? actual.indexOf(left) < 0 : left !== actual;

@@ -77,12 +76,14 @@ var rightComparator = Array.isArray(actual) ? actual.indexOf(right) >= 0 : right === actual;

increased: function (key) {
if (!key) {
if (typeof key === 'undefined') {
throw new Error('Key parameter is required');
}
return isNumber(nested_property_1.default.get(data, key), nested_property_1.default.get(nextData, key)) && nested_property_1.default.get(data, key) < nested_property_1.default.get(nextData, key);
return (isNumber(nested_property_1.get(data, key), nested_property_1.get(nextData, key)) &&
nested_property_1.get(data, key) < nested_property_1.get(nextData, key));
},
decreased: function (key) {
if (!key) {
if (typeof key === 'undefined') {
throw new Error('Key parameter is required');
}
return isNumber(nested_property_1.default.get(data, key), nested_property_1.default.get(nextData, key)) && nested_property_1.default.get(data, key) > nested_property_1.default.get(nextData, key);
return (isNumber(nested_property_1.get(data, key), nested_property_1.get(nextData, key)) &&
nested_property_1.get(data, key) > nested_property_1.get(nextData, key));
},

@@ -92,1 +93,2 @@ };

exports.default = treeChanges;
//# sourceMappingURL=index.js.map
{
"name": "tree-changes",
"version": "0.5.0",
"version": "0.5.1",
"description": "Helpers function to get tree changes between two datasets",

@@ -30,11 +30,15 @@ "author": "Gil Barbara <gilbarbara@gmail.com>",

"devDependencies": {
"@gilbarbara/tsconfig": "^0.1.0",
"@size-limit/preset-small-lib": "^2.1.0",
"@types/deep-diff": "^1.0.0",
"@types/jest": "^24.0.15",
"@types/node": "^12.6.3",
"bundlesize": "^0.18.0",
"@types/jest": "^24.0.17",
"@types/node": "^12.7.2",
"chalk": "^2.4.2",
"cross-env": "^5.2.0",
"husky": "^3.0.0",
"jest": "^24.8.0",
"rimraf": "^2.6.3",
"husky": "^3.0.4",
"jest": "^24.9.0",
"prettier": "^1.18.2",
"repo-tools": "^0.2.0",
"rimraf": "^3.0.0",
"size-limit": "^2.1.0",
"ts-jest": "^24.0.2",

@@ -52,12 +56,21 @@ "tslint": "^5.18.0",

"lint": "tslint -p tsconfig.json",
"test": "jest --coverage",
"test": "jest",
"test:coverage": "jest --coverage",
"test:watch": "jest --watch --verbose",
"bundlesize": "bundlesize",
"validate": "npm run lint && npm test && npm run build && bundlesize",
"format": "prettier \"**/*.{js,jsx,json,yml,yaml,css,less,scss,ts,tsx,md,graphql,mdx}\" --write",
"validate": "npm run lint && npm run test:coverage && npm run size",
"size": "npm run build && size-limit",
"prepublishOnly": "npm run validate"
},
"bundlesize": [
"prettier": {
"trailingComma": "all",
"singleQuote": true,
"arrowParens": "avoid",
"printWidth": 100,
"proseWrap": "never"
},
"size-limit": [
{
"path": "./lib/index.js",
"maxSize": "1 kB"
"limit": "3 kB"
}

@@ -67,5 +80,6 @@ ],

"hooks": {
"pre-commit": "npm run validate"
"pre-commit": "repo-tools check-remote && npm run validate",
"post-merge": "repo-tools install-packages"
}
}
}
tree-changes
===
[![NPM version](https://badge.fury.io/js/tree-changes.svg)](https://www.npmjs.com/package/tree-changes)
[![build status](https://travis-ci.org/gilbarbara/tree-changes.svg)](https://travis-ci.org/gilbarbara/tree-changes)
[![Maintainability](https://api.codeclimate.com/v1/badges/93528e49029782f5f7d2/maintainability)](https://codeclimate.com/github/gilbarbara/tree-changes/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/93528e49029782f5f7d2/test_coverage)](https://codeclimate.com/github/gilbarbara/tree-changes/test_coverage)
[![NPM version](https://badge.fury.io/js/tree-changes.svg)](https://www.npmjs.com/package/tree-changes) [![build status](https://travis-ci.org/gilbarbara/tree-changes.svg)](https://travis-ci.org/gilbarbara/tree-changes) [![Maintainability](https://api.codeclimate.com/v1/badges/93528e49029782f5f7d2/maintainability)](https://codeclimate.com/github/gilbarbara/tree-changes/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/93528e49029782f5f7d2/test_coverage)](https://codeclimate.com/github/gilbarbara/tree-changes/test_coverage)
Get changes between two versions of the same object.
A good use for this is in [React](https://reactjs.org/) lifecycle methods, like `componentWillReceiveProps` or `componentDidUpdate`.
Get changes between two versions of data with similar shape.
### Setup
## Setup

@@ -18,3 +14,3 @@ ```bash

### Usage
## Usage

@@ -24,25 +20,37 @@ ```js

const A = {
status: 'idle',
const savedData = {
data: { a: 1 },
hasData: false,
data: { a: 1 },
items: [{ name: 'test' }],
ratio: 0.45,
ratio: 0.9,
retries: 0,
sort: {
data: [{ type: 'asc' }, { type: 'desc' }],
status: 'idle',
},
switch: false,
};
const B = {
status: 'done',
const newData = {
data: { a: 1 },
hasData: true,
data: { a: 1 },
items: [],
ratio: 0.4,
ratio: 0.5,
retries: 1,
sort: {
data: [{ type: 'desc' }, { type: 'asc' }],
status: 'success',
},
};
const { changed, changedFrom, changedTo, increased, decreased } = treeChanges(objA, objB);
const {
changed,
changedFrom,
changedTo,
increased,
decreased,
} = treeChanges(savedData, newData);
if (changed('status')) {
// do something
if (changed('hasData')) {
// execute some side-effect
}

@@ -55,7 +63,16 @@

// works with array values too
if (changedFrom('status', 'idle', ['done', 'ready']) {
if (changedFrom('sort.status', 'idle', ['done', 'success']) {
// status has changed!
}
// support nested match
if (changedTo('sort.data.0.type', 'desc') {
// update the type
}
if (decreased('ratio')) {
// do something!
}
if (increased('retries')) {
// hey, slow down.

@@ -65,3 +82,3 @@ }

### With React
#### Works with arrays too.

@@ -71,2 +88,19 @@ ```js

const { changed, changedTo } = treeChanges([0, { id: 2 }], [0, { id: 4 }]);
changed(); // true
changed(0); // false
changed(1); // true
changedTo('1.id', 4); // true
```
> It uses [deep-diff](https://github.com/flitbit/diff) to compare plain objects/arrays and [nested-property](https://github.com/cosmosio/nested-property) to get the nested key.
## With React
### Class components
```js
import treeChanges from 'tree-changes';
class Comp extends React.Component {

@@ -89,20 +123,53 @@ ...

### API
### Functional components with hooks
**changed(key: string)**
```jsx
import React, { useEffect, useRef } from 'react';
import treeChanges from 'tree-changes';
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
function useTreeChanges(props) {
const prevProps = usePrevious(props) || {};
return treeChanges(prevProps, props);
}
const Page = (props) => {
const { changedTo } = useTreeChanges(props);
if (changedTo('isLoaded', true)) {
sendAnalyticsEvent('load', 'MySuperPage')
}
return <div>...</div>;
};
```
## API
**changed**(`key: KeyType`)
Check if the value has changed. Supports objects and arrays.
**changedFrom(key: string, previous: string | boolean | number, actual: string | boolean | number)**
**changedFrom**(`key: KeyType`, `previous: InputType`, `actual?: InputType`)
Check if the value has changed from `previous` to `actual`.
**changedTo(key: string, actual: string | boolean | number)**
**changedTo**(`key: KeyType`, `actual: InputType`)
Check if the value has changed to `actual`.
**increased(key: string)**
**increased**(`key: KeyType`)
Check if both versions are numbers and the value has increased.
**decreased(key: string)**
**decreased**(`key: KeyType`)
Check if both versions are numbers and the value has decreased.
> type KeyType = string | number;
type InputType = string | boolean | number | object | Array<string | boolean | number | object>;

@@ -1,23 +0,28 @@

import deep from 'deep-diff';
import { diff } from 'deep-diff';
// @ts-ignore
import nested from 'nested-property';
import { get as nested } from 'nested-property';
interface IObject {
interface IPlainObject {
[key: string]: any;
}
export type TypeInput = string | boolean | number | string[] | boolean[] | number[] | IObject;
export type TypeInput =
| string
| boolean
| number
| IPlainObject
| Array<string | boolean | number | IPlainObject>;
export type IData = IObject | IObject[];
export type IData = IPlainObject | IPlainObject[];
export interface ITreeChanges {
changed: (key?: string) => boolean;
changedFrom: (key: string, previous: TypeInput, actual?: TypeInput) => boolean;
changedTo: (key: string, actual: TypeInput) => boolean;
increased: (key: string) => boolean;
decreased: (key: string) => boolean;
changed: (key?: string | number) => boolean;
changedFrom: (key: string | number, previous: TypeInput, actual?: TypeInput) => boolean;
changedTo: (key: string | number, actual: TypeInput) => boolean;
increased: (key: string | number) => boolean;
decreased: (key: string | number) => boolean;
}
function isPlainObj(...args: any): boolean {
return args.every((d:any) => {
return args.every((d: any) => {
if (!d) {

@@ -28,4 +33,6 @@ return false;

return Object.prototype.toString.call(d)
.slice(8, -1) === 'Object' && (prototype === null || prototype === Object.getPrototypeOf({}));
return (
Object.prototype.toString.call(d).slice(8, -1) === 'Object' &&
(prototype === null || prototype === Object.getPrototypeOf({}))
);
});

@@ -35,3 +42,3 @@ }

function isArray(...args: any): boolean {
return args.every((d: any) => Array.isArray(d));
return args.every(Array.isArray);
}

@@ -49,10 +56,8 @@

return {
changed(key?: string): boolean {
const left = nested.get(data, key);
const right = nested.get(nextData, key);
changed(key?: string | number): boolean {
const left = nested(data, key);
const right = nested(nextData, key);
if ((isArray(left, right)) || (isPlainObj(left, right))) {
const diff = deep.diff(left, right);
return !!diff;
if (isArray(left, right) || isPlainObj(left, right)) {
return !!diff(left, right);
}

@@ -62,4 +67,4 @@

},
changedFrom(key: string, previous: TypeInput, actual?: TypeInput): boolean {
if (!key) {
changedFrom(key: string | number, previous: TypeInput, actual?: TypeInput): boolean {
if (typeof key === 'undefined') {
throw new Error('Key parameter is required');

@@ -69,36 +74,45 @@ }

const useActual = typeof previous !== 'undefined' && typeof actual !== 'undefined';
const left = nested.get(data, key);
const right = nested.get(nextData, key);
const leftComparator = Array.isArray(previous) ? previous.indexOf(left as never) >= 0 : left === previous;
const rightComparator = Array.isArray(actual) ? actual.indexOf(right as never) >= 0 : right === actual;
const left = nested(data, key);
const right = nested(nextData, key);
const leftComparator = Array.isArray(previous)
? previous.indexOf(left) >= 0
: left === previous;
const rightComparator = Array.isArray(actual) ? actual.indexOf(right) >= 0 : right === actual;
return leftComparator && (useActual ? rightComparator : !useActual);
},
changedTo(key: string, actual: TypeInput): boolean {
if (!key) {
changedTo(key: string | number, actual: TypeInput): boolean {
if (typeof key === 'undefined') {
throw new Error('Key parameter is required');
}
const left = nested.get(data, key);
const right = nested.get(nextData, key);
const leftComparator = Array.isArray(actual) ? actual.indexOf(left as never) < 0 : left !== actual;
const rightComparator = Array.isArray(actual) ? actual.indexOf(right as never) >= 0 : right === actual;
const left = nested(data, key);
const right = nested(nextData, key);
const leftComparator = Array.isArray(actual) ? actual.indexOf(left) < 0 : left !== actual;
const rightComparator = Array.isArray(actual) ? actual.indexOf(right) >= 0 : right === actual;
return leftComparator && rightComparator;
},
increased(key: string): boolean {
if (!key) {
increased(key: string | number): boolean {
if (typeof key === 'undefined') {
throw new Error('Key parameter is required');
}
return isNumber(nested.get(data, key), nested.get(nextData, key)) && nested.get(data, key) < nested.get(nextData, key);
return (
isNumber(nested(data, key), nested(nextData, key)) &&
nested(data, key) < nested(nextData, key)
);
},
decreased(key: string): boolean {
if (!key) {
decreased(key: string | number): boolean {
if (typeof key === 'undefined') {
throw new Error('Key parameter is required');
}
return isNumber(nested.get(data, key), nested.get(nextData, key)) && nested.get(data, key) > nested.get(nextData, key);
return (
isNumber(nested(data, key), nested(nextData, key)) &&
nested(data, key) > nested(nextData, key)
);
},
};
}
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