@diffson/core 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +264 -0
  2. package/package.json +5 -1
  3. package/.turbo/turbo-build.log +0 -1
  4. package/.turbo/turbo-test.log +0 -96
  5. package/.turbo/turbo-typecheck.log +0 -2
  6. package/src/contract/constant/DiffConstants.ts +0 -10
  7. package/src/contract/constant/PresetName.ts +0 -6
  8. package/src/contract/constant/index.ts +0 -2
  9. package/src/contract/index.ts +0 -2
  10. package/src/contract/type/ArrayComparator.ts +0 -15
  11. package/src/contract/type/ComparatorOrchestrator.ts +0 -16
  12. package/src/contract/type/DiffService.ts +0 -31
  13. package/src/contract/type/JsonTypes.ts +0 -3
  14. package/src/contract/type/NullComparator.ts +0 -9
  15. package/src/contract/type/ObjectComparator.ts +0 -15
  16. package/src/contract/type/OtherComparator.ts +0 -14
  17. package/src/contract/type/PrimitiveComparator.ts +0 -13
  18. package/src/contract/type/Result.ts +0 -7
  19. package/src/contract/type/SingleNodeDifference.ts +0 -13
  20. package/src/contract/type/index.ts +0 -10
  21. package/src/index.ts +0 -17
  22. package/src/service/comparator/ComparatorOrchestrator.ts +0 -50
  23. package/src/service/comparator/array/AbstractArray.ts +0 -34
  24. package/src/service/comparator/array/SequentialArrayComparator.test.ts +0 -46
  25. package/src/service/comparator/array/SequentialArrayComparator.ts +0 -48
  26. package/src/service/comparator/array/SimilarArrayComparator.test.ts +0 -37
  27. package/src/service/comparator/array/SimilarArrayComparator.ts +0 -211
  28. package/src/service/comparator/array/index.ts +0 -3
  29. package/src/service/comparator/index.ts +0 -6
  30. package/src/service/comparator/nulls/DefaultNullComparator.test.ts +0 -38
  31. package/src/service/comparator/nulls/DefaultNullComparator.ts +0 -9
  32. package/src/service/comparator/nulls/index.ts +0 -1
  33. package/src/service/comparator/object/AbstractObject.ts +0 -102
  34. package/src/service/comparator/object/LeftJoinObjectComparator.test.ts +0 -71
  35. package/src/service/comparator/object/LeftJoinObjectComparator.ts +0 -18
  36. package/src/service/comparator/object/UnionKeyObjectComparator.test.ts +0 -20
  37. package/src/service/comparator/object/UnionKeyObjectComparator.ts +0 -19
  38. package/src/service/comparator/object/index.ts +0 -3
  39. package/src/service/comparator/other/DefaultOtherComparator.test.ts +0 -48
  40. package/src/service/comparator/other/DefaultOtherComparator.ts +0 -23
  41. package/src/service/comparator/other/index.ts +0 -1
  42. package/src/service/comparator/primitive/DefaultPrimitiveComparator.test.ts +0 -50
  43. package/src/service/comparator/primitive/DefaultPrimitiveComparator.ts +0 -27
  44. package/src/service/comparator/primitive/index.ts +0 -1
  45. package/src/service/diff/Diff.test.ts +0 -113
  46. package/src/service/diff/DiffContext.ts +0 -37
  47. package/src/service/diff/DiffService.test.ts +0 -292
  48. package/src/service/diff/DiffService.ts +0 -245
  49. package/src/service/diff/PathTracker.ts +0 -71
  50. package/src/service/diff/index.ts +0 -1
  51. package/src/service/index.ts +0 -2
  52. package/src/util/TypeGuards.test.ts +0 -90
  53. package/src/util/TypeGuards.ts +0 -33
  54. package/src/util/index.ts +0 -1
  55. package/tsconfig.json +0 -11
  56. package/tsconfig.tsbuildinfo +0 -1
