@diffson/core 1.0.3 → 1.0.5

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 (79) hide show
  1. package/dist/contract/constant/DiffConstants.d.ts +8 -0
  2. package/dist/contract/constant/DiffConstants.js +8 -0
  3. package/dist/contract/constant/PresetName.d.ts +6 -0
  4. package/dist/contract/constant/PresetName.js +7 -0
  5. package/dist/contract/constant/index.d.ts +2 -0
  6. package/dist/contract/constant/index.js +2 -0
  7. package/dist/contract/index.d.ts +2 -0
  8. package/dist/contract/index.js +2 -0
  9. package/dist/contract/type/ArrayComparator.d.ts +8 -0
  10. package/dist/contract/type/ArrayComparator.js +2 -0
  11. package/dist/contract/type/ComparatorOrchestrator.d.ts +9 -0
  12. package/dist/contract/type/ComparatorOrchestrator.js +2 -0
  13. package/dist/contract/type/DiffService.d.ts +27 -0
  14. package/dist/contract/type/DiffService.js +2 -0
  15. package/dist/contract/type/JsonTypes.d.ts +5 -0
  16. package/dist/contract/type/JsonTypes.js +1 -0
  17. package/dist/contract/type/NullComparator.d.ts +6 -0
  18. package/dist/contract/type/NullComparator.js +2 -0
  19. package/dist/contract/type/ObjectComparator.d.ts +8 -0
  20. package/dist/contract/type/ObjectComparator.js +2 -0
  21. package/dist/contract/type/OtherComparator.d.ts +7 -0
  22. package/dist/contract/type/OtherComparator.js +2 -0
  23. package/dist/contract/type/PrimitiveComparator.d.ts +6 -0
  24. package/dist/contract/type/PrimitiveComparator.js +2 -0
  25. package/dist/contract/type/Result.d.ts +7 -0
  26. package/dist/contract/type/Result.js +7 -0
  27. package/dist/contract/type/SingleNodeDifference.d.ts +7 -0
  28. package/dist/contract/type/SingleNodeDifference.js +12 -0
  29. package/dist/contract/type/index.d.ts +10 -0
  30. package/dist/contract/type/index.js +10 -0
  31. package/dist/index.d.ts +6 -0
  32. package/dist/index.js +8 -0
  33. package/dist/service/comparator/ComparatorOrchestrator.d.ts +13 -0
  34. package/dist/service/comparator/ComparatorOrchestrator.js +55 -0
  35. package/dist/service/comparator/array/AbstractArray.d.ts +11 -0
  36. package/dist/service/comparator/array/AbstractArray.js +40 -0
  37. package/dist/service/comparator/array/SequentialArrayComparator.d.ts +9 -0
  38. package/dist/service/comparator/array/SequentialArrayComparator.js +49 -0
  39. package/dist/service/comparator/array/SimilarArrayComparator.d.ts +21 -0
  40. package/dist/service/comparator/array/SimilarArrayComparator.js +152 -0
  41. package/dist/service/comparator/array/index.d.ts +3 -0
  42. package/dist/service/comparator/array/index.js +3 -0
  43. package/dist/service/comparator/index.d.ts +6 -0
  44. package/dist/service/comparator/index.js +6 -0
  45. package/dist/service/comparator/nulls/DefaultNullComparator.d.ts +6 -0
  46. package/dist/service/comparator/nulls/DefaultNullComparator.js +6 -0
  47. package/dist/service/comparator/nulls/index.d.ts +1 -0
  48. package/dist/service/comparator/nulls/index.js +1 -0
  49. package/dist/service/comparator/object/AbstractObject.d.ts +16 -0
  50. package/dist/service/comparator/object/AbstractObject.js +90 -0
  51. package/dist/service/comparator/object/LeftJoinObjectComparator.d.ts +8 -0
  52. package/dist/service/comparator/object/LeftJoinObjectComparator.js +25 -0
  53. package/dist/service/comparator/object/UnionKeyObjectComparator.d.ts +8 -0
  54. package/dist/service/comparator/object/UnionKeyObjectComparator.js +26 -0
  55. package/dist/service/comparator/object/index.d.ts +3 -0
  56. package/dist/service/comparator/object/index.js +3 -0
  57. package/dist/service/comparator/other/DefaultOtherComparator.d.ts +6 -0
  58. package/dist/service/comparator/other/DefaultOtherComparator.js +13 -0
  59. package/dist/service/comparator/other/index.d.ts +1 -0
  60. package/dist/service/comparator/other/index.js +1 -0
  61. package/dist/service/comparator/primitive/DefaultPrimitiveComparator.d.ts +6 -0
  62. package/dist/service/comparator/primitive/DefaultPrimitiveComparator.js +16 -0
  63. package/dist/service/comparator/primitive/index.d.ts +1 -0
  64. package/dist/service/comparator/primitive/index.js +1 -0
  65. package/dist/service/diff/DiffContext.d.ts +13 -0
  66. package/dist/service/diff/DiffContext.js +29 -0
  67. package/dist/service/diff/DiffService.d.ts +26 -0
  68. package/dist/service/diff/DiffService.js +184 -0
  69. package/dist/service/diff/PathTracker.d.ts +21 -0
  70. package/dist/service/diff/PathTracker.js +56 -0
  71. package/dist/service/diff/index.d.ts +1 -0
  72. package/dist/service/diff/index.js +1 -0
  73. package/dist/service/index.d.ts +2 -0
  74. package/dist/service/index.js +2 -0
  75. package/dist/util/TypeGuards.d.ts +6 -0
  76. package/dist/util/TypeGuards.js +32 -0
  77. package/dist/util/index.d.ts +1 -0
  78. package/dist/util/index.js +1 -0
  79. package/package.json +6 -4
