@diffson/core 1.0.0

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 (211) hide show
  1. package/.turbo/turbo-build.log +1 -0
  2. package/.turbo/turbo-test.log +96 -0
  3. package/.turbo/turbo-typecheck.log +2 -0
  4. package/dist/contract/constant/DiffConstants.d.ts +9 -0
  5. package/dist/contract/constant/DiffConstants.d.ts.map +1 -0
  6. package/dist/contract/constant/DiffConstants.js +9 -0
  7. package/dist/contract/constant/DiffConstants.js.map +1 -0
  8. package/dist/contract/constant/PresetName.d.ts +7 -0
  9. package/dist/contract/constant/PresetName.d.ts.map +1 -0
  10. package/dist/contract/constant/PresetName.js +8 -0
  11. package/dist/contract/constant/PresetName.js.map +1 -0
  12. package/dist/contract/constant/index.d.ts +3 -0
  13. package/dist/contract/constant/index.d.ts.map +1 -0
  14. package/dist/contract/constant/index.js +3 -0
  15. package/dist/contract/constant/index.js.map +1 -0
  16. package/dist/contract/index.d.ts +3 -0
  17. package/dist/contract/index.d.ts.map +1 -0
  18. package/dist/contract/index.js +3 -0
  19. package/dist/contract/index.js.map +1 -0
  20. package/dist/contract/type/ArrayComparator.d.ts +9 -0
  21. package/dist/contract/type/ArrayComparator.d.ts.map +1 -0
  22. package/dist/contract/type/ArrayComparator.js +3 -0
  23. package/dist/contract/type/ArrayComparator.js.map +1 -0
  24. package/dist/contract/type/ComparatorOrchestrator.d.ts +10 -0
  25. package/dist/contract/type/ComparatorOrchestrator.d.ts.map +1 -0
  26. package/dist/contract/type/ComparatorOrchestrator.js +3 -0
  27. package/dist/contract/type/ComparatorOrchestrator.js.map +1 -0
  28. package/dist/contract/type/DiffService.d.ts +28 -0
  29. package/dist/contract/type/DiffService.d.ts.map +1 -0
  30. package/dist/contract/type/DiffService.js +3 -0
  31. package/dist/contract/type/DiffService.js.map +1 -0
  32. package/dist/contract/type/JsonTypes.d.ts +6 -0
  33. package/dist/contract/type/JsonTypes.d.ts.map +1 -0
  34. package/dist/contract/type/JsonTypes.js +2 -0
  35. package/dist/contract/type/JsonTypes.js.map +1 -0
  36. package/dist/contract/type/NullComparator.d.ts +7 -0
  37. package/dist/contract/type/NullComparator.d.ts.map +1 -0
  38. package/dist/contract/type/NullComparator.js +3 -0
  39. package/dist/contract/type/NullComparator.js.map +1 -0
  40. package/dist/contract/type/ObjectComparator.d.ts +9 -0
  41. package/dist/contract/type/ObjectComparator.d.ts.map +1 -0
  42. package/dist/contract/type/ObjectComparator.js +3 -0
  43. package/dist/contract/type/ObjectComparator.js.map +1 -0
  44. package/dist/contract/type/OtherComparator.d.ts +8 -0
  45. package/dist/contract/type/OtherComparator.d.ts.map +1 -0
  46. package/dist/contract/type/OtherComparator.js +3 -0
  47. package/dist/contract/type/OtherComparator.js.map +1 -0
  48. package/dist/contract/type/PrimitiveComparator.d.ts +7 -0
  49. package/dist/contract/type/PrimitiveComparator.d.ts.map +1 -0
  50. package/dist/contract/type/PrimitiveComparator.js +3 -0
  51. package/dist/contract/type/PrimitiveComparator.js.map +1 -0
  52. package/dist/contract/type/Result.d.ts +8 -0
  53. package/dist/contract/type/Result.d.ts.map +1 -0
  54. package/dist/contract/type/Result.js +8 -0
  55. package/dist/contract/type/Result.js.map +1 -0
  56. package/dist/contract/type/SingleNodeDifference.d.ts +8 -0
  57. package/dist/contract/type/SingleNodeDifference.d.ts.map +1 -0
  58. package/dist/contract/type/SingleNodeDifference.js +13 -0
  59. package/dist/contract/type/SingleNodeDifference.js.map +1 -0
  60. package/dist/contract/type/index.d.ts +11 -0
  61. package/dist/contract/type/index.d.ts.map +1 -0
  62. package/dist/contract/type/index.js +11 -0
  63. package/dist/contract/type/index.js.map +1 -0
  64. package/dist/index.d.ts +7 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +9 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/service/comparator/ComparatorOrchestrator.d.ts +14 -0
  69. package/dist/service/comparator/ComparatorOrchestrator.d.ts.map +1 -0
  70. package/dist/service/comparator/ComparatorOrchestrator.js +56 -0
  71. package/dist/service/comparator/ComparatorOrchestrator.js.map +1 -0
  72. package/dist/service/comparator/array/AbstractArray.d.ts +12 -0
  73. package/dist/service/comparator/array/AbstractArray.d.ts.map +1 -0
  74. package/dist/service/comparator/array/AbstractArray.js +41 -0
  75. package/dist/service/comparator/array/AbstractArray.js.map +1 -0
  76. package/dist/service/comparator/array/SequentialArrayComparator.d.ts +10 -0
  77. package/dist/service/comparator/array/SequentialArrayComparator.d.ts.map +1 -0
  78. package/dist/service/comparator/array/SequentialArrayComparator.js +50 -0
  79. package/dist/service/comparator/array/SequentialArrayComparator.js.map +1 -0
  80. package/dist/service/comparator/array/SimilarArrayComparator.d.ts +22 -0
  81. package/dist/service/comparator/array/SimilarArrayComparator.d.ts.map +1 -0
  82. package/dist/service/comparator/array/SimilarArrayComparator.js +153 -0
  83. package/dist/service/comparator/array/SimilarArrayComparator.js.map +1 -0
  84. package/dist/service/comparator/array/index.d.ts +4 -0
  85. package/dist/service/comparator/array/index.d.ts.map +1 -0
  86. package/dist/service/comparator/array/index.js +4 -0
  87. package/dist/service/comparator/array/index.js.map +1 -0
  88. package/dist/service/comparator/index.d.ts +7 -0
  89. package/dist/service/comparator/index.d.ts.map +1 -0
  90. package/dist/service/comparator/index.js +7 -0
  91. package/dist/service/comparator/index.js.map +1 -0
  92. package/dist/service/comparator/nulls/DefaultNullComparator.d.ts +7 -0
  93. package/dist/service/comparator/nulls/DefaultNullComparator.d.ts.map +1 -0
  94. package/dist/service/comparator/nulls/DefaultNullComparator.js +7 -0
  95. package/dist/service/comparator/nulls/DefaultNullComparator.js.map +1 -0
  96. package/dist/service/comparator/nulls/index.d.ts +2 -0
  97. package/dist/service/comparator/nulls/index.d.ts.map +1 -0
  98. package/dist/service/comparator/nulls/index.js +2 -0
  99. package/dist/service/comparator/nulls/index.js.map +1 -0
  100. package/dist/service/comparator/object/AbstractObject.d.ts +17 -0
  101. package/dist/service/comparator/object/AbstractObject.d.ts.map +1 -0
  102. package/dist/service/comparator/object/AbstractObject.js +91 -0
  103. package/dist/service/comparator/object/AbstractObject.js.map +1 -0
  104. package/dist/service/comparator/object/LeftJoinObjectComparator.d.ts +9 -0
  105. package/dist/service/comparator/object/LeftJoinObjectComparator.d.ts.map +1 -0
  106. package/dist/service/comparator/object/LeftJoinObjectComparator.js +26 -0
  107. package/dist/service/comparator/object/LeftJoinObjectComparator.js.map +1 -0
  108. package/dist/service/comparator/object/UnionKeyObjectComparator.d.ts +9 -0
  109. package/dist/service/comparator/object/UnionKeyObjectComparator.d.ts.map +1 -0
  110. package/dist/service/comparator/object/UnionKeyObjectComparator.js +27 -0
  111. package/dist/service/comparator/object/UnionKeyObjectComparator.js.map +1 -0
  112. package/dist/service/comparator/object/index.d.ts +4 -0
  113. package/dist/service/comparator/object/index.d.ts.map +1 -0
  114. package/dist/service/comparator/object/index.js +4 -0
  115. package/dist/service/comparator/object/index.js.map +1 -0
  116. package/dist/service/comparator/other/DefaultOtherComparator.d.ts +7 -0
  117. package/dist/service/comparator/other/DefaultOtherComparator.d.ts.map +1 -0
  118. package/dist/service/comparator/other/DefaultOtherComparator.js +14 -0
  119. package/dist/service/comparator/other/DefaultOtherComparator.js.map +1 -0
  120. package/dist/service/comparator/other/index.d.ts +2 -0
  121. package/dist/service/comparator/other/index.d.ts.map +1 -0
  122. package/dist/service/comparator/other/index.js +2 -0
  123. package/dist/service/comparator/other/index.js.map +1 -0
  124. package/dist/service/comparator/primitive/DefaultPrimitiveComparator.d.ts +7 -0
  125. package/dist/service/comparator/primitive/DefaultPrimitiveComparator.d.ts.map +1 -0
  126. package/dist/service/comparator/primitive/DefaultPrimitiveComparator.js +17 -0
  127. package/dist/service/comparator/primitive/DefaultPrimitiveComparator.js.map +1 -0
  128. package/dist/service/comparator/primitive/index.d.ts +2 -0
  129. package/dist/service/comparator/primitive/index.d.ts.map +1 -0
  130. package/dist/service/comparator/primitive/index.js +2 -0
  131. package/dist/service/comparator/primitive/index.js.map +1 -0
  132. package/dist/service/diff/DiffContext.d.ts +14 -0
  133. package/dist/service/diff/DiffContext.d.ts.map +1 -0
  134. package/dist/service/diff/DiffContext.js +30 -0
  135. package/dist/service/diff/DiffContext.js.map +1 -0
  136. package/dist/service/diff/DiffService.d.ts +27 -0
  137. package/dist/service/diff/DiffService.d.ts.map +1 -0
  138. package/dist/service/diff/DiffService.js +185 -0
  139. package/dist/service/diff/DiffService.js.map +1 -0
  140. package/dist/service/diff/PathTracker.d.ts +22 -0
  141. package/dist/service/diff/PathTracker.d.ts.map +1 -0
  142. package/dist/service/diff/PathTracker.js +57 -0
  143. package/dist/service/diff/PathTracker.js.map +1 -0
  144. package/dist/service/diff/index.d.ts +2 -0
  145. package/dist/service/diff/index.d.ts.map +1 -0
  146. package/dist/service/diff/index.js +2 -0
  147. package/dist/service/diff/index.js.map +1 -0
  148. package/dist/service/index.d.ts +3 -0
  149. package/dist/service/index.d.ts.map +1 -0
  150. package/dist/service/index.js +3 -0
  151. package/dist/service/index.js.map +1 -0
  152. package/dist/util/TypeGuards.d.ts +7 -0
  153. package/dist/util/TypeGuards.d.ts.map +1 -0
  154. package/dist/util/TypeGuards.js +33 -0
  155. package/dist/util/TypeGuards.js.map +1 -0
  156. package/dist/util/index.d.ts +2 -0
  157. package/dist/util/index.d.ts.map +1 -0
  158. package/dist/util/index.js +2 -0
  159. package/dist/util/index.js.map +1 -0
  160. package/package.json +40 -0
  161. package/src/contract/constant/DiffConstants.ts +10 -0
  162. package/src/contract/constant/PresetName.ts +6 -0
  163. package/src/contract/constant/index.ts +2 -0
  164. package/src/contract/index.ts +2 -0
  165. package/src/contract/type/ArrayComparator.ts +15 -0
  166. package/src/contract/type/ComparatorOrchestrator.ts +16 -0
  167. package/src/contract/type/DiffService.ts +31 -0
  168. package/src/contract/type/JsonTypes.ts +3 -0
  169. package/src/contract/type/NullComparator.ts +9 -0
  170. package/src/contract/type/ObjectComparator.ts +15 -0
  171. package/src/contract/type/OtherComparator.ts +14 -0
  172. package/src/contract/type/PrimitiveComparator.ts +13 -0
  173. package/src/contract/type/Result.ts +7 -0
  174. package/src/contract/type/SingleNodeDifference.ts +13 -0
  175. package/src/contract/type/index.ts +10 -0
  176. package/src/index.ts +17 -0
  177. package/src/service/comparator/ComparatorOrchestrator.ts +50 -0
  178. package/src/service/comparator/array/AbstractArray.ts +34 -0
  179. package/src/service/comparator/array/SequentialArrayComparator.test.ts +46 -0
  180. package/src/service/comparator/array/SequentialArrayComparator.ts +48 -0
  181. package/src/service/comparator/array/SimilarArrayComparator.test.ts +37 -0
  182. package/src/service/comparator/array/SimilarArrayComparator.ts +211 -0
  183. package/src/service/comparator/array/index.ts +3 -0
  184. package/src/service/comparator/index.ts +6 -0
  185. package/src/service/comparator/nulls/DefaultNullComparator.test.ts +38 -0
  186. package/src/service/comparator/nulls/DefaultNullComparator.ts +9 -0
  187. package/src/service/comparator/nulls/index.ts +1 -0
  188. package/src/service/comparator/object/AbstractObject.ts +102 -0
  189. package/src/service/comparator/object/LeftJoinObjectComparator.test.ts +71 -0
  190. package/src/service/comparator/object/LeftJoinObjectComparator.ts +18 -0
  191. package/src/service/comparator/object/UnionKeyObjectComparator.test.ts +20 -0
  192. package/src/service/comparator/object/UnionKeyObjectComparator.ts +19 -0
  193. package/src/service/comparator/object/index.ts +3 -0
  194. package/src/service/comparator/other/DefaultOtherComparator.test.ts +48 -0
  195. package/src/service/comparator/other/DefaultOtherComparator.ts +23 -0
  196. package/src/service/comparator/other/index.ts +1 -0
  197. package/src/service/comparator/primitive/DefaultPrimitiveComparator.test.ts +50 -0
  198. package/src/service/comparator/primitive/DefaultPrimitiveComparator.ts +27 -0
  199. package/src/service/comparator/primitive/index.ts +1 -0
  200. package/src/service/diff/Diff.test.ts +113 -0
  201. package/src/service/diff/DiffContext.ts +37 -0
  202. package/src/service/diff/DiffService.test.ts +292 -0
  203. package/src/service/diff/DiffService.ts +245 -0
  204. package/src/service/diff/PathTracker.ts +71 -0
  205. package/src/service/diff/index.ts +1 -0
  206. package/src/service/index.ts +2 -0
  207. package/src/util/TypeGuards.test.ts +90 -0
  208. package/src/util/TypeGuards.ts +33 -0
  209. package/src/util/index.ts +1 -0
  210. package/tsconfig.json +11 -0
  211. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,2 @@