@@ -1,34 +0,0 @@
1
- import { Inject } from "@wendellhu/redi";
2
- import type { IArrayComparator, IComparatorOrchestrator, JsonArray, JsonValue } from "../../../contract/type";
3
- import { IComparatorOrchestrator as IComparatorOrchestratorToken } from "../../../contract/type";
4
- import { DiffContext } from "../../diff/DiffContext";
5
- import type { PathTracker } from "../../diff/PathTracker";
6
- import { DIFFERENT } from "../../../contract/constant";
7
-
8
- export abstract class AbstractArray implements IArrayComparator {
9
- constructor(
10
- @Inject(IComparatorOrchestratorToken) protected orchestrator: IComparatorOrchestrator
11
- ) {}
12
-
13
- abstract diffArray(a: JsonArray, b: JsonArray, pathTracker: PathTracker): DiffContext;
14
-
15
- diffElement(a: JsonValue | undefined, b: JsonValue | undefined, pathTracker: PathTracker): DiffContext {
16
- return this.orchestrator.diffElement(a, b, pathTracker);
17
- }
18
-
19
- protected parentContextAddChildContext(parentResult: DiffContext, childResult: DiffContext): void {
20
- if (childResult.isSame() === DIFFERENT) {
21
- for (const singleNodeDifference of childResult.getDiffResultModels()) {
22
- parentResult.getDiffResultModels().push(singleNodeDifference);
23
- }
24
- parentResult.setSame(false);
25
- }
26
- }
27
-
28
- protected constructArrayPath(i: number): string {
29
- if (i === null || i === undefined || i < 0) {
30
- throw new Error("数组索引号入参为空或者为负。 入参:" + i);
31
- }
32
- return "[" + i + "]";
33
- }
34
- }
@@ -1,46 +0,0 @@
1
- import { describe, it, expect } from "bun:test";
2
- import { DiffService } from "../../diff/DiffService";
3
- import { SequentialArrayComparator } from "./SequentialArrayComparator";
4
-
5
- function createSequentialDiffService(): DiffService {
6
- return new DiffService().withArrayComparator(SequentialArrayComparator);
7
- }
8
-
9
- describe("SequentialArrayComparator", () => {
10
- it("should compare arrays by index", () => {
11
- const left = { items: [1, 2, 3] };
12
- const right = { items: [1, 4, 3] };
13
-
14
- const diffService = createSequentialDiffService();
15
- const results = diffService.diffElement(left, right);
16
-
17
- expect(results.length).toBe(1);
18
- expect(results[0].leftPath).toBe("items.[1]");
19
- expect(results[0].left).toBe("2");
20
- expect(results[0].right).toBe("4");
21
- });
22
-
23
- it("should detect added elements", () => {
24
- const left = { items: [1, 2] };
25
- const right = { items: [1, 2, 3] };
26
-
27
- const diffService = createSequentialDiffService();
28
- const results = diffService.diffElement(left, right);
29
-
30
- expect(results.length).toBe(1);
31
- expect(results[0].diffType).toBe("ADD");
32
- expect(results[0].rightPath).toBe("items.[2]");
33
- });
34
-
35
- it("should detect deleted elements", () => {
36
- const left = { items: [1, 2, 3] };
37
- const right = { items: [1, 2] };
38
-
39
- const diffService = createSequentialDiffService();
40
- const results = diffService.diffElement(left, right);
41
-
42
- expect(results.length).toBe(1);
43
- expect(results[0].diffType).toBe("DELETE");
44
- expect(results[0].leftPath).toBe("items.[2]");
45
- });
46
- });
@@ -1,48 +0,0 @@
1
- import { Inject } from "@wendellhu/redi";
2
- import { AbstractArray } from "./AbstractArray";
3
- import { DiffContext } from "../../diff/DiffContext";
4
- import type { PathTracker } from "../../diff/PathTracker";
5
- import type { JsonArray, IComparatorOrchestrator } from "../../../contract/type";
6
- import { IComparatorOrchestrator as IComparatorOrchestratorToken } from "../../../contract/type";
7
-
8
- export class SequentialArrayComparator extends AbstractArray {
9
- constructor(
10
- @Inject(IComparatorOrchestratorToken) orchestrator: IComparatorOrchestrator
11
- ) {
12
- super(orchestrator);
13
- }
14
-
15
- diffArray(a: JsonArray, b: JsonArray, pathTracker: PathTracker): DiffContext {
16
- const arrayDiffContext = new DiffContext();
17
- const maxLength = Math.max(a.length, b.length);
18
-
19
- for (let i = 0; i < maxLength; i++) {
20
- pathTracker.addAllpath(this.constructArrayPath(i));
21
- const diffContext = this.generateDiffResult(a, b, i, pathTracker);
22
- this.parentContextAddChildContext(arrayDiffContext, diffContext);
23
- pathTracker.removeAllLastPath();
24
- }
25
- return arrayDiffContext;
26
- }
27
-
28
- private generateDiffResult(
29
- a: JsonArray,
30
- b: JsonArray,
31
- i: number,
32
- pathTracker: PathTracker
33
- ): DiffContext {
34
- if (i >= a.length && i >= b.length) {
35
- throw new Error("数组索引号入参超过数组长度。 索引号:" + i + " 数组a:" + a + "数组b:" + b);
36
- }
37
-
38
- let diffContext: DiffContext;
39
- if (i < a.length && i < b.length) {
40
- diffContext = this.diffElement(a[i], b[i], pathTracker);
41
- } else if (i >= a.length) {
42
- diffContext = this.diffElement(undefined, b[i], pathTracker);
43
- } else {
44
- diffContext = this.diffElement(a[i], undefined, pathTracker);
45
- }
46
- return diffContext;
47
- }
48
- }
@@ -1,37 +0,0 @@
1
- import { describe, it, expect } from "bun:test";
2
- import { DiffService } from "../../diff/DiffService";
3
-
4
- describe("SimilarArrayComparator", () => {
5
- it("should match similar elements", () => {
6
- const left = { items: [{ id: 1, name: "a" }, { id: 2, name: "b" }] };
7
- const right = { items: [{ id: 2, name: "b" }, { id: 1, name: "a" }] };
8
-
9
- const diffService = new DiffService();
10
- const results = diffService.diffElement(left, right);
11
-
12
- expect(results).toEqual([]);
13
- });
14
-
15
- it("should detect modifications in matched elements", () => {
16
- const left = { items: [{ id: 1, name: "a" }] };
17
- const right = { items: [{ id: 1, name: "b" }] };
18
-
19
- const diffService = new DiffService();
20
- const results = diffService.diffElement(left, right);
21
-
22
- expect(results.length).toBe(1);
23
- expect(results[0].left).toBe("a");
24
- expect(results[0].right).toBe("b");
25
- });
26
-
27
- it("should detect added elements", () => {
28
- const left = { items: [{ id: 1 }] };
29
- const right = { items: [{ id: 1 }, { id: 2 }] };
30
-
31
- const diffService = new DiffService();
32
- const results = diffService.diffElement(left, right);
33
-
34
- expect(results.length).toBe(1);
35
- expect(results[0].diffType).toBe("ADD");
36
- });
37
- });
@@ -1,211 +0,0 @@
1
- import { Inject } from "@wendellhu/redi";
2
- import { AbstractArray } from "./AbstractArray";
3
- import { DiffContext } from "../../diff/DiffContext";
4
- import type { PathTracker } from "../../diff/PathTracker";
5
- import type { JsonArray, IComparatorOrchestrator } from "../../../contract/type";
6
- import { SingleNodeDifference, IComparatorOrchestrator as IComparatorOrchestratorToken } from "../../../contract/type";
7
-
8
- export class SimilarArrayComparator extends AbstractArray {
9
- private readonly USEABLE = false;
10
- private readonly USED = true;
11
-
12
- constructor(
13
- @Inject(IComparatorOrchestratorToken) orchestrator: IComparatorOrchestrator
14
- ) {
15
- super(orchestrator);
16
- }
17
-
18
- diffArray(a: JsonArray, b: JsonArray, pathTracker: PathTracker): DiffContext {
19
- let diffContext: DiffContext;
20
-
21
- if (a.length <= b.length) {
22
- diffContext = this.diff(a, b, pathTracker);
23
- } else {
24
- this.exchangeLeftAndRightPath(pathTracker);
25
- diffContext = this.diff(b, a, pathTracker);
26
- this.exchangeLeftAndRightPath(pathTracker);
27
- this.exchangeResult(diffContext);
28
- }
29
- return diffContext;
30
- }
31
-
32
- private exchangeResult(diffContext: DiffContext): void {
33
- const singleNodeDifferences = diffContext.getDiffResultModels();
34
- for (const singleNodeDifference of singleNodeDifferences) {
35
- this.exchangePathAndResult(singleNodeDifference);
36
- }
37
- }
38
-
39
- private exchangePathAndResult(singleNodeDifference: SingleNodeDifference): void {
40
- const tempStringA = singleNodeDifference.leftPath;
41
- const tempLeft = singleNodeDifference.left;
42
- singleNodeDifference.leftPath = singleNodeDifference.rightPath;
43
- singleNodeDifference.rightPath = tempStringA;
44
- singleNodeDifference.left = singleNodeDifference.right;
45
- singleNodeDifference.right = tempLeft;
46
- }
47
-
48
- private exchangeLeftAndRightPath(pathTracker: PathTracker): void {
49
- const tempA = pathTracker.getLeftPath();
50
- pathTracker.setLeftPath(pathTracker.getRightPath());
51
- pathTracker.setRightPath(tempA);
52
- }
53
-
54
- diff(a: JsonArray, b: JsonArray, pathTracker: PathTracker): DiffContext {
55
- const rowlength = a.length;
56
- const linelength = b.length;
57
-
58
- const similarMatrix: number[][] = Array.from({ length: rowlength }, () =>
59
- Array(linelength).fill(0)
60
- );
61
-
62
- const row: boolean[] = Array(rowlength).fill(false);
63
- const line: boolean[] = Array(linelength).fill(false);
64
-
65
- for (let i = 0; i < rowlength; i++) {
66
- pathTracker.addLeftPath(this.constructArrayPath(i));
67
- this.constructSimilarMatrix(a, b, i, pathTracker, similarMatrix, row, line);
68
- pathTracker.removeLastLeftPath();
69
- }
70
- return this.obtainDiffResult(a, b, pathTracker, row, line, similarMatrix);
71
- }
72
-
73
- private obtainDiffResult(
74
- a: JsonArray,
75
- b: JsonArray,
76
- pathTracker: PathTracker,
77
- row: boolean[],
78
- line: boolean[],
79
- similarMatrix: number[][]
80
- ): DiffContext {
81
- const arrayDiffContext = new DiffContext();
82
- this.obtainModifyDiffResult(a, b, pathTracker, row, line, similarMatrix, arrayDiffContext);
83
- this.obtainAddDiffResult(b, pathTracker, line, arrayDiffContext);
84
- return arrayDiffContext;
85
- }
86
-
87
- private obtainAddDiffResult(
88
- b: JsonArray,
89
- pathTracker: PathTracker,
90
- line: boolean[],
91
- arrayDiffContext: DiffContext
92
- ): void {
93
- for (let j = 0; j < line.length; j++) {
94
- if (line[j] === this.USED) {
95
- continue;
96
- }
97
- const addOrDeleteDiffContext = this.constructAddContext(b, j, pathTracker);
98
- this.parentContextAddChildContext(arrayDiffContext, addOrDeleteDiffContext);
99
- }
100
- }
101
-
102
- private obtainModifyDiffResult(
103
- a: JsonArray,
104
- b: JsonArray,
105
- pathTracker: PathTracker,
106
- row: boolean[],
107
- line: boolean[],
108
- similarMatrix: number[][],
109
- arrayDiffContext: DiffContext
110
- ): void {
111
- let counts = 0;
112
- for (const value of row) {
113
- if (value === this.USEABLE) {
114
- counts++;
115
- }
116
- }
117
-
118
- for (let n = 0; n < counts; n++) {
119
- let bestLineIndex = 0;
120
- let bestRowIndex = 0;
121
- let minDiffPair = Number.MAX_SAFE_INTEGER;
122
-
123
- for (let i = 0; i < row.length; i++) {
124
- for (let j = 0; j < line.length; j++) {
125
- if (row[i] === this.USED || line[j] === this.USED) {
126
- continue;
127
- }
128
- if (similarMatrix[i][j] < minDiffPair) {
129
- bestRowIndex = i;
130
- bestLineIndex = j;
131
- minDiffPair = similarMatrix[i][j];
132
- }
133
- }
134
- }
135
-
136
- const modifyDiffContext = this.constructModifyContext(
137
- a,
138
- b,
139
- bestRowIndex,
140
- bestLineIndex,
141
- pathTracker
142
- );
143
- row[bestRowIndex] = this.USED;
144
- line[bestLineIndex] = this.USED;
145
- this.parentContextAddChildContext(arrayDiffContext, modifyDiffContext);
146
- }
147
- }
148
-
149
- private constructAddContext(
150
- b: JsonArray,
151
- index: number,
152
- pathTracker: PathTracker
153
- ): DiffContext {
154
- pathTracker.addAllpath(this.constructArrayPath(index));
155
- const diffContext = this.diffElement(undefined, b[index], pathTracker);
156
- pathTracker.removeAllLastPath();
157
- return diffContext;
158
- }
159
-
160
- private constructModifyContext(
161
- a: JsonArray,
162
- b: JsonArray,
163
- i: number,
164
- bestLineIndex: number,
165
- pathTracker: PathTracker
166
- ): DiffContext {
167
- pathTracker.addLeftPath(this.constructArrayPath(i));
168
- pathTracker.addRightPath(this.constructArrayPath(bestLineIndex));
169
- const diffContext = this.diffElement(a[i], b[bestLineIndex], pathTracker);
170
- pathTracker.removeAllLastPath();
171
- return diffContext;
172
- }
173
-
174
- private constructSimilarMatrix(
175
- arrayA: JsonArray,
176
- arrayB: JsonArray,
177
- rowIndex: number,
178
- pathTracker: PathTracker,
179
- similarArray: number[][],
180
- row: boolean[],
181
- line: boolean[]
182
- ): void {
183
- if (rowIndex < 0 || rowIndex >= arrayB.length) {
184
- throw new Error(
185
- "索引号入参超出数组长度。 索引号:" + rowIndex + " 数组B:" + JSON.stringify(arrayB)
186
- );
187
- }
188
-
189
- for (let j = 0; j < arrayB.length; j++) {
190
- if (line[j] === this.USEABLE) {
191
- pathTracker.addRightPath(this.constructArrayPath(j));
192
- const diffContext = this.diffElement(arrayA[rowIndex], arrayB[j], pathTracker);
193
- pathTracker.removeLastRightPath();
194
-
195
- if (diffContext.isSame()) {
196
- row[rowIndex] = this.USED;
197
- line[j] = this.USED;
198
- return;
199
- } else if (this.existSpecialPath(diffContext.getSpecialPathResult())) {
200
- similarArray[rowIndex][j] = 0;
201
- } else {
202
- similarArray[rowIndex][j] = diffContext.getDiffResultModels().length;
203
- }
204
- }
205
- }
206
- }
207
-
208
- private existSpecialPath(specialPathResult: string[] | null): boolean {
209
- return specialPathResult !== null && specialPathResult.length > 0;
210
- }
211
- }
@@ -1,3 +0,0 @@
1
- export * from "./AbstractArray";
2
- export * from "./SequentialArrayComparator";
3
- export * from "./SimilarArrayComparator";
@@ -1,6 +0,0 @@
1
- export * from "./ComparatorOrchestrator";
2
- export * from "./array";
3
- export * from "./object";
4
- export * from "./primitive";
5
- export * from "./nulls";
6
- export * from "./other";
@@ -1,38 +0,0 @@
1
- import { describe, it, expect } from "bun:test";
2
- import { DiffService } from "../../diff/DiffService";
3
-
4
- describe("DefaultNullComparator", () => {
5
- it("should not report differences for null vs null", () => {
6
- const left = { value: null };
7
- const right = { value: null };
8
-
9
- const diffService = new DiffService();
10
- const results = diffService.diffElement(left, right);
11
-
12
- expect(results).toEqual([]);
13
- });
14
-
15
- it("should detect null to value changes", () => {
16
- const left = { value: null };
17
- const right = { value: 1 };
18
-
19
- const diffService = new DiffService();
20
- const results = diffService.diffElement(left, right);
21
-
22
- expect(results.length).toBe(1);
23
- expect(results[0].left).toBe("null");
24
- expect(results[0].right).toBe("1");
25
- });
26
-
27
- it("should detect value to null changes", () => {
28
- const left = { value: 1 };
29
- const right = { value: null };
30
-
31
- const diffService = new DiffService();
32
- const results = diffService.diffElement(left, right);
33
-
34
- expect(results.length).toBe(1);
35
- expect(results[0].left).toBe("1");
36
- expect(results[0].right).toBe("null");
37
- });
38
- });
@@ -1,9 +0,0 @@
1
- import type { INullComparator } from "../../../contract/type";
2
- import { DiffContext } from "../../diff/DiffContext";
3
- import type { PathTracker } from "../../diff/PathTracker";
4
-
5
- export class DefaultNullComparator implements INullComparator {
6
- diff(_a: null, _b: null, _pathTracker: PathTracker): DiffContext {
7
- return new DiffContext();
8
- }
9
- }
@@ -1 +0,0 @@
1
- export * from "./DefaultNullComparator";
@@ -1,102 +0,0 @@
1
- import { Inject } from "@wendellhu/redi";
2
- import type { IObjectComparator, IComparatorOrchestrator, JsonObject, JsonValue } from "../../../contract/type";
3
- import { IComparatorOrchestrator as IComparatorOrchestratorToken } from "../../../contract/type";
4
- import { DiffContext } from "../../diff/DiffContext";
5
- import type { PathTracker } from "../../diff/PathTracker";
6
- import { DIFFERENT, MERGE_PATH } from "../../../contract/constant";
7
-
8
- export abstract class AbstractObject implements IObjectComparator {
9
- constructor(
10
- @Inject(IComparatorOrchestratorToken) protected orchestrator: IComparatorOrchestrator
11
- ) {}
12
-
13
- abstract diff(a: JsonObject, b: JsonObject, pathTracker: PathTracker): DiffContext;
14
-
15
- diffElement(a: JsonValue | undefined, b: JsonValue | undefined, pathTracker: PathTracker): DiffContext {
16
- return this.orchestrator.diffElement(a, b, pathTracker);
17
- }
18
-
19
- protected parentContextAddChildContext(parentResult: DiffContext, childResult: DiffContext): void {
20
- if (childResult.isSame() === DIFFERENT) {
21
- for (const singleNodeDifference of childResult.getDiffResultModels()) {
22
- parentResult.getDiffResultModels().push(singleNodeDifference);
23
- }
24
- parentResult.setSame(false);
25
- }
26
- }
27
-
28
- protected diffValueByKey(
29
- a: JsonObject,
30
- b: JsonObject,
31
- keySet: Set<string>,
32
- pathTracker: PathTracker
33
- ): DiffContext {
34
- const objectDiffContext = new DiffContext();
35
- const specialPathResult: string[] = [];
36
-
37
- for (const key of keySet) {
38
- pathTracker.addAllpath(key);
39
-
40
- if (!this.needDiff(pathTracker.getNoisePahList(), pathTracker.getLeftPath())) {
41
- pathTracker.removeAllLastPath();
42
- continue;
43
- }
44
-
45
- const diffContext = this.diffElement(a[key], b[key], pathTracker);
46
- this.parentContextAddChildContext(objectDiffContext, diffContext);
47
-
48
- this.specialPathHandle(diffContext.isSame(), specialPathResult, pathTracker);
49
- pathTracker.removeAllLastPath();
50
- }
51
- objectDiffContext.setSpecialPathResult(specialPathResult);
52
- return objectDiffContext;
53
- }
54
-
55
- private specialPathHandle(
56
- isSame: boolean,
57
- specialPathResult: string[],
58
- pathTracker: PathTracker
59
- ): void {
60
- if (!isSame) {
61
- return;
62
- }
63
- const specialPath = this.getSpecialPath(pathTracker);
64
- if (this.existPath(specialPath)) {
65
- specialPathResult.push(specialPath!);
66
- }
67
- }
68
-
69
- private existPath(specialPath: string | null): boolean {
70
- return specialPath !== null;
71
- }
72
-
73
- protected getSpecialPath(pathTracker: PathTracker): string | null {
74
- if (!pathTracker || !pathTracker.getSpecialPath() || pathTracker.getSpecialPath()!.length === 0) {
75
- return null;
76
- }
77
- const currentPath = this.listJoin(pathTracker.getLeftPath());
78
- if (pathTracker.getSpecialPath()!.includes(currentPath)) {
79
- return currentPath;
80
- }
81
- return null;
82
- }
83
-
84
- protected needDiff(noisePahList: string[] | null, pathList: string[]): boolean {
85
- if (!noisePahList || !pathList || noisePahList.length === 0 || pathList.length === 0) {
86
- return true;
87
- }
88
- const path = this.listJoin(pathList);
89
- if (noisePahList.includes(path)) {
90
- return false;
91
- }
92
- return true;
93
- }
94
-
95
- protected listJoin(path: string[]): string {
96
- if (!path) {
97
- throw new Error("当前路径不能为空");
98
- }
99
- const filtered = path.filter((e) => e.charAt(0) !== "[");
100
- return filtered.join(MERGE_PATH);
101
- }
102
- }
@@ -1,71 +0,0 @@
1
- import { describe, it, expect } from "bun:test";
2
- import { Injector } from "@wendellhu/redi";
3
- import {
4
- IComparatorOrchestrator,
5
- IObjectComparator,
6
- IArrayComparator,
7
- IPrimitiveComparator,
8
- INullComparator,
9
- IOtherComparator,
10
- IDiffService,
11
- } from "../../../contract/type";
12
- import { ComparatorOrchestrator } from "../ComparatorOrchestrator";
13
- import { LeftJoinObjectComparator } from "./LeftJoinObjectComparator";
14
- import { SimilarArrayComparator } from "../array/SimilarArrayComparator";
15
- import { DefaultPrimitiveComparator } from "../primitive/DefaultPrimitiveComparator";
16
- import { DefaultNullComparator } from "../nulls/DefaultNullComparator";
17
- import { DefaultOtherComparator } from "../other/DefaultOtherComparator";
18
- import { DiffService } from "../../diff/DiffService";
19
-
20
- function createLeftJoinDiffService(): IDiffService {
21
- const injector = new Injector([
22
- [IComparatorOrchestrator, { useClass: ComparatorOrchestrator, lazy: true }],
23
- [IObjectComparator, { useClass: LeftJoinObjectComparator }],
24
- [IArrayComparator, { useClass: SimilarArrayComparator }],
25
- [IPrimitiveComparator, { useClass: DefaultPrimitiveComparator }],
26
- [INullComparator, { useClass: DefaultNullComparator }],
27
- [IOtherComparator, { useClass: DefaultOtherComparator }],
28
- [IDiffService, { useClass: DiffService }],
29
- ]);
30
- return injector.get(IDiffService);
31
- }
32
-
33
- describe("LeftJoinObjectComparator", () => {
34
- it("should only compare keys from left object", () => {
35
- const left = { a: 1, b: 2 };
36
- const right = { a: 1, b: 2, c: 3 };
37
-
38
- const diffService = createLeftJoinDiffService();
39
- const results = diffService.diffElement(left, right);
40
-
41
- expect(results.length).toEqual(1);
42
- expect(results[0].rightPath).toBe("c");
43
- expect(results[0].diffType).toBe("ADD");
44
- });
45
-
46
- it("should detect changes in left keys", () => {
47
- const left = { a: 1, b: 2 };
48
- const right = { a: 2, b: 2, c: 3 };
49
-
50
- const diffService = createLeftJoinDiffService();
51
- const results = diffService.diffElement(left, right);
52
-
53
- expect(results.length).toBe(2);
54
- expect(results[0].leftPath).toBe("a");
55
- expect(results[0].diffType).toBe("MODIFY");
56
- expect(results[1].rightPath).toBe("c");
57
- expect(results[1].diffType).toBe("ADD");
58
- });
59
-
60
- it("should detect missing keys in right object", () => {
61
- const left = { a: 1, b: 2 };
62
- const right = { a: 1 };
63
-
64
- const diffService = createLeftJoinDiffService();
65
- const results = diffService.diffElement(left, right);
66
-
67
- expect(results.length).toBe(1);
68
- expect(results[0].leftPath).toBe("b");
69
- expect(results[0].diffType).toBe("DELETE");
70
- });
71
- });
@@ -1,18 +0,0 @@
1
- import { Inject } from "@wendellhu/redi";
2
- import { AbstractObject } from "./AbstractObject";
3
- import { DiffContext } from "../../diff/DiffContext";
4
- import type { PathTracker } from "../../diff/PathTracker";
5
- import { type JsonObject, IComparatorOrchestrator } from "#contract";
6
-
7
-
8
- export class LeftJoinObjectComparator extends AbstractObject {
9
- constructor(
10
- @Inject(IComparatorOrchestrator) orchestrator: IComparatorOrchestrator
11
- ) {
12
- super(orchestrator);
13
- }
14
-
15
- diff(a: JsonObject, b: JsonObject, pathTracker: PathTracker): DiffContext {
16
- return this.diffValueByKey(a, b, new Set(Object.keys(a)), pathTracker);
17
- }
18
- }
@@ -1,20 +0,0 @@
1
- import { describe, it, expect } from "bun:test";
2
- import { DiffService } from "../../diff/DiffService";
3
-
4
- describe("UnionKeyObjectComparator", () => {
5
- it("should compare all keys from both objects", () => {
6
- const left = { a: 1, b: 2 };
7
- const right = { b: 2, c: 3 };
8
-
9
- const diffService = new DiffService();
10
- const results = diffService.diffElement(left, right);
11
-
12
- expect(results.length).toBe(2);
13
-
14
- const deleteResult = results.find((r) => r.diffType === "DELETE");
15
- const addResult = results.find((r) => r.diffType === "ADD");
16
-
17
- expect(deleteResult?.leftPath).toBe("a");
18
- expect(addResult?.rightPath).toBe("c");
19
- });
20
- });
@@ -1,19 +0,0 @@
1
- import { Inject } from "@wendellhu/redi";
2
- import { AbstractObject } from "./AbstractObject";
3
- import { DiffContext } from "../../diff/DiffContext";
4
- import type { PathTracker } from "../../diff/PathTracker";
5
- import type { JsonObject, IComparatorOrchestrator } from "../../../contract/type";
6
- import { IComparatorOrchestrator as IComparatorOrchestratorToken } from "../../../contract/type";
7
-
8
- export class UnionKeyObjectComparator extends AbstractObject {
9
- constructor(
10
- @Inject(IComparatorOrchestratorToken) orchestrator: IComparatorOrchestrator
11
- ) {
12
- super(orchestrator);
13
- }
14
-
15
- diff(a: JsonObject, b: JsonObject, pathTracker: PathTracker): DiffContext {
16
- const unionSet = new Set<string>([...Object.keys(a), ...Object.keys(b)]);
17
- return this.diffValueByKey(a, b, unionSet, pathTracker);
18
- }
19
- }
@@ -1,3 +0,0 @@
1
- export * from "./AbstractObject";
2
- export * from "./UnionKeyObjectComparator";
3
- export * from "./LeftJoinObjectComparator";