Skip to content

Commit 9c8c562

Browse files
committed
add type definitions, split out tests, small refactoring, updated tech
1 parent 4e86f27 commit 9c8c562

13 files changed

+917
-854
lines changed

.mocharc.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"reporter": "spec",
3+
"timeout": 120000,
4+
"slow": 300,
5+
"bail": true,
6+
"recursive": true,
7+
"require": [
8+
"should"
9+
],
10+
"extension": ["js"]
11+
}

lib/index.d.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
export declare enum UpdatedValues {
2+
first = 1,
3+
second = 2,
4+
both = 3,
5+
bothWithDeepDiff = 4
6+
}
7+
declare type CompareFunction<A> = (value: A, other: A) => boolean;
8+
declare type ReturnTypeNormal<T> = {
9+
same: T[];
10+
added: T[];
11+
updated: T[];
12+
removed: T[];
13+
};
14+
declare type ReturnTypeBoth<T> = {
15+
same: T[];
16+
added: T[];
17+
updated: [T, T][];
18+
removed: T[];
19+
};
20+
declare class Wrapper<T> {
21+
wrapped(e: T): import("deep-diff").Diff<T, T>[] | undefined;
22+
}
23+
declare type FooInternalType<T> = ReturnType<Wrapper<T>['wrapped']>;
24+
declare type ReturnTypeDeepDiff<T> = {
25+
same: T[];
26+
added: T[];
27+
updated: [T, T, FooInternalType<T>][];
28+
removed: T[];
29+
};
30+
declare function diff<T>(first: T[], second: T[], idField: keyof T, options?: {
31+
compareFunction?: CompareFunction<T>;
32+
updatedValues?: UpdatedValues.first;
33+
}): ReturnTypeNormal<T>;
34+
declare function diff<T>(first: T[], second: T[], idField: keyof T, options?: {
35+
compareFunction?: CompareFunction<T>;
36+
updatedValues?: UpdatedValues.second;
37+
}): ReturnTypeNormal<T>;
38+
declare function diff<T>(first: T[], second: T[], idField: keyof T, options?: {
39+
compareFunction?: CompareFunction<T>;
40+
updatedValues?: UpdatedValues.both;
41+
}): ReturnTypeBoth<T>;
42+
declare function diff<T>(first: T[], second: T[], idField: keyof T, options?: {
43+
compareFunction?: CompareFunction<T>;
44+
updatedValues?: UpdatedValues.bothWithDeepDiff;
45+
}): ReturnTypeDeepDiff<T>;
46+
declare namespace diff {
47+
var updatedValues: typeof UpdatedValues;
48+
}
49+
export default diff;
50+
//# sourceMappingURL=index.d.ts.map

lib/index.js

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,14 @@ const diff = (first = [], second = [], idField = 'id', options = {}) => {
3434
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');
3535
if (!isFunction(opts.compareFunction)) throw new Error('diff-arrays-of-objects error: "options.compareFunction" must be a function but is not');
3636

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

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

6259
// this creates the "added", "same" and "updated" results
63-
const result = groupBy(groupingFunction)(second);
64-
65-
// check what value should be returned for "updated" results
66-
// updatedValues.second is the default so doesn't have an "if" here
67-
if (opts.updatedValues === updatedValues.first) {
68-
result.updated = map(u => firstIndex[u[idField]])(result.updated);
69-
} else if (opts.updatedValues === updatedValues.both) {
70-
result.updated = map(u => [firstIndex[u[idField]], u])(result.updated);
71-
} else if (opts.updatedValues === updatedValues.bothWithDeepDiff) {
72-
result.updated = map((u) => {
73-
const f = firstIndex[u[idField]];
74-
const s = u;
75-
const dd = deepDiff(f, s);
76-
return [f, s, dd];
77-
})(result.updated);
78-
}
60+
const result = {
61+
added: [],
62+
same: [],
63+
updated: [],
64+
removed: [],
65+
...groupBy(groupingFunction)(second),
66+
};
7967

8068
// now add "removed" and return
8169
const removedIds = difference(firstIds)(secondIds);
8270
const removed = map(id => firstIndex[id])(removedIds);
83-
return { same: [], added: [], updated: [], ...result, removed };
71+
72+
switch (opts.updatedValues) {
73+
case updatedValues.first:
74+
result.updated = result.updated.map(u => firstIndex[u[idField]]);
75+
return { ...result, removed };
76+
77+
case updatedValues.second:
78+
return { ...result, removed };
79+
80+
case updatedValues.both: {
81+
const updated = result.updated.map(u => [firstIndex[u[idField]], u]);
82+
return { added: result.added, same: result.same, updated: updated, removed };
83+
}
84+
85+
case updatedValues.bothWithDeepDiff: {
86+
const updated = result.updated.map((u) => {
87+
const firstItem = firstIndex[u[idField]];
88+
const secondItem = u;
89+
const deepDiffResult = deepDiff(firstItem, secondItem);
90+
91+
return [firstItem, secondItem, deepDiffResult];
92+
});
93+
94+
return { added: result.added, same: result.same, updated: updated, removed };
95+
}
96+
97+
default:
98+
throw new Error(
99+
'diff-arrays-of-objects error: reached the end of the UpdatedValues switch statement without taking a branch',
100+
);
101+
}
84102
};
85103

86104
diff.updatedValues = updatedValues;

0 commit comments

Comments
 (0)