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

change-checker

v2.3.0

Published

Utility for creating generic deep typed diffs to track changes between lifecycles of objects.

Downloads

32

Readme

ChangeChecker

A typescript utility for creating generic deep typed diffs to track changes between lifecycles of objects.

  • dependency free
  • fast
  • typed
  • extensible

Try it online

Switch to VSCode mode (Preferences -> Experiments -> Use VSCode in the browser)
Edit change-checker example using Vue

Installation

npm install change-checker
yarn add change-checker
bower install change-checker

Load

TypeScript

import { ChangeChecker } from 'change-checker';

Javascript

var changeChecker = require('change-checker');

AMD

define(function(require,exports,module){
  var changeChecker = require('change-checker');
});

How it works

Configuration

Create an instance of the class 'ChangeChecker' and optionally add plugins as needed (more about plugins, see below).

const changeChecker = new ChangeChecker().withPlugin(new DatePlugin())
                                         .withPlugin(new DecimalPlugin());

Take snapshots

To create a diff you first have to take a snapshot of your current model by calling the 'takeSnapshot' method.

const snapshot = changeChecker.takeSnapshot(model);

Create the diff

After mutating your model call the method 'createDiff' providing your snapshot and the mutated model.

const diff = changeChecker.createDiff(snapshot, model);

Query for changes

Deep dirty check

If you want to know wether anything has changed you can do a deep dirty check at any node using '$isDirty()'

diff.$isDirty(); // has anything changed?
diff.property.$isDirty() // has anything changed below a specific property?

Get more detailed information about C~~R~~UD operations done to your model

If you want to know if an array or object was created, changed or deleted use $isCreated, $isChanged, $isDeleted.

diff.$isChanged; // if true, the object has a new property, got some deleted or any value or reference to another object has changed

The former and present value of properties are available through $formerValue and $value.

diff.property.$value; // present value of the property
if(diff.property.$isChanged){
  const formerValue = diff.property.$formerValue // the former value of the properyt (if changed)
}

If the property is a value type (number, string etc.) or a "value like" (look below for "Plugin") $value and $formerValue remain of this type.

const value: string = diff.stringProperty.$value;
const decimal: Decimal = diff.decimalProperty.$value;

Otherwise both ($value and $formerValue) are also diffs.

const addressDiff: ObjectDiff<{  street: string; }> = diff.address.$value; // model: {  street: string; }
const isAddressChanged = addressDiff.$isChanged;

If you want to operate on deleted or inserted entries of the array the properties $deleted and $inserted provide this information.

diff.array.$value.$inserted;
diff.array.$value.$deleted;

You can unwrap the former and present model at any point using $unwrap(Era = Era.Former | Era.Present).

diff.array.$value.$inserted.map((x) => x.$unwrap(Era.Present)); // The result contains structural equal objects of all inserted entries 
diff.$unwrap(Era.Present); // The result contains the full structural equal model

Example

interface ICompany {
  name: string;
  addresses: IAddress[];
}

interface IAddress {
  street: string;
}

const model!: ICompany;

const changeChecker = new ChangeChecker();
const snapshot = changeChecker.takeSnapshot(model);

// mutate model

const diff = changeChecker.createDiff(snapshot, model);

if (diff.$isDirty()) {
  if (diff.name.$isChanged) {
    // publish update name command
  }

  for (const address of diff.addresses.$value.$inserted.map((x) => x.$unwrap(Era.Present))) {
    // publish insert address command
  }

  for (const address of diff.addresses.$value.$deleted.map((x) => x.$unwrap(Era.Present))) {
    // publish delete address command
  }
}

Plugins

Value likes

Without plugins the library would create diff objects (associated with $isCreated, $isDeleted so far and so forth) for all Objects. This behaviour is useless for objects like Date or 3rd party libraries like decimal.js. Those should be handeled like true values like strings, numbers etc. To solve this issue it is possible to create 'value like' plugins. They must provide a 'clone', 'equals' and 'isMatch' function to overwrite the default equality and reference rules of javascript.

Example

import Decimal from "decimal.js";
import { IValueLikePlugin, ICloneContext } from "change-checker";

export class DecimalPlugin implements IValueLikePlugin<Decimal> {
    public name: string = "DecimalPlugin";

    public isValueLikePlugin: true = true;

    public clone(_: ICloneContext, instance: Decimal): Decimal {
        return new Decimal(instance);
    }

    public equals(left: Decimal, right: Decimal): boolean {
        return left.equals(right);
    }

    public isMatch(instance: any): instance is Decimal {
        return instance instanceof Decimal;
    }
}

declare module "change-checker/types/ValueLikeRegistry" {
    export interface IValueLikeRegistry {
        decimal: Decimal;
    }
}

Build

  • clone
  • yarn
  • yarn build

Test

  • yarn test
  • npm test