DoneDeal0 / superdiff

Superdiff compares two arrays or objects and returns a full diff of their differences in a readable format.
https://www.npmjs.com/package/@donedeal0/superdiff
695 stars 6 forks source link

chore: stream large lists diff #26

Closed DoneDeal0 closed 1 month ago

DoneDeal0 commented 1 month ago

NEW FEATURE

streamListDiff()

import { streamListDiff } from "@donedeal0/superdiff";

Streams the diff of two object lists, ideal for large lists and maximum performance.

FORMAT

Input

 prevList: Record<string, unknown>[],
 nextList: Record<string, unknown>[],
 referenceProperty: keyof Record<string, unknown>,
 options: {
  showOnly?: ("added" | "deleted" | "moved" | "updated" | "equal")[], // [] by default
  chunksSize?: number, // // 0 by default
  considerMoveAsUpdate? boolean; // false by default
}

Output

The objects diff are grouped in arrays - called chunks - and are consumed thanks to an event listener. You have access to 3 events:

interface StreamListener<T extends Record<string, unknown>> {
  on<E extends keyof EmitterEvents<T>>(
    event: E,
    listener: Listener<EmitterEvents<T>[E]>,
  ): this;
}

type EmitterEvents<T extends Record<string, unknown>> = {
  data: [StreamListDiff<T>[]];
  error: [Error];
  finish: [];
};

type StreamListDiff<T extends Record<string, unknown>> = {
  currentValue: T | null;
  previousValue: T | null;
  prevIndex: number | null;
  newIndex: number | null;
  indexDiff: number | null;
  status: "added" | "deleted" | "moved" | "updated" | "equal";
};

USAGE

Input

const diff = streamListDiff(
      [ 
-       { id: 1, name: "Item 1" },  
        { id: 2, name: "Item 2" },
        { id: 3, name: "Item 3" } 
      ],
      [
+       { id: 0, name: "Item 0" }, 
        { id: 2, name: "Item 2" },
+       { id: 3, name: "Item Three" },
      ],
      "id", 
      { chunksSize: 2 }
    );

Output

diff.on("data", (chunk) => {
      // first chunk received (2 object diffs)
      [
+       {
+         previousValue: null,
+         currentValue: { id: 0, name: 'Item 0' },
+         prevIndex: null,
+         newIndex: 0,
+         indexDiff: null,
+         status: 'added'
+       },
-       {
-         previousValue: { id: 1, name: 'Item 1' },
-         currentValue: null,
-         prevIndex: 0,
-         newIndex: null,
-         indexDiff: null,
-         status: 'deleted'
-       }
      ]
    // second chunk received (2 object diffs)
      [
        {
          previousValue: { id: 2, name: 'Item 2' },
          currentValue: { id: 2, name: 'Item 2' },
          prevIndex: 1,
          newIndex: 1,
          indexDiff: 0,
          status: 'equal'
        },
+       {
+         previousValue: { id: 3, name: 'Item 3' },
+         currentValue: { id: 3, name: 'Item Three' },
+         prevIndex: 2,
+         newIndex: 2,
+         indexDiff: 0,
+         status: 'updated'
+       },
     ]
});

diff.on("finish", () => console.log("The full diff is available"))
diff.on("error", (err) => console.log(err))

ADDITIONAL FIXES

github-actions[bot] commented 1 month ago

:tada: This PR is included in version 2.1.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket: