Skip to content

migrated the project to typescript #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .mocharc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"reporter": "spec",
"timeout": 120000,
"slow": 300,
"bail": true,
"recursive": true,
"require": [
"should"
],
"extension": ["js"]
}
50 changes: 50 additions & 0 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
export declare enum UpdatedValues {
first = 1,
second = 2,
both = 3,
bothWithDeepDiff = 4
}
declare type CompareFunction<A> = (value: A, other: A) => boolean;
declare type ReturnTypeNormal<T> = {
same: T[];
added: T[];
updated: T[];
removed: T[];
};
declare type ReturnTypeBoth<T> = {
same: T[];
added: T[];
updated: [T, T][];
removed: T[];
};
declare class Wrapper<T> {
wrapped(e: T): import("deep-diff").Diff<T, T>[] | undefined;
}
declare type FooInternalType<T> = ReturnType<Wrapper<T>['wrapped']>;
declare type ReturnTypeDeepDiff<T> = {
same: T[];
added: T[];
updated: [T, T, FooInternalType<T>][];
removed: T[];
};
declare function diff<T>(first: T[], second: T[], idField: keyof T, options?: {
compareFunction?: CompareFunction<T>;
updatedValues?: UpdatedValues.first;
}): ReturnTypeNormal<T>;
declare function diff<T>(first: T[], second: T[], idField: keyof T, options?: {
compareFunction?: CompareFunction<T>;
updatedValues?: UpdatedValues.second;
}): ReturnTypeNormal<T>;
declare function diff<T>(first: T[], second: T[], idField: keyof T, options?: {
compareFunction?: CompareFunction<T>;
updatedValues?: UpdatedValues.both;
}): ReturnTypeBoth<T>;
declare function diff<T>(first: T[], second: T[], idField: keyof T, options?: {
compareFunction?: CompareFunction<T>;
updatedValues?: UpdatedValues.bothWithDeepDiff;
}): ReturnTypeDeepDiff<T>;
declare namespace diff {
var updatedValues: typeof UpdatedValues;
}
export default diff;
//# sourceMappingURL=index.d.ts.map
64 changes: 41 additions & 23 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,14 @@ const diff = (first = [], second = [], idField = 'id', options = {}) => {
if (values(updatedValues).indexOf(opts.updatedValues) === -1) throw new Error('diff-arrays-of-objects error: "options.updatedValues" must be a one of the ".updatedValues" but is not');
if (!isFunction(opts.compareFunction)) throw new Error('diff-arrays-of-objects error: "options.compareFunction" must be a function but is not');

// arrays to hold the id values in the two arrays
const firstIds = [];
const secondIds = [];
// arrays to hold the id values in the two arrays
const firstIds = first.map(i => i[idField]);
const secondIds = second.map(i => i[idField]);

// index the first array by its id values.
// if first is [{ id: 1, a: 1 }, { id: 2, a: 3 }] then
// firstIndex will be { 1: { id: 1, a: 1 }, 2: { id: 2, a: 3 } }
// "getKey" has a side-effect of pushing the id value into firstIds; this saves on another iteration through "first"
const getKey = (o) => {
firstIds.push(o[idField]); // ! side-effect
return o[idField];
};
const firstIndex = keyBy(getKey)(first);
Expand All @@ -52,35 +50,55 @@ const diff = (first = [], second = [], idField = 'id', options = {}) => {
// It has a side-effect of pushing the idField value of second object (o2)
// into the secondIds array. The side-effect can easily be avoided but it saves another iteration "second"
const groupingFunction = (o2) => {
secondIds.push(o2[idField]); // ! side-effect
const o1 = firstIndex[o2[idField]]; // take advantage of the closure
if (!o1) return 'added';
else if (opts.compareFunction(o1, o2)) return 'same';
else return 'updated';
};

// this creates the "added", "same" and "updated" results
const result = groupBy(groupingFunction)(second);

// check what value should be returned for "updated" results
// updatedValues.second is the default so doesn't have an "if" here
if (opts.updatedValues === updatedValues.first) {
result.updated = map(u => firstIndex[u[idField]])(result.updated);
} else if (opts.updatedValues === updatedValues.both) {
result.updated = map(u => [firstIndex[u[idField]], u])(result.updated);
} else if (opts.updatedValues === updatedValues.bothWithDeepDiff) {
result.updated = map((u) => {
const f = firstIndex[u[idField]];
const s = u;
const dd = deepDiff(f, s);
return [f, s, dd];
})(result.updated);
}
const result = {
added: [],
same: [],
updated: [],
removed: [],
...groupBy(groupingFunction)(second),
};

// now add "removed" and return
const removedIds = difference(firstIds)(secondIds);
const removed = map(id => firstIndex[id])(removedIds);
return { same: [], added: [], updated: [], ...result, removed };

switch (opts.updatedValues) {
case updatedValues.first:
result.updated = result.updated.map(u => firstIndex[u[idField]]);
return { ...result, removed };

case updatedValues.second:
return { ...result, removed };

case updatedValues.both: {
const updated = result.updated.map(u => [firstIndex[u[idField]], u]);
return { added: result.added, same: result.same, updated: updated, removed };
}

case updatedValues.bothWithDeepDiff: {
const updated = result.updated.map((u) => {
const firstItem = firstIndex[u[idField]];
const secondItem = u;
const deepDiffResult = deepDiff(firstItem, secondItem);

return [firstItem, secondItem, deepDiffResult];
});

return { added: result.added, same: result.same, updated: updated, removed };
}

default:
throw new Error(
'diff-arrays-of-objects error: reached the end of the UpdatedValues switch statement without taking a branch',
);
}
};

diff.updatedValues = updatedValues;
Expand Down
Loading