@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.
- package/README.md +264 -0
- package/package.json +5 -1
- package/.turbo/turbo-build.log +0 -1
- package/.turbo/turbo-test.log +0 -96
- package/.turbo/turbo-typecheck.log +0 -2
- package/src/contract/constant/DiffConstants.ts +0 -10
- package/src/contract/constant/PresetName.ts +0 -6
- package/src/contract/constant/index.ts +0 -2
- package/src/contract/index.ts +0 -2
- package/src/contract/type/ArrayComparator.ts +0 -15
- package/src/contract/type/ComparatorOrchestrator.ts +0 -16
- package/src/contract/type/DiffService.ts +0 -31
- package/src/contract/type/JsonTypes.ts +0 -3
- package/src/contract/type/NullComparator.ts +0 -9
- package/src/contract/type/ObjectComparator.ts +0 -15
- package/src/contract/type/OtherComparator.ts +0 -14
- package/src/contract/type/PrimitiveComparator.ts +0 -13
- package/src/contract/type/Result.ts +0 -7
- package/src/contract/type/SingleNodeDifference.ts +0 -13
- package/src/contract/type/index.ts +0 -10
- package/src/index.ts +0 -17
- package/src/service/comparator/ComparatorOrchestrator.ts +0 -50
- package/src/service/comparator/array/AbstractArray.ts +0 -34
- package/src/service/comparator/array/SequentialArrayComparator.test.ts +0 -46
- package/src/service/comparator/array/SequentialArrayComparator.ts +0 -48
- package/src/service/comparator/array/SimilarArrayComparator.test.ts +0 -37
- package/src/service/comparator/array/SimilarArrayComparator.ts +0 -211
- package/src/service/comparator/array/index.ts +0 -3
- package/src/service/comparator/index.ts +0 -6
- package/src/service/comparator/nulls/DefaultNullComparator.test.ts +0 -38
- package/src/service/comparator/nulls/DefaultNullComparator.ts +0 -9
- package/src/service/comparator/nulls/index.ts +0 -1
- package/src/service/comparator/object/AbstractObject.ts +0 -102
- package/src/service/comparator/object/LeftJoinObjectComparator.test.ts +0 -71
- package/src/service/comparator/object/LeftJoinObjectComparator.ts +0 -18
- package/src/service/comparator/object/UnionKeyObjectComparator.test.ts +0 -20
- package/src/service/comparator/object/UnionKeyObjectComparator.ts +0 -19
- package/src/service/comparator/object/index.ts +0 -3
- package/src/service/comparator/other/DefaultOtherComparator.test.ts +0 -48
- package/src/service/comparator/other/DefaultOtherComparator.ts +0 -23
- package/src/service/comparator/other/index.ts +0 -1
- package/src/service/comparator/primitive/DefaultPrimitiveComparator.test.ts +0 -50
- package/src/service/comparator/primitive/DefaultPrimitiveComparator.ts +0 -27
- package/src/service/comparator/primitive/index.ts +0 -1
- package/src/service/diff/Diff.test.ts +0 -113
- package/src/service/diff/DiffContext.ts +0 -37
- package/src/service/diff/DiffService.test.ts +0 -292
- package/src/service/diff/DiffService.ts +0 -245
- package/src/service/diff/PathTracker.ts +0 -71
- package/src/service/diff/index.ts +0 -1
- package/src/service/index.ts +0 -2
- package/src/util/TypeGuards.test.ts +0 -90
- package/src/util/TypeGuards.ts +0 -33
- package/src/util/index.ts +0 -1
- package/tsconfig.json +0 -11
- package/tsconfig.tsbuildinfo +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# @diffson/core
|
|
2
|
+
|
|
3
|
+
A powerful TypeScript library for comparing JSON objects with multiple comparison strategies.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @diffson/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { DiffService, PresetName } from '@diffson/core';
|
|
15
|
+
|
|
16
|
+
// Create a diff service
|
|
17
|
+
const diffService = new DiffService();
|
|
18
|
+
|
|
19
|
+
// Compare two JSON objects
|
|
20
|
+
const left = { name: 'John', age: 30 };
|
|
21
|
+
const right = { name: 'John', age: 31 };
|
|
22
|
+
|
|
23
|
+
const results = diffService.diffElement(left, right);
|
|
24
|
+
|
|
25
|
+
console.log(results);
|
|
26
|
+
// [
|
|
27
|
+
// {
|
|
28
|
+
// leftPath: 'age',
|
|
29
|
+
// rightPath: 'age',
|
|
30
|
+
// left: '30',
|
|
31
|
+
// right: '31',
|
|
32
|
+
// diffType: 'MODIFY'
|
|
33
|
+
// }
|
|
34
|
+
// ]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## API Reference
|
|
38
|
+
|
|
39
|
+
### DiffService
|
|
40
|
+
|
|
41
|
+
The main class for comparing JSON objects.
|
|
42
|
+
|
|
43
|
+
#### Constructor
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
new DiffService(preset?: PresetName)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Parameters:**
|
|
50
|
+
- `preset` (optional): Comparison strategy preset. Default: `PresetName.FullSmart`
|
|
51
|
+
|
|
52
|
+
**Presets:**
|
|
53
|
+
- `PresetName.FullSmart` - Smart comparison of all fields (default)
|
|
54
|
+
- `PresetName.FullOrdered` - Order-sensitive comparison
|
|
55
|
+
- `PresetName.LeftSmart` - Compare only fields in left object, smart mode
|
|
56
|
+
- `PresetName.LeftOrdered` - Compare only fields in left object, order-sensitive
|
|
57
|
+
|
|
58
|
+
#### Methods
|
|
59
|
+
|
|
60
|
+
##### `diffElement(left, right, options?)`
|
|
61
|
+
|
|
62
|
+
Compare two JSON values directly.
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
diffElement(
|
|
66
|
+
left: JsonValue,
|
|
67
|
+
right: JsonValue,
|
|
68
|
+
options?: {
|
|
69
|
+
noisePath?: string[];
|
|
70
|
+
specialPath?: string[];
|
|
71
|
+
parseNestedJson?: boolean;
|
|
72
|
+
}
|
|
73
|
+
): Result[]
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Parameters:**
|
|
77
|
+
- `left`: First JSON value
|
|
78
|
+
- `right`: Second JSON value
|
|
79
|
+
- `options` (optional):
|
|
80
|
+
- `noisePath`: Array of paths to ignore during comparison
|
|
81
|
+
- `specialPath`: Array of paths to mark as special even if values match
|
|
82
|
+
- `parseNestedJson`: Parse nested JSON strings recursively
|
|
83
|
+
|
|
84
|
+
**Returns:** Array of `Result` objects representing differences.
|
|
85
|
+
|
|
86
|
+
##### `diffJson(leftJson, rightJson, options?)`
|
|
87
|
+
|
|
88
|
+
Compare two JSON strings.
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
diffJson(
|
|
92
|
+
leftJson: string,
|
|
93
|
+
rightJson: string,
|
|
94
|
+
options?: {
|
|
95
|
+
noisePath?: string[];
|
|
96
|
+
specialPath?: string[];
|
|
97
|
+
parseNestedJson?: boolean;
|
|
98
|
+
}
|
|
99
|
+
): Result[]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Parameters:**
|
|
103
|
+
- `leftJson`: First JSON string
|
|
104
|
+
- `rightJson`: Second JSON string
|
|
105
|
+
- `options`: Same as `diffElement`
|
|
106
|
+
|
|
107
|
+
**Returns:** Array of `Result` objects representing differences.
|
|
108
|
+
|
|
109
|
+
### Result Object
|
|
110
|
+
|
|
111
|
+
Each difference is represented by a `Result` object:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
{
|
|
115
|
+
leftPath: string | null; // Path in left object
|
|
116
|
+
rightPath: string | null; // Path in right object
|
|
117
|
+
left: unknown; // Value in left object
|
|
118
|
+
right: unknown; // Value in right object
|
|
119
|
+
diffType: string; // 'ADD' | 'DELETE' | 'MODIFY'
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Diff Types:**
|
|
124
|
+
- `ADD`: Field exists in right but not in left
|
|
125
|
+
- `DELETE`: Field exists in left but not in right
|
|
126
|
+
- `MODIFY`: Field exists in both but with different values
|
|
127
|
+
|
|
128
|
+
## Usage Examples
|
|
129
|
+
|
|
130
|
+
### Basic Comparison
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
import { DiffService } from '@diffson/core';
|
|
134
|
+
|
|
135
|
+
const diffService = new DiffService();
|
|
136
|
+
|
|
137
|
+
const left = { a: 1, b: 2 };
|
|
138
|
+
const right = { a: 1, b: 3, c: 4 };
|
|
139
|
+
|
|
140
|
+
const results = diffService.diffElement(left, right);
|
|
141
|
+
// Results: [
|
|
142
|
+
// { leftPath: 'b', rightPath: 'b', left: '2', right: '3', diffType: 'MODIFY' },
|
|
143
|
+
// { leftPath: null, rightPath: 'c', left: null, right: '4', diffType: 'ADD' }
|
|
144
|
+
// ]
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Using Presets
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
import { DiffService, PresetName } from '@diffson/core';
|
|
151
|
+
|
|
152
|
+
// Order-sensitive comparison
|
|
153
|
+
const orderedDiff = new DiffService(PresetName.FullOrdered);
|
|
154
|
+
const results1 = orderedDiff.diffElement([1, 2, 3], [1, 3, 2]);
|
|
155
|
+
// Detects order changes
|
|
156
|
+
|
|
157
|
+
// Left-only comparison (ignore fields only in right)
|
|
158
|
+
const leftDiff = new DiffService(PresetName.LeftSmart);
|
|
159
|
+
const left = { a: 1, b: 2 };
|
|
160
|
+
const right = { a: 1, b: 2, c: 3 };
|
|
161
|
+
const results2 = leftDiff.diffElement(left, right);
|
|
162
|
+
// Results: [] (ignores 'c' since it's not in left)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Ignoring Paths (Noise Paths)
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
const diffService = new DiffService();
|
|
169
|
+
|
|
170
|
+
const left = { name: 'John', timestamp: 1000 };
|
|
171
|
+
const right = { name: 'John', timestamp: 2000 };
|
|
172
|
+
|
|
173
|
+
// Ignore timestamp field
|
|
174
|
+
const results = diffService.diffElement(left, right, {
|
|
175
|
+
noisePath: ['timestamp']
|
|
176
|
+
});
|
|
177
|
+
// Results: [] (timestamp is ignored)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Nested Objects
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
const left = {
|
|
184
|
+
user: { name: 'Alice', age: 30 },
|
|
185
|
+
items: [{ id: 1, name: 'Item 1' }]
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const right = {
|
|
189
|
+
user: { name: 'Bob', age: 30 },
|
|
190
|
+
items: [{ id: 1, name: 'Item 1' }]
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const results = diffService.diffElement(left, right);
|
|
194
|
+
// Results: [
|
|
195
|
+
// { leftPath: 'user.name', rightPath: 'user.name', left: 'Alice', right: 'Bob', diffType: 'MODIFY' }
|
|
196
|
+
// ]
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Parsing Nested JSON Strings
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
const left = { data: '{"nested":"value1"}' };
|
|
203
|
+
const right = { data: '{"nested":"value2"}' };
|
|
204
|
+
|
|
205
|
+
// Without parseNestedJson
|
|
206
|
+
const results1 = diffService.diffElement(left, right);
|
|
207
|
+
// Compares strings: '{"nested":"value1"}' vs '{"nested":"value2"}'
|
|
208
|
+
|
|
209
|
+
// With parseNestedJson
|
|
210
|
+
const results2 = diffService.diffElement(left, right, {
|
|
211
|
+
parseNestedJson: true
|
|
212
|
+
});
|
|
213
|
+
// Parses and compares: { nested: 'value1' } vs { nested: 'value2' }
|
|
214
|
+
// Results: [{ leftPath: 'data.nested', rightPath: 'data.nested', ... }]
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Comparing JSON Strings
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
const leftJson = '{"name":"John","age":30}';
|
|
221
|
+
const rightJson = '{"name":"John","age":31}';
|
|
222
|
+
|
|
223
|
+
const results = diffService.diffJson(leftJson, rightJson);
|
|
224
|
+
// Same as diffElement but accepts JSON strings
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Fluent API (Advanced)
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
import { DiffService, SequentialArrayComparator, LeftJoinObjectComparator } from '@diffson/core';
|
|
231
|
+
|
|
232
|
+
const diffService = new DiffService()
|
|
233
|
+
.withArrayComparator(SequentialArrayComparator)
|
|
234
|
+
.withObjectComparator(LeftJoinObjectComparator);
|
|
235
|
+
|
|
236
|
+
const results = diffService.diffElement(left, right);
|
|
237
|
+
// Uses custom comparators
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Path Format
|
|
241
|
+
|
|
242
|
+
Paths use dot notation to reference nested fields:
|
|
243
|
+
|
|
244
|
+
- `field` - Object field
|
|
245
|
+
- `array.[0]` - Array element at index 0
|
|
246
|
+
- `parent.child` - Nested object field
|
|
247
|
+
- `items.[0].name` - Field in array element
|
|
248
|
+
|
|
249
|
+
When using `noisePath`, array indices are auto-filtered:
|
|
250
|
+
- `items.name` matches `items.[0].name`, `items.[1].name`, etc.
|
|
251
|
+
|
|
252
|
+
## TypeScript Support
|
|
253
|
+
|
|
254
|
+
This library is written in TypeScript and includes full type definitions.
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import type { JsonValue, Result, PresetName } from '@diffson/core';
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## License
|
|
261
|
+
|
|
262
|
+
MIT
|
|
263
|
+
|
|
264
|
+
|
package/package.json
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@diffson/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
7
11
|
"imports": {
|
|
8
12
|
"#contract": "./src/contract/index.ts",
|
|
9
13
|
"#service": "./src/service/index.ts"
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
$ tsc
|
package/.turbo/turbo-test.log
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
[0m[2m[35m$[0m [2m[1mbun test[0m
|
|
3
|
-
[0m[1mbun test [0m[2mv1.3.5 (1e86cebd)[0m
|
|
4
|
-
[0m
|
|
5
|
-
src/util/TypeGuards.test.ts:
|
|
6
|
-
[0m[32m✓[0m [0mTypeGuards[2m > [0misJsonObject[2m >[0m[1m should return true for objects[0m [0m[2m[0.92ms[0m[2m][0m
|
|
7
|
-
[0m[32m✓[0m [0mTypeGuards[2m > [0misJsonObject[2m >[0m[1m should return false for non-objects[0m [0m[2m[0.05ms[0m[2m][0m
|
|
8
|
-
[0m[32m✓[0m [0mTypeGuards[2m > [0misJsonArray[2m >[0m[1m should return true for arrays[0m [0m[2m[0.02ms[0m[2m][0m
|
|
9
|
-
[0m[32m✓[0m [0mTypeGuards[2m > [0misJsonArray[2m >[0m[1m should return false for non-arrays[0m [0m[2m[0.02ms[0m[2m][0m
|
|
10
|
-
[0m[32m✓[0m [0mTypeGuards[2m > [0misJsonPrimitive[2m >[0m[1m should return true for primitives[0m [0m[2m[0.01ms[0m[2m][0m
|
|
11
|
-
[0m[32m✓[0m [0mTypeGuards[2m > [0misJsonPrimitive[2m >[0m[1m should return false for non-primitives[0m [0m[2m[0.02ms[0m[2m][0m
|
|
12
|
-
[0m[32m✓[0m [0mTypeGuards[2m > [0misJsonNull[2m >[0m[1m should return true for null[0m [0m[2m[0.02ms[0m[2m][0m
|
|
13
|
-
[0m[32m✓[0m [0mTypeGuards[2m > [0misJsonNull[2m >[0m[1m should return false for non-null[0m [0m[2m[0.01ms[0m[2m][0m
|
|
14
|
-
[0m[32m✓[0m [0mTypeGuards[2m > [0mjsonElement2Str[2m >[0m[1m should convert primitives to strings[0m [0m[2m[0.03ms[0m[2m][0m
|
|
15
|
-
[0m[32m✓[0m [0mTypeGuards[2m > [0mjsonElement2Str[2m >[0m[1m should return null for undefined[0m
|
|
16
|
-
[0m[32m✓[0m [0mTypeGuards[2m > [0mjsonElement2Str[2m >[0m[1m should return 'null' for null[0m
|
|
17
|
-
[0m[32m✓[0m [0mTypeGuards[2m > [0mjsonElement2Str[2m >[0m[1m should return placeholder for objects[0m
|
|
18
|
-
[0m[32m✓[0m [0mTypeGuards[2m > [0mjsonElement2Str[2m >[0m[1m should return placeholder for arrays[0m
|
|
19
|
-
[0m
|
|
20
|
-
src/service/diff/Diff.test.ts:
|
|
21
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mdiffElement[2m >[0m[1m should return empty array for identical objects[0m [0m[2m[1.15ms[0m[2m][0m
|
|
22
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mdiffElement[2m >[0m[1m should detect modified values[0m [0m[2m[0.12ms[0m[2m][0m
|
|
23
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mdiffElement[2m >[0m[1m should detect added fields[0m [0m[2m[0.06ms[0m[2m][0m
|
|
24
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mdiffElement[2m >[0m[1m should detect deleted fields[0m [0m[2m[0.13ms[0m[2m][0m
|
|
25
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mdiffJson[2m >[0m[1m should parse JSON strings and diff them[0m [0m[2m[0.10ms[0m[2m][0m
|
|
26
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mdiffJson[2m >[0m[1m should return empty array for identical JSON strings[0m [0m[2m[0.09ms[0m[2m][0m
|
|
27
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mdiffJson[2m >[0m[1m should throw error for invalid left JSON string[0m [0m[2m[0.31ms[0m[2m][0m
|
|
28
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mdiffJson[2m >[0m[1m should throw error for invalid right JSON string[0m [0m[2m[0.02ms[0m[2m][0m
|
|
29
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mnested objects[2m >[0m[1m should handle nested objects[0m [0m[2m[0.09ms[0m[2m][0m
|
|
30
|
-
[0m
|
|
31
|
-
src/service/diff/DiffService.test.ts:
|
|
32
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mbasic comparison[2m >[0m[1m should return empty array for identical objects[0m [0m[2m[0.10ms[0m[2m][0m
|
|
33
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mbasic comparison[2m >[0m[1m should detect modified values[0m [0m[2m[0.06ms[0m[2m][0m
|
|
34
|
-
[
|
|
35
|
-
Result {
|
|
36
|
-
[0mleftPath[2m:[0m [0m[32m[0m[32m"items.[1]"[0m[0m[0m[2m,[0m
|
|
37
|
-
[0mrightPath[2m:[0m [0m[32m[0m[32m"items.[1]"[0m[0m[0m[2m,[0m
|
|
38
|
-
[0mleft[2m:[0m [0m[32m[0m[32m"2"[0m[0m[0m[2m,[0m
|
|
39
|
-
[0mright[2m:[0m [0m[32m[0m[32m"4"[0m[0m[0m[2m,[0m
|
|
40
|
-
[0mdiffType[2m:[0m [0m[32m[0m[32m"MODIFY"[0m[0m[0m[2m,[0m
|
|
41
|
-
}
|
|
42
|
-
]
|
|
43
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mwithArrayComparator[2m >[0m[1m should use sequential array comparator when configured[0m [0m[2m[0.85ms[0m[2m][0m
|
|
44
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mwithArrayComparator[2m >[0m[1m should reuse injector when configuration changes[0m [0m[2m[0.40ms[0m[2m][0m
|
|
45
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mpreset[2m >[0m[1m should use FullOrdered preset[0m [0m[2m[0.04ms[0m[2m][0m
|
|
46
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mpreset[2m >[0m[1m should use LeftSmart preset[0m [0m[2m[0.03ms[0m[2m][0m
|
|
47
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mpreset[2m >[0m[1m should use LeftOrdered preset[0m [0m[2m[0.05ms[0m[2m][0m
|
|
48
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mcompareWithOptions[2m >[0m[1m should ignore noise paths[0m [0m[2m[0.06ms[0m[2m][0m
|
|
49
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mcompareWithOptions[2m >[0m[1m should handle special paths[0m [0m[2m[0.13ms[0m[2m][0m
|
|
50
|
-
[0m[32m✓[0m [0mDiffService[2m > [0mfluent API[2m >[0m[1m should support method chaining[0m [0m[2m[0.34ms[0m[2m][0m
|
|
51
|
-
[0m[32m✓[0m [0mDiffService - parseNestedJson[2m >[0m[1m should parse nested JSON strings when parseNestedJson option is true[0m [0m[2m[0.61ms[0m[2m][0m
|
|
52
|
-
[0m[32m✓[0m [0mDiffService - parseNestedJson[2m >[0m[1m should not parse nested JSON strings when parseNestedJson option is false or undefined[0m [0m[2m[0.07ms[0m[2m][0m
|
|
53
|
-
[0m[32m✓[0m [0mDiffService - parseNestedJson[2m >[0m[1m should handle deeply nested JSON strings[0m [0m[2m[0.09ms[0m[2m][0m
|
|
54
|
-
[0m[32m✓[0m [0mDiffService - parseNestedJson[2m >[0m[1m should handle arrays containing JSON strings[0m [0m[2m[0.11ms[0m[2m][0m
|
|
55
|
-
[0m[32m✓[0m [0mDiffService - parseNestedJson[2m >[0m[1m should handle mixed content with both JSON strings and regular strings[0m [0m[2m[0.07ms[0m[2m][0m
|
|
56
|
-
[0m[32m✓[0m [0mDiffService - parseNestedJson[2m >[0m[1m should not fail on invalid JSON strings[0m [0m[2m[0.07ms[0m[2m][0m
|
|
57
|
-
[0m
|
|
58
|
-
src/service/comparator/array/SequentialArrayComparator.test.ts:
|
|
59
|
-
[0m[32m✓[0m [0mSequentialArrayComparator[2m >[0m[1m should compare arrays by index[0m [0m[2m[0.13ms[0m[2m][0m
|
|
60
|
-
[0m[32m✓[0m [0mSequentialArrayComparator[2m >[0m[1m should detect added elements[0m [0m[2m[0.03ms[0m[2m][0m
|
|
61
|
-
[0m[32m✓[0m [0mSequentialArrayComparator[2m >[0m[1m should detect deleted elements[0m [0m[2m[0.04ms[0m[2m][0m
|
|
62
|
-
[0m
|
|
63
|
-
src/service/comparator/array/SimilarArrayComparator.test.ts:
|
|
64
|
-
[0m[32m✓[0m [0mSimilarArrayComparator[2m >[0m[1m should match similar elements[0m [0m[2m[0.04ms[0m[2m][0m
|
|
65
|
-
[0m[32m✓[0m [0mSimilarArrayComparator[2m >[0m[1m should detect modifications in matched elements[0m [0m[2m[0.10ms[0m[2m][0m
|
|
66
|
-
[0m[32m✓[0m [0mSimilarArrayComparator[2m >[0m[1m should detect added elements[0m [0m[2m[0.05ms[0m[2m][0m
|
|
67
|
-
[0m
|
|
68
|
-
src/service/comparator/primitive/DefaultPrimitiveComparator.test.ts:
|
|
69
|
-
[0m[32m✓[0m [0mDefaultPrimitiveComparator[2m >[0m[1m should detect string changes[0m
|
|
70
|
-
[0m[32m✓[0m [0mDefaultPrimitiveComparator[2m >[0m[1m should detect number changes[0m [0m[2m[0.12ms[0m[2m][0m
|
|
71
|
-
[0m[32m✓[0m [0mDefaultPrimitiveComparator[2m >[0m[1m should detect boolean changes[0m [0m[2m[0.02ms[0m[2m][0m
|
|
72
|
-
[0m[32m✓[0m [0mDefaultPrimitiveComparator[2m >[0m[1m should not report identical primitives[0m [0m[2m[0.03ms[0m[2m][0m
|
|
73
|
-
[0m
|
|
74
|
-
src/service/comparator/other/DefaultOtherComparator.test.ts:
|
|
75
|
-
[0m[32m✓[0m [0mDefaultOtherComparator[2m >[0m[1m should detect type changes from object to array[0m
|
|
76
|
-
[0m[32m✓[0m [0mDefaultOtherComparator[2m >[0m[1m should detect type changes from array to primitive[0m [0m[2m[0.22ms[0m[2m][0m
|
|
77
|
-
[0m[32m✓[0m [0mDefaultOtherComparator[2m >[0m[1m should detect undefined to value[0m [0m[2m[0.02ms[0m[2m][0m
|
|
78
|
-
[0m[32m✓[0m [0mDefaultOtherComparator[2m >[0m[1m should detect value to undefined[0m [0m[2m[0.04ms[0m[2m][0m
|
|
79
|
-
[0m
|
|
80
|
-
src/service/comparator/nulls/DefaultNullComparator.test.ts:
|
|
81
|
-
[0m[32m✓[0m [0mDefaultNullComparator[2m >[0m[1m should not report differences for null vs null[0m [0m[2m[0.23ms[0m[2m][0m
|
|
82
|
-
[0m[32m✓[0m [0mDefaultNullComparator[2m >[0m[1m should detect null to value changes[0m [0m[2m[0.16ms[0m[2m][0m
|
|
83
|
-
[0m[32m✓[0m [0mDefaultNullComparator[2m >[0m[1m should detect value to null changes[0m [0m[2m[0.03ms[0m[2m][0m
|
|
84
|
-
[0m
|
|
85
|
-
src/service/comparator/object/UnionKeyObjectComparator.test.ts:
|
|
86
|
-
[0m[32m✓[0m [0mUnionKeyObjectComparator[2m >[0m[1m should compare all keys from both objects[0m [0m[2m[0.12ms[0m[2m][0m
|
|
87
|
-
[0m
|
|
88
|
-
src/service/comparator/object/LeftJoinObjectComparator.test.ts:
|
|
89
|
-
[0m[32m✓[0m [0mLeftJoinObjectComparator[2m >[0m[1m should only compare keys from left object[0m [0m[2m[0.15ms[0m[2m][0m
|
|
90
|
-
[0m[32m✓[0m [0mLeftJoinObjectComparator[2m >[0m[1m should detect changes in left keys[0m [0m[2m[0.04ms[0m[2m][0m
|
|
91
|
-
[0m[32m✓[0m [0mLeftJoinObjectComparator[2m >[0m[1m should detect missing keys in right object[0m [0m[2m[0.03ms[0m[2m][0m
|
|
92
|
-
|
|
93
|
-
[0m[32m 59 pass[0m
|
|
94
|
-
[0m[2m 0 fail[0m
|
|
95
|
-
154 expect() calls
|
|
96
|
-
Ran 59 tests across 10 files. [0m[2m[[1m27.00ms[0m[2m][0m
|
|
@@ -1,10 +0,0 @@
|
|
|
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
|
-
|
package/src/contract/index.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
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");
|
|
@@ -1,16 +0,0 @@
|
|
|
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");
|
|
@@ -1,31 +0,0 @@
|
|
|
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");
|
|
@@ -1,9 +0,0 @@
|
|
|
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");
|
|
@@ -1,15 +0,0 @@
|
|
|
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");
|
|
@@ -1,14 +0,0 @@
|
|
|
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");
|
|
@@ -1,13 +0,0 @@
|
|
|
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");
|
|
@@ -1,13 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
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";
|
|
@@ -1,50 +0,0 @@
|
|
|
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
|
-
}
|