@@ -0,0 +1,6 @@
1
+ export * from "./ComparatorOrchestrator";
2
+ export * from "./array";
3
+ export * from "./object";
4
+ export * from "./primitive";
5
+ export * from "./nulls";
6
+ export * from "./other";
@@ -0,0 +1,6 @@
1
+ import type { INullComparator } from "../../../contract/type";
2
+ import { DiffContext } from "../../diff/DiffContext";
3
+ import type { PathTracker } from "../../diff/PathTracker";
4
+ export declare class DefaultNullComparator implements INullComparator {
5
+ diff(_a: null, _b: null, _pathTracker: PathTracker): DiffContext;
6
+ }
@@ -0,0 +1,6 @@
1
+ import { DiffContext } from "../../diff/DiffContext";
2
+ export class DefaultNullComparator {
3
+ diff(_a, _b, _pathTracker) {
4
+ return new DiffContext();
5
+ }
6
+ }
@@ -0,0 +1 @@
1
+ export * from "./DefaultNullComparator";
@@ -0,0 +1 @@
1
+ export * from "./DefaultNullComparator";
@@ -0,0 +1,16 @@
1
+ import type { IObjectComparator, IComparatorOrchestrator, JsonObject, JsonValue } from "../../../contract/type";
2
+ import { DiffContext } from "../../diff/DiffContext";
3
+ import type { PathTracker } from "../../diff/PathTracker";
4
+ export declare abstract class AbstractObject implements IObjectComparator {
5
+ protected orchestrator: IComparatorOrchestrator;
6
+ constructor(orchestrator: IComparatorOrchestrator);
7
+ abstract diff(a: JsonObject, b: JsonObject, pathTracker: PathTracker): DiffContext;
8
+ diffElement(a: JsonValue | undefined, b: JsonValue | undefined, pathTracker: PathTracker): DiffContext;
9
+ protected parentContextAddChildContext(parentResult: DiffContext, childResult: DiffContext): void;
10
+ protected diffValueByKey(a: JsonObject, b: JsonObject, keySet: Set<string>, pathTracker: PathTracker): DiffContext;
11
+ private specialPathHandle;
12
+ private existPath;
13
+ protected getSpecialPath(pathTracker: PathTracker): string | null;
14
+ protected needDiff(noisePahList: string[] | null, pathList: string[]): boolean;
15
+ protected listJoin(path: string[]): string;
16
+ }
@@ -0,0 +1,90 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
+ return function (target, key) { decorator(target, key, paramIndex); }
9
+ };
10
+ import { Inject } from "@wendellhu/redi";
11
+ import { IComparatorOrchestrator as IComparatorOrchestratorToken } from "../../../contract/type";
12
+ import { DiffContext } from "../../diff/DiffContext";
13
+ import { DIFFERENT, MERGE_PATH } from "../../../contract/constant";
14
+ let AbstractObject = class AbstractObject {
15
+ orchestrator;
16
+ constructor(orchestrator) {
17
+ this.orchestrator = orchestrator;
18
+ }
19
+ diffElement(a, b, pathTracker) {
20
+ return this.orchestrator.diffElement(a, b, pathTracker);
21
+ }
22
+ parentContextAddChildContext(parentResult, childResult) {
23
+ if (childResult.isSame() === DIFFERENT) {
24
+ for (const singleNodeDifference of childResult.getDiffResultModels()) {
25
+ parentResult.getDiffResultModels().push(singleNodeDifference);
26
+ }
27
+ parentResult.setSame(false);
28
+ }
29
+ }
30
+ diffValueByKey(a, b, keySet, pathTracker) {
31
+ const objectDiffContext = new DiffContext();
32
+ const specialPathResult = [];
33
+ for (const key of keySet) {
34
+ pathTracker.addAllpath(key);
35
+ if (!this.needDiff(pathTracker.getNoisePahList(), pathTracker.getLeftPath())) {
36
+ pathTracker.removeAllLastPath();
37
+ continue;
38
+ }
39
+ const diffContext = this.diffElement(a[key], b[key], pathTracker);
40
+ this.parentContextAddChildContext(objectDiffContext, diffContext);
41
+ this.specialPathHandle(diffContext.isSame(), specialPathResult, pathTracker);
42
+ pathTracker.removeAllLastPath();
43
+ }
44
+ objectDiffContext.setSpecialPathResult(specialPathResult);
45
+ return objectDiffContext;
46
+ }
47
+ specialPathHandle(isSame, specialPathResult, pathTracker) {
48
+ if (!isSame) {
49
+ return;
50
+ }
51
+ const specialPath = this.getSpecialPath(pathTracker);
52
+ if (this.existPath(specialPath)) {
53
+ specialPathResult.push(specialPath);
54
+ }
55
+ }
56
+ existPath(specialPath) {
57
+ return specialPath !== null;
58
+ }
59
+ getSpecialPath(pathTracker) {
60
+ if (!pathTracker || !pathTracker.getSpecialPath() || pathTracker.getSpecialPath().length === 0) {
61
+ return null;
62
+ }
63
+ const currentPath = this.listJoin(pathTracker.getLeftPath());
64
+ if (pathTracker.getSpecialPath().includes(currentPath)) {
65
+ return currentPath;
66
+ }
67
+ return null;
68
+ }
69
+ needDiff(noisePahList, pathList) {
70
+ if (!noisePahList || !pathList || noisePahList.length === 0 || pathList.length === 0) {
71
+ return true;
72
+ }
73
+ const path = this.listJoin(pathList);
74
+ if (noisePahList.includes(path)) {
75
+ return false;
76
+ }
77
+ return true;
78
+ }
79
+ listJoin(path) {
80
+ if (!path) {
81
+ throw new Error("当前路径不能为空");
82
+ }
83
+ const filtered = path.filter((e) => e.charAt(0) !== "[");
84
+ return filtered.join(MERGE_PATH);
85
+ }
86
+ };
87
+ AbstractObject = __decorate([
88
+ __param(0, Inject(IComparatorOrchestratorToken))
89
+ ], AbstractObject);
90
+ export { AbstractObject };
@@ -0,0 +1,8 @@
1
+ import { AbstractObject } from "./AbstractObject";
2
+ import { DiffContext } from "../../diff/DiffContext";
3
+ import type { PathTracker } from "../../diff/PathTracker";
4
+ import { type JsonObject, IComparatorOrchestrator } from "#contract";
5
+ export declare class LeftJoinObjectComparator extends AbstractObject {
6
+ constructor(orchestrator: IComparatorOrchestrator);
7
+ diff(a: JsonObject, b: JsonObject, pathTracker: PathTracker): DiffContext;
8
+ }
@@ -0,0 +1,25 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
+ return function (target, key) { decorator(target, key, paramIndex); }
9
+ };
10
+ import { Inject } from "@wendellhu/redi";
11
+ import { AbstractObject } from "./AbstractObject";
12
+ import { DiffContext } from "../../diff/DiffContext";
13
+ import { IComparatorOrchestrator } from "#contract";
14
+ let LeftJoinObjectComparator = class LeftJoinObjectComparator extends AbstractObject {
15
+ constructor(orchestrator) {
16
+ super(orchestrator);
17
+ }
18
+ diff(a, b, pathTracker) {
19
+ return this.diffValueByKey(a, b, new Set(Object.keys(a)), pathTracker);
20
+ }
21
+ };
22
+ LeftJoinObjectComparator = __decorate([
23
+ __param(0, Inject(IComparatorOrchestrator))
24
+ ], LeftJoinObjectComparator);
25
+ export { LeftJoinObjectComparator };
@@ -0,0 +1,8 @@
1
+ import { AbstractObject } from "./AbstractObject";
2
+ import { DiffContext } from "../../diff/DiffContext";
3
+ import type { PathTracker } from "../../diff/PathTracker";
4
+ import type { JsonObject, IComparatorOrchestrator } from "../../../contract/type";
5
+ export declare class UnionKeyObjectComparator extends AbstractObject {
6
+ constructor(orchestrator: IComparatorOrchestrator);
7
+ diff(a: JsonObject, b: JsonObject, pathTracker: PathTracker): DiffContext;
8
+ }
@@ -0,0 +1,26 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
+ return function (target, key) { decorator(target, key, paramIndex); }
9
+ };
10
+ import { Inject } from "@wendellhu/redi";
11
+ import { AbstractObject } from "./AbstractObject";
12
+ import { DiffContext } from "../../diff/DiffContext";
13
+ import { IComparatorOrchestrator as IComparatorOrchestratorToken } from "../../../contract/type";
14
+ let UnionKeyObjectComparator = class UnionKeyObjectComparator extends AbstractObject {
15
+ constructor(orchestrator) {
16
+ super(orchestrator);
17
+ }
18
+ diff(a, b, pathTracker) {
19
+ const unionSet = new Set([...Object.keys(a), ...Object.keys(b)]);
20
+ return this.diffValueByKey(a, b, unionSet, pathTracker);
21
+ }
22
+ };
23
+ UnionKeyObjectComparator = __decorate([
24
+ __param(0, Inject(IComparatorOrchestratorToken))
25
+ ], UnionKeyObjectComparator);
26
+ export { UnionKeyObjectComparator };
@@ -0,0 +1,3 @@
1
+ export * from "./AbstractObject";
2
+ export * from "./UnionKeyObjectComparator";
3
+ export * from "./LeftJoinObjectComparator";
@@ -0,0 +1,3 @@
1
+ export * from "./AbstractObject";
2
+ export * from "./UnionKeyObjectComparator";
3
+ export * from "./LeftJoinObjectComparator";
@@ -0,0 +1,6 @@
1
+ import type { IOtherComparator, JsonValue } from "../../../contract/type";
2
+ import { DiffContext } from "../../diff/DiffContext";
3
+ import type { PathTracker } from "../../diff/PathTracker";
4
+ export declare class DefaultOtherComparator implements IOtherComparator {
5
+ diff(a: JsonValue | undefined, b: JsonValue | undefined, pathTracker: PathTracker): DiffContext;
6
+ }
@@ -0,0 +1,13 @@
1
+ import { DiffContext } from "../../diff/DiffContext";
2
+ import { SingleNodeDifference } from "../../../contract/type";
3
+ import { DIFFERENT, MERGE_PATH } from "../../../contract/constant";
4
+ import { jsonElement2Str } from "../../../util";
5
+ export class DefaultOtherComparator {
6
+ diff(a, b, pathTracker) {
7
+ const otherDiffContext = new DiffContext(DIFFERENT);
8
+ const singleNodeDifferences = [];
9
+ singleNodeDifferences.push(new SingleNodeDifference(pathTracker.getLeftPath().join(MERGE_PATH), pathTracker.getRightPath().join(MERGE_PATH), jsonElement2Str(a), jsonElement2Str(b)));
10
+ otherDiffContext.setDiffResultModels(singleNodeDifferences);
11
+ return otherDiffContext;
12
+ }
13
+ }
@@ -0,0 +1 @@
1
+ export * from "./DefaultOtherComparator";
@@ -0,0 +1 @@
1
+ export * from "./DefaultOtherComparator";
@@ -0,0 +1,6 @@
1
+ import type { IPrimitiveComparator } from "../../../contract/type";
2
+ import { DiffContext } from "../../diff/DiffContext";
3
+ import type { PathTracker } from "../../diff/PathTracker";
4
+ export declare class DefaultPrimitiveComparator implements IPrimitiveComparator {
5
+ diff(a: string | number | boolean, b: string | number | boolean, pathTracker: PathTracker): DiffContext;
6
+ }
@@ -0,0 +1,16 @@
1
+ import { DiffContext } from "../../diff/DiffContext";
2
+ import { SingleNodeDifference } from "../../../contract/type";
3
+ import { DIFFERENT, MERGE_PATH } from "../../../contract/constant";
4
+ import { jsonElement2Str } from "../../../util";
5
+ export class DefaultPrimitiveComparator {
6
+ diff(a, b, pathTracker) {
7
+ const primitiveDiffContext = new DiffContext();
8
+ if (a !== b) {
9
+ const singleNodeDifferences = [];
10
+ singleNodeDifferences.push(new SingleNodeDifference(pathTracker.getLeftPath().join(MERGE_PATH), pathTracker.getRightPath().join(MERGE_PATH), jsonElement2Str(a), jsonElement2Str(b)));
11
+ primitiveDiffContext.setDiffResultModels(singleNodeDifferences);
12
+ primitiveDiffContext.setSame(DIFFERENT);
13
+ }
14
+ return primitiveDiffContext;
15
+ }
16
+ }
@@ -0,0 +1 @@
1
+ export * from "./DefaultPrimitiveComparator";
@@ -0,0 +1 @@
1
+ export * from "./DefaultPrimitiveComparator";
@@ -0,0 +1,13 @@
1
+ import { SingleNodeDifference } from "../../contract/type";
2
+ export declare class DiffContext {
3
+ private _isSame;
4
+ private singleNodeDifferences;
5
+ private specialPathResult;
6
+ constructor(isSame?: boolean);
7
+ isSame(): boolean;
8
+ setSame(same: boolean): void;
9
+ getDiffResultModels(): SingleNodeDifference[];
10
+ setDiffResultModels(singleNodeDifferences: SingleNodeDifference[]): void;
11
+ getSpecialPathResult(): string[] | null;
12
+ setSpecialPathResult(specialPathResult: string[]): void;
13
+ }
@@ -0,0 +1,29 @@
1
+ import { SingleNodeDifference } from "../../contract/type";
2
+ export class DiffContext {
3
+ _isSame;
4
+ singleNodeDifferences;
5
+ specialPathResult;
6
+ constructor(isSame = true) {
7
+ this._isSame = isSame;
8
+ this.singleNodeDifferences = [];
9
+ this.specialPathResult = null;
10
+ }
11
+ isSame() {
12
+ return this._isSame;
13
+ }
14
+ setSame(same) {
15
+ this._isSame = same;
16
+ }
17
+ getDiffResultModels() {
18
+ return this.singleNodeDifferences;
19
+ }
20
+ setDiffResultModels(singleNodeDifferences) {
21
+ this.singleNodeDifferences = singleNodeDifferences;
22
+ }
23
+ getSpecialPathResult() {
24
+ return this.specialPathResult;
25
+ }
26
+ setSpecialPathResult(specialPathResult) {
27
+ this.specialPathResult = specialPathResult;
28
+ }
29
+ }
@@ -0,0 +1,26 @@
1
+ import { type JsonValue, Result, type IDiffService, IComparatorOrchestrator, IObjectComparator, IArrayComparator, IPrimitiveComparator, INullComparator, IOtherComparator, PresetName } from "#contract";
2
+ export declare class DiffService implements IDiffService {
3
+ private config;
4
+ constructor(preset?: PresetName);
5
+ withObjectComparator(cls: new (orchestrator: IComparatorOrchestrator) => IObjectComparator): this;
6
+ withArrayComparator(cls: new (orchestrator: IComparatorOrchestrator) => IArrayComparator): this;
7
+ withPrimitiveComparator(cls: new () => IPrimitiveComparator): this;
8
+ withNullComparator(cls: new () => INullComparator): this;
9
+ withOtherComparator(cls: new () => IOtherComparator): this;
10
+ diffJson(leftJson: string, rightJson: string, options?: {
11
+ noisePath?: string[];
12
+ specialPath?: string[];
13
+ parseNestedJson?: boolean;
14
+ }): Result[];
15
+ diffElement(left: JsonValue, right: JsonValue, options?: {
16
+ noisePath?: string[];
17
+ specialPath?: string[];
18
+ parseNestedJson?: boolean;
19
+ }): Result[];
20
+ private getOrCreateOrchestrator;
21
+ private constructResult;
22
+ private convert;
23
+ private compareInternal;
24
+ private splitPath;
25
+ private parseNestedJsonStrings;
26
+ }
@@ -0,0 +1,184 @@
1
+ import isJSON from "is-json";
2
+ import { Injector } from "@wendellhu/redi";
3
+ import { Result, SingleNodeDifference, IComparatorOrchestrator, IObjectComparator, IArrayComparator, IPrimitiveComparator, INullComparator, IOtherComparator, PresetName, } from "#contract";
4
+ import { SPLIT_PATH, OBJECT_NULL, TYPE_MODIFY, TYPE_ADD, TYPE_DELETE } from "#contract";
5
+ import { DiffContext } from "./DiffContext";
6
+ import { PathTracker } from "./PathTracker";
7
+ import { ComparatorOrchestrator } from "../comparator/ComparatorOrchestrator";
8
+ import { UnionKeyObjectComparator } from "../comparator/object/UnionKeyObjectComparator";
9
+ import { LeftJoinObjectComparator } from "../comparator/object/LeftJoinObjectComparator";
10
+ import { SimilarArrayComparator } from "../comparator/array/SimilarArrayComparator";
11
+ import { SequentialArrayComparator } from "../comparator/array/SequentialArrayComparator";
12
+ import { DefaultPrimitiveComparator } from "../comparator/primitive/DefaultPrimitiveComparator";
13
+ import { DefaultNullComparator } from "../comparator/nulls/DefaultNullComparator";
14
+ import { DefaultOtherComparator } from "../comparator/other/DefaultOtherComparator";
15
+ export class DiffService {
16
+ config;
17
+ constructor(preset = PresetName.FullSmart) {
18
+ this.config = {
19
+ objectComparator: UnionKeyObjectComparator,
20
+ arrayComparator: SimilarArrayComparator,
21
+ primitiveComparator: DefaultPrimitiveComparator,
22
+ nullComparator: DefaultNullComparator,
23
+ otherComparator: DefaultOtherComparator,
24
+ };
25
+ switch (preset) {
26
+ case PresetName.FullOrdered:
27
+ this.config.arrayComparator = SequentialArrayComparator;
28
+ break;
29
+ case PresetName.LeftSmart:
30
+ this.config.objectComparator = LeftJoinObjectComparator;
31
+ break;
32
+ case PresetName.LeftOrdered:
33
+ this.config.objectComparator = LeftJoinObjectComparator;
34
+ this.config.arrayComparator = SequentialArrayComparator;
35
+ break;
36
+ case PresetName.FullSmart:
37
+ default:
38
+ this.config.objectComparator = UnionKeyObjectComparator;
39
+ this.config.arrayComparator = SimilarArrayComparator;
40
+ break;
41
+ }
42
+ }
43
+ withObjectComparator(cls) {
44
+ this.config.objectComparator = cls;
45
+ return this;
46
+ }
47
+ withArrayComparator(cls) {
48
+ this.config.arrayComparator = cls;
49
+ return this;
50
+ }
51
+ withPrimitiveComparator(cls) {
52
+ this.config.primitiveComparator = cls;
53
+ return this;
54
+ }
55
+ withNullComparator(cls) {
56
+ this.config.nullComparator = cls;
57
+ return this;
58
+ }
59
+ withOtherComparator(cls) {
60
+ this.config.otherComparator = cls;
61
+ return this;
62
+ }
63
+ diffJson(leftJson, rightJson, options) {
64
+ let left;
65
+ let right;
66
+ try {
67
+ left = JSON.parse(leftJson);
68
+ }
69
+ catch (error) {
70
+ throw new Error(`Failed to parse left JSON string: ${error instanceof Error ? error.message : String(error)}`);
71
+ }
72
+ try {
73
+ right = JSON.parse(rightJson);
74
+ }
75
+ catch (error) {
76
+ throw new Error(`Failed to parse right JSON string: ${error instanceof Error ? error.message : String(error)}`);
77
+ }
78
+ // 将解析后的对象和选项传递给 diffElement
79
+ return this.diffElement(left, right, options);
80
+ }
81
+ diffElement(left, right, options) {
82
+ // 如果启用递归解析嵌套 JSON
83
+ if (options?.parseNestedJson) {
84
+ left = this.parseNestedJsonStrings(left);
85
+ right = this.parseNestedJsonStrings(right);
86
+ }
87
+ const orchestrator = this.getOrCreateOrchestrator();
88
+ const diffContext = this.compareInternal(left, right, orchestrator, options);
89
+ return this.constructResult(diffContext);
90
+ }
91
+ getOrCreateOrchestrator() {
92
+ const injector = new Injector([
93
+ [IComparatorOrchestrator, { useClass: ComparatorOrchestrator, lazy: true }],
94
+ [IObjectComparator, { useClass: this.config.objectComparator }],
95
+ [IArrayComparator, { useClass: this.config.arrayComparator }],
96
+ [IPrimitiveComparator, { useClass: this.config.primitiveComparator }],
97
+ [INullComparator, { useClass: this.config.nullComparator }],
98
+ [IOtherComparator, { useClass: this.config.otherComparator }],
99
+ ]);
100
+ return injector.get(IComparatorOrchestrator);
101
+ }
102
+ constructResult(diffContext) {
103
+ const list = [];
104
+ for (const resultModel of diffContext.getDiffResultModels()) {
105
+ const printModel = this.convert(resultModel);
106
+ const leftAndRightBothNull = resultModel.left === OBJECT_NULL && resultModel.right === OBJECT_NULL;
107
+ if (leftAndRightBothNull) {
108
+ printModel.diffType = TYPE_MODIFY;
109
+ }
110
+ else if (resultModel.left === OBJECT_NULL) {
111
+ printModel.diffType = TYPE_ADD;
112
+ printModel.leftPath = null;
113
+ }
114
+ else if (resultModel.right === OBJECT_NULL) {
115
+ printModel.diffType = TYPE_DELETE;
116
+ printModel.rightPath = null;
117
+ }
118
+ else {
119
+ printModel.diffType = TYPE_MODIFY;
120
+ }
121
+ list.push(printModel);
122
+ }
123
+ return list;
124
+ }
125
+ convert(resultModel) {
126
+ const printModel = new Result();
127
+ printModel.left = resultModel.left;
128
+ printModel.right = resultModel.right;
129
+ printModel.leftPath = resultModel.leftPath;
130
+ printModel.rightPath = resultModel.rightPath;
131
+ return printModel;
132
+ }
133
+ compareInternal(left, right, orchestrator, options) {
134
+ const pathTracker = new PathTracker(null, null);
135
+ if (options?.noisePath) {
136
+ pathTracker.setNoisePahList(this.splitPath(options.noisePath));
137
+ }
138
+ if (options?.specialPath) {
139
+ pathTracker.setSpecialPath(this.splitPath(options.specialPath));
140
+ }
141
+ return orchestrator.diffElement(left, right, pathTracker);
142
+ }
143
+ splitPath(pathList) {
144
+ const result = [];
145
+ for (const path of pathList) {
146
+ const parts = path.split(SPLIT_PATH);
147
+ result.push(parts.join("."));
148
+ }
149
+ return result;
150
+ }
151
+ parseNestedJsonStrings(value) {
152
+ // 如果是字符串,尝试解析为 JSON
153
+ if (typeof value === "string") {
154
+ if (isJSON(value)) {
155
+ try {
156
+ const parsed = JSON.parse(value);
157
+ // 递归处理解析后的值
158
+ return this.parseNestedJsonStrings(parsed);
159
+ }
160
+ catch {
161
+ // 如果解析失败,返回原字符串
162
+ return value;
163
+ }
164
+ }
165
+ return value;
166
+ }
167
+ // 如果是数组,递归处理每个元素
168
+ if (Array.isArray(value)) {
169
+ return value.map(item => this.parseNestedJsonStrings(item));
170
+ }
171
+ // 如果是对象,递归处理每个属性值
172
+ if (typeof value === "object" && value !== null) {
173
+ const result = {};
174
+ for (const key in value) {
175
+ if (Object.prototype.hasOwnProperty.call(value, key)) {
176
+ result[key] = this.parseNestedJsonStrings(value[key]);
177
+ }
178
+ }
179
+ return result;
180
+ }
181
+ // 其他类型(number, boolean, null)直接返回
182
+ return value;
183
+ }
184
+ }
@@ -0,0 +1,21 @@
1
+ export declare class PathTracker {
2
+ private leftPath;
3
+ private rightPath;
4
+ private specialPath;
5
+ private noisePahList;
6
+ constructor(noisePahList?: string[] | null, specialPath?: string[] | null);
7
+ getNoisePahList(): string[] | null;
8
+ setNoisePahList(noisePahList: string[]): void;
9
+ getSpecialPath(): string[] | null;
10
+ setSpecialPath(specialPath: string[]): void;
11
+ getLeftPath(): string[];
12
+ setLeftPath(leftPath: string[]): void;
13
+ getRightPath(): string[];
14
+ setRightPath(rightPath: string[]): void;
15
+ addAllpath(lastPath: string): void;
16
+ addLeftPath(lastPath: string): void;
17
+ addRightPath(lastPath: string): void;
18
+ removeAllLastPath(): void;
19
+ removeLastLeftPath(): void;
20
+ removeLastRightPath(): void;
21
+ }
@@ -0,0 +1,56 @@
1
+ export class PathTracker {
2
+ leftPath;
3
+ rightPath;
4
+ specialPath;
5
+ noisePahList;
6
+ constructor(noisePahList = null, specialPath = null) {
7
+ this.leftPath = [];
8
+ this.rightPath = [];
9
+ this.noisePahList = noisePahList;
10
+ this.specialPath = specialPath;
11
+ }
12
+ getNoisePahList() {
13
+ return this.noisePahList;
14
+ }
15
+ setNoisePahList(noisePahList) {
16
+ this.noisePahList = noisePahList;
17
+ }
18
+ getSpecialPath() {
19
+ return this.specialPath;
20
+ }
21
+ setSpecialPath(specialPath) {
22
+ this.specialPath = specialPath;
23
+ }
24
+ getLeftPath() {
25
+ return this.leftPath;
26
+ }
27
+ setLeftPath(leftPath) {
28
+ this.leftPath = leftPath;
29
+ }
30
+ getRightPath() {
31
+ return this.rightPath;
32
+ }
33
+ setRightPath(rightPath) {
34
+ this.rightPath = rightPath;
35
+ }
36
+ addAllpath(lastPath) {
37
+ this.leftPath.push(lastPath);
38
+ this.rightPath.push(lastPath);
39
+ }
40
+ addLeftPath(lastPath) {
41
+ this.leftPath.push(lastPath);
42
+ }
43
+ addRightPath(lastPath) {
44
+ this.rightPath.push(lastPath);
45
+ }
46
+ removeAllLastPath() {
47
+ this.leftPath.pop();
48
+ this.rightPath.pop();
49
+ }
50
+ removeLastLeftPath() {
51
+ this.leftPath.pop();
52
+ }
53
+ removeLastRightPath() {
54
+ this.rightPath.pop();
55
+ }
56
+ }
@@ -0,0 +1 @@
1
+ export * from "./DiffService";
@@ -0,0 +1 @@
1
+ export * from "./DiffService";
@@ -0,0 +1,2 @@
1
+ export * from "./diff";
2
+ export * from "./comparator";
@@ -0,0 +1,2 @@
1
+ export * from "./diff";
2
+ export * from "./comparator";
@@ -0,0 +1,6 @@
1
+ import type { JsonValue, JsonObject, JsonArray } from "../contract/type";
2
+ export declare function isJsonObject(value: JsonValue | undefined): value is JsonObject;
3
+ export declare function isJsonArray(value: JsonValue | undefined): value is JsonArray;
4
+ export declare function isJsonPrimitive(value: JsonValue | undefined): value is string | number | boolean;
5
+ export declare function isJsonNull(value: JsonValue | undefined): value is null;
6
+ export declare function jsonElement2Str(element: JsonValue | undefined): string | null;