1
+ export * from "./TypeGuards";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@diffson/core",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "imports": {
8
+ "#contract": "./src/contract/index.ts",
9
+ "#service": "./src/service/index.ts"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "import": {
14
+ "@diffson/source": "./src/index.ts",
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ },
18
+ "require": {
19
+ "@diffson/source": "./src/index.ts",
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.js"
22
+ }
23
+ },
24
+ "./package.json": "./package.json"
25
+ },
26
+ "scripts": {
27
+ "build": "tsc",
28
+ "test": "bun test",
29
+ "typecheck": "tsc --noEmit",
30
+ "clean": "rm -rf dist node_modules"
31
+ },
32
+ "dependencies": {
33
+ "@wendellhu/redi": "latest",
34
+ "is-json": "latest"
35
+ },
36
+ "devDependencies": {
37
+ "@types/bun": "latest",
38
+ "typescript": "^5.7.0"
39
+ }
40
+ }
@@ -0,0 +1,10 @@
1
+ export const DIFFERENT = false;
2
+ export const SAME = true;
3
+ export const SPLIT_PATH = "\\.";
4
+ export const MERGE_PATH = ".";
5
+
6
+ export const OBJECT_NULL = null;
7
+ export const TYPE_MODIFY = "MODIFY";
8
+ export const TYPE_ADD = "ADD";
9
+ export const TYPE_DELETE = "DELETE";
10
+
@@ -0,0 +1,6 @@
1
+ export enum PresetName {
2
+ FullSmart = "fullSmart",
3
+ FullOrdered = "fullOrdered",
4
+ LeftSmart = "leftSmart",
5
+ LeftOrdered = "leftOrdered",
6
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./DiffConstants";
2
+ export * from "./PresetName";
@@ -0,0 +1,2 @@
1
+ export * from "./type";
2
+ export * from "./constant";
@@ -0,0 +1,15 @@
1
+ import { createIdentifier } from "@wendellhu/redi";
2
+ import type { JsonArray, JsonValue } from "./JsonTypes";
3
+ import type { DiffContext } from "../../service/diff/DiffContext";
4
+ import type { PathTracker } from "../../service/diff/PathTracker";
5
+
6
+ export interface IArrayComparator {
7
+ diffArray(a: JsonArray, b: JsonArray, pathTracker: PathTracker): DiffContext;
8
+ diffElement(
9
+ a: JsonValue | undefined,
10
+ b: JsonValue | undefined,
11
+ pathTracker: PathTracker
12
+ ): DiffContext;
13
+ }
14
+
15
+ export const IArrayComparator = createIdentifier<IArrayComparator>("IArrayComparator");
@@ -0,0 +1,16 @@
1
+ import { createIdentifier } from "@wendellhu/redi";
2
+ import type { JsonValue } from "./JsonTypes";
3
+ import type { DiffContext } from "../../service/diff/DiffContext";
4
+ import type { PathTracker } from "../../service/diff/PathTracker";
5
+ import type { IArrayComparator } from "./ArrayComparator";
6
+
7
+ export interface IComparatorOrchestrator {
8
+ diffElement(
9
+ a: JsonValue | undefined,
10
+ b: JsonValue | undefined,
11
+ pathTracker: PathTracker
12
+ ): DiffContext;
13
+ getArrayComparator(): IArrayComparator;
14
+ }
15
+
16
+ export const IComparatorOrchestrator = createIdentifier<IComparatorOrchestrator>("IComparatorOrchestrator");
@@ -0,0 +1,31 @@
1
+ import { createIdentifier } from "@wendellhu/redi";
2
+ import type { JsonValue } from "./JsonTypes";
3
+ import type { Result } from "./Result";
4
+
5
+ export interface IDiffService {
6
+ /**
7
+ * Diff two JSON strings
8
+ * @param leftJson - Left JSON string
9
+ * @param rightJson - Right JSON string
10
+ * @returns Array of differences
11
+ */
12
+ diffJson(leftJson: string, rightJson: string, options?: {
13
+ noisePath?: string[];
14
+ specialPath?: string[];
15
+ parseNestedJson?: boolean;
16
+ }): Result[];
17
+
18
+ /**
19
+ * Diff two JSON objects directly
20
+ * @param left - Left JSON value
21
+ * @param right - Right JSON value
22
+ * @returns Array of differences
23
+ */
24
+ diffElement(left: JsonValue, right: JsonValue, options?: {
25
+ noisePath?: string[];
26
+ specialPath?: string[];
27
+ parseNestedJson?: boolean;
28
+ }): Result[];
29
+ }
30
+
31
+ export const IDiffService = createIdentifier<IDiffService>("IDiffService");
@@ -0,0 +1,3 @@
1
+ export type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
2
+ export type JsonObject = { [key: string]: JsonValue };
3
+ export type JsonArray = JsonValue[];
@@ -0,0 +1,9 @@
1
+ import { createIdentifier } from "@wendellhu/redi";
2
+ import type { DiffContext } from "../../service/diff/DiffContext";
3
+ import type { PathTracker } from "../../service/diff/PathTracker";
4
+
5
+ export interface INullComparator {
6
+ diff(a: null, b: null, pathTracker: PathTracker): DiffContext;
7
+ }
8
+
9
+ export const INullComparator = createIdentifier<INullComparator>("INullComparator");
@@ -0,0 +1,15 @@
1
+ import { createIdentifier } from "@wendellhu/redi";
2
+ import type { JsonObject, JsonValue } from "./JsonTypes";
3
+ import type { DiffContext } from "../../service/diff/DiffContext";
4
+ import type { PathTracker } from "../../service/diff/PathTracker";
5
+
6
+ export interface IObjectComparator {
7
+ diff(a: JsonObject, b: JsonObject, pathTracker: PathTracker): DiffContext;
8
+ diffElement(
9
+ a: JsonValue | undefined,
10
+ b: JsonValue | undefined,
11
+ pathTracker: PathTracker
12
+ ): DiffContext;
13
+ }
14
+
15
+ export const IObjectComparator = createIdentifier<IObjectComparator>("IObjectComparator");
@@ -0,0 +1,14 @@
1
+ import { createIdentifier } from "@wendellhu/redi";
2
+ import type { JsonValue } from "./JsonTypes";
3
+ import type { DiffContext } from "../../service/diff/DiffContext";
4
+ import type { PathTracker } from "../../service/diff/PathTracker";
5
+
6
+ export interface IOtherComparator {
7
+ diff(
8
+ a: JsonValue | undefined,
9
+ b: JsonValue | undefined,
10
+ pathTracker: PathTracker
11
+ ): DiffContext;
12
+ }
13
+
14
+ export const IOtherComparator = createIdentifier<IOtherComparator>("IOtherComparator");
@@ -0,0 +1,13 @@
1
+ import { createIdentifier } from "@wendellhu/redi";
2
+ import type { DiffContext } from "../../service/diff/DiffContext";
3
+ import type { PathTracker } from "../../service/diff/PathTracker";
4
+
5
+ export interface IPrimitiveComparator {
6
+ diff(
7
+ a: string | number | boolean,
8
+ b: string | number | boolean,
9
+ pathTracker: PathTracker
10
+ ): DiffContext;
11
+ }
12
+
13
+ export const IPrimitiveComparator = createIdentifier<IPrimitiveComparator>("IPrimitiveComparator");
@@ -0,0 +1,7 @@
1
+ export class Result {
2
+ leftPath: string | null = null;
3
+ rightPath: string | null = null;
4
+ left: unknown = null;
5
+ right: unknown = null;
6
+ diffType: string = "";
7
+ }
@@ -0,0 +1,13 @@
1
+ export class SingleNodeDifference {
2
+ leftPath: string;
3
+ rightPath: string;
4
+ left: unknown;
5
+ right: unknown;
6
+
7
+ constructor(leftPath: string, rightPath: string, left: unknown, right: unknown) {
8
+ this.leftPath = leftPath;
9
+ this.rightPath = rightPath;
10
+ this.left = left;
11
+ this.right = right;
12
+ }
13
+ }
@@ -0,0 +1,10 @@
1
+ export * from "./JsonTypes";
2
+ export * from "./Result";
3
+ export * from "./SingleNodeDifference";
4
+ export * from "./ComparatorOrchestrator";
5
+ export * from "./ObjectComparator";
6
+ export * from "./ArrayComparator";
7
+ export * from "./PrimitiveComparator";
8
+ export * from "./NullComparator";
9
+ export * from "./OtherComparator";
10
+ export * from "./DiffService";
package/src/index.ts ADDED
@@ -0,0 +1,17 @@
1
+ // Public API - Types
2
+ export type { JsonValue, JsonObject, JsonArray } from "./contract/type/JsonTypes";
3
+ export { Result } from "./contract/type/Result";
4
+ export * from "./contract/type/DiffService";
5
+
6
+ // Public API - Constants
7
+ export {
8
+ TYPE_ADD,
9
+ TYPE_DELETE,
10
+ TYPE_MODIFY,
11
+ } from "./contract/constant";
12
+
13
+ // Public API - Enums
14
+ export { PresetName } from "./contract/constant/PresetName";
15
+
16
+ // Public API - Service
17
+ export { DiffService } from "./service";
@@ -0,0 +1,50 @@
1
+ import { Inject } from "@wendellhu/redi";
2
+ import {
3
+ type IComparatorOrchestrator,
4
+ type IObjectComparator,
5
+ IObjectComparator as IObjectComparatorToken,
6
+ type IArrayComparator,
7
+ IArrayComparator as IArrayComparatorToken,
8
+ type IPrimitiveComparator,
9
+ IPrimitiveComparator as IPrimitiveComparatorToken,
10
+ type INullComparator,
11
+ INullComparator as INullComparatorToken,
12
+ type IOtherComparator,
13
+ IOtherComparator as IOtherComparatorToken,
14
+ type JsonValue,
15
+ } from "../../contract/type";
16
+ import { DiffContext } from "../diff/DiffContext";
17
+ import type { PathTracker } from "../diff/PathTracker";
18
+ import { isJsonObject, isJsonArray, isJsonPrimitive, isJsonNull } from "../../util";
19
+
20
+ export class ComparatorOrchestrator implements IComparatorOrchestrator {
21
+ constructor(
22
+ @Inject(IObjectComparatorToken) protected objectComparator: IObjectComparator,
23
+ @Inject(IArrayComparatorToken) protected arrayComparator: IArrayComparator,
24
+ @Inject(IPrimitiveComparatorToken) protected primitiveComparator: IPrimitiveComparator,
25
+ @Inject(INullComparatorToken) protected nullComparator: INullComparator,
26
+ @Inject(IOtherComparatorToken) protected otherComparator: IOtherComparator
27
+ ) {}
28
+
29
+ diffElement(
30
+ a: JsonValue | undefined,
31
+ b: JsonValue | undefined,
32
+ pathTracker: PathTracker
33
+ ): DiffContext {
34
+ if (isJsonObject(a) && isJsonObject(b)) {
35
+ return this.objectComparator.diff(a, b, pathTracker);
36
+ } else if (isJsonArray(a) && isJsonArray(b)) {
37
+ return this.arrayComparator.diffArray(a, b, pathTracker);
38
+ } else if (isJsonPrimitive(a) && isJsonPrimitive(b)) {
39
+ return this.primitiveComparator.diff(a, b, pathTracker);
40
+ } else if (isJsonNull(a) && isJsonNull(b)) {
41
+ return this.nullComparator.diff(a, b, pathTracker);
42
+ } else {
43
+ return this.otherComparator.diff(a, b, pathTracker);
44
+ }
45
+ }
46
+
47
+ getArrayComparator(): IArrayComparator {
48
+ return this.arrayComparator;
49
+ }
50
+ }
@@ -0,0 +1,34 @@
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
+ }
@@ -0,0 +1,46 @@
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
+ });
@@ -0,0 +1,48 @@
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
+ }
@@ -0,0 +1,37 @@
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
+ });