@fgv/ts-json 5.0.0-4 → 5.0.0-6
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/dist/ts-json.d.ts +656 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +25 -0
- package/lib/index.js.map +1 -1
- package/lib/packlets/diff/detailedDiff.d.ts +375 -0
- package/lib/packlets/diff/detailedDiff.d.ts.map +1 -0
- package/lib/packlets/diff/detailedDiff.js +342 -0
- package/lib/packlets/diff/detailedDiff.js.map +1 -0
- package/lib/packlets/diff/index.d.ts +3 -0
- package/lib/packlets/diff/index.d.ts.map +1 -0
- package/lib/packlets/diff/index.js +40 -0
- package/lib/packlets/diff/index.js.map +1 -0
- package/lib/packlets/diff/threeWayDiff.d.ts +263 -0
- package/lib/packlets/diff/threeWayDiff.d.ts.map +1 -0
- package/lib/packlets/diff/threeWayDiff.js +261 -0
- package/lib/packlets/diff/threeWayDiff.js.map +1 -0
- package/lib/packlets/diff/utils.d.ts +6 -0
- package/lib/packlets/diff/utils.d.ts.map +1 -0
- package/lib/packlets/diff/utils.js +62 -0
- package/lib/packlets/diff/utils.js.map +1 -0
- package/package.json +6 -6
package/dist/ts-json.d.ts
CHANGED
|
@@ -230,6 +230,86 @@ export { Converters }
|
|
|
230
230
|
*/
|
|
231
231
|
export declare function defaultExtendVars(base: TemplateVars | undefined, values: VariableValue[]): Result<TemplateVars | undefined>;
|
|
232
232
|
|
|
233
|
+
declare namespace Diff {
|
|
234
|
+
export {
|
|
235
|
+
jsonDiff,
|
|
236
|
+
jsonEquals,
|
|
237
|
+
DiffChangeType,
|
|
238
|
+
IDiffChange,
|
|
239
|
+
IDiffResult,
|
|
240
|
+
IJsonDiffOptions,
|
|
241
|
+
jsonThreeWayDiff,
|
|
242
|
+
IThreeWayDiffMetadata,
|
|
243
|
+
IThreeWayDiff
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
export { Diff }
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* JSON Diff Utilities for TypeScript
|
|
250
|
+
*
|
|
251
|
+
* This module provides comprehensive tools for comparing JSON values and identifying
|
|
252
|
+
* differences between them. It offers two complementary approaches:
|
|
253
|
+
*
|
|
254
|
+
* ## **Detailed Diff API** (`jsonDiff`)
|
|
255
|
+
* Best for analysis, debugging, and understanding specific changes:
|
|
256
|
+
* - Returns a list of individual changes with exact paths and values
|
|
257
|
+
* - Ideal for logging, change tracking, and detailed analysis
|
|
258
|
+
* - Configurable options for array handling and path notation
|
|
259
|
+
*
|
|
260
|
+
* ## **Three-Way Diff API** (`jsonThreeWayDiff`)
|
|
261
|
+
* Best for applying changes and programmatic manipulation:
|
|
262
|
+
* - Returns three objects representing removed, unchanged, and added data
|
|
263
|
+
* - Perfect for merging, UI displays, and actionable results
|
|
264
|
+
* - Treats arrays as atomic units for simpler handling
|
|
265
|
+
*
|
|
266
|
+
* ## **Simple Equality** (`jsonEquals`)
|
|
267
|
+
* Fast boolean check for JSON equality without change details.
|
|
268
|
+
*
|
|
269
|
+
* **Key Features:**
|
|
270
|
+
* - Deep recursive comparison of nested structures
|
|
271
|
+
* - Support for all JSON types: objects, arrays, primitives, null
|
|
272
|
+
* - TypeScript-first with comprehensive type safety
|
|
273
|
+
* - Result pattern for consistent error handling
|
|
274
|
+
* - Extensive TSDoc documentation with practical examples
|
|
275
|
+
*
|
|
276
|
+
* @example Quick comparison of the two main APIs
|
|
277
|
+
* ```typescript
|
|
278
|
+
* const before = { name: "John", age: 30, city: "NYC" };
|
|
279
|
+
* const after = { name: "Jane", age: 30, country: "USA" };
|
|
280
|
+
*
|
|
281
|
+
* // Detailed analysis
|
|
282
|
+
* const detailed = jsonDiff(before, after);
|
|
283
|
+
* // Returns: [
|
|
284
|
+
* // { path: "name", type: "modified", oldValue: "John", newValue: "Jane" },
|
|
285
|
+
* // { path: "city", type: "removed", oldValue: "NYC" },
|
|
286
|
+
* // { path: "country", type: "added", newValue: "USA" }
|
|
287
|
+
* // ]
|
|
288
|
+
*
|
|
289
|
+
* // Actionable objects
|
|
290
|
+
* const actionable = jsonThreeWayDiff(before, after);
|
|
291
|
+
* // Returns: {
|
|
292
|
+
* // onlyInA: { name: "John", city: "NYC" },
|
|
293
|
+
* // unchanged: { age: 30 },
|
|
294
|
+
* // onlyInB: { name: "Jane", country: "USA" }
|
|
295
|
+
* // }
|
|
296
|
+
*
|
|
297
|
+
* // Apply changes: { ...unchanged, ...onlyInB }
|
|
298
|
+
* // Revert changes: { ...unchanged, ...onlyInA }
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
301
|
+
/**
|
|
302
|
+
* Type of change detected in a JSON diff operation.
|
|
303
|
+
*
|
|
304
|
+
* - `'added'` - Property exists only in the second object
|
|
305
|
+
* - `'removed'` - Property exists only in the first object
|
|
306
|
+
* - `'modified'` - Property exists in both objects but with different values
|
|
307
|
+
* - `'unchanged'` - Property exists in both objects with identical values (only included when `includeUnchanged` is true)
|
|
308
|
+
*
|
|
309
|
+
* @public
|
|
310
|
+
*/
|
|
311
|
+
declare type DiffChangeType = 'added' | 'removed' | 'modified' | 'unchanged';
|
|
312
|
+
|
|
233
313
|
declare namespace EditorRules {
|
|
234
314
|
export {
|
|
235
315
|
IConditionalJsonKeyResult,
|
|
@@ -276,6 +356,98 @@ declare interface IConditionalJsonRuleOptions extends Partial<IJsonEditorOptions
|
|
|
276
356
|
flattenUnconditionalValues?: boolean;
|
|
277
357
|
}
|
|
278
358
|
|
|
359
|
+
/**
|
|
360
|
+
* Represents a single change in a JSON diff operation.
|
|
361
|
+
*
|
|
362
|
+
* Each change describes a specific difference between two JSON values, including
|
|
363
|
+
* the location of the change and the old/new values involved.
|
|
364
|
+
*
|
|
365
|
+
* @example
|
|
366
|
+
* ```typescript
|
|
367
|
+
* // Example changes from diffing { name: "John", age: 30 } vs { name: "Jane", city: "NYC" }
|
|
368
|
+
* const changes: IDiffChange[] = [
|
|
369
|
+
* { path: "name", type: "modified", oldValue: "John", newValue: "Jane" },
|
|
370
|
+
* { path: "age", type: "removed", oldValue: 30 },
|
|
371
|
+
* { path: "city", type: "added", newValue: "NYC" }
|
|
372
|
+
* ];
|
|
373
|
+
* ```
|
|
374
|
+
*
|
|
375
|
+
* @public
|
|
376
|
+
*/
|
|
377
|
+
declare interface IDiffChange {
|
|
378
|
+
/**
|
|
379
|
+
* The path to the changed value using dot notation.
|
|
380
|
+
*
|
|
381
|
+
* For nested objects, uses dots to separate levels (e.g., "user.profile.name").
|
|
382
|
+
* For arrays, uses numeric indices (e.g., "items.0.id", "tags.2").
|
|
383
|
+
* Empty string indicates the root value itself changed.
|
|
384
|
+
*
|
|
385
|
+
* @example "user.name", "items.0.id", "settings.theme", ""
|
|
386
|
+
*/
|
|
387
|
+
path: string;
|
|
388
|
+
/**
|
|
389
|
+
* The type of change that occurred.
|
|
390
|
+
*
|
|
391
|
+
* @see {@link DiffChangeType} for detailed descriptions of each change type.
|
|
392
|
+
*/
|
|
393
|
+
type: DiffChangeType;
|
|
394
|
+
/**
|
|
395
|
+
* The value in the first object.
|
|
396
|
+
*
|
|
397
|
+
* - Present for `'removed'` and `'modified'` changes
|
|
398
|
+
* - Present for `'unchanged'` changes when `includeUnchanged` is true
|
|
399
|
+
* - Undefined for `'added'` changes
|
|
400
|
+
*/
|
|
401
|
+
oldValue?: JsonValue;
|
|
402
|
+
/**
|
|
403
|
+
* The value in the second object.
|
|
404
|
+
*
|
|
405
|
+
* - Present for `'added'` and `'modified'` changes
|
|
406
|
+
* - Present for `'unchanged'` changes when `includeUnchanged` is true
|
|
407
|
+
* - Undefined for `'removed'` changes
|
|
408
|
+
*/
|
|
409
|
+
newValue?: JsonValue;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Result of a JSON diff operation containing all detected changes.
|
|
414
|
+
*
|
|
415
|
+
* This interface provides detailed information about every difference found
|
|
416
|
+
* between two JSON values, making it ideal for analysis, debugging, and
|
|
417
|
+
* understanding exactly what changed.
|
|
418
|
+
*
|
|
419
|
+
* @example
|
|
420
|
+
* ```typescript
|
|
421
|
+
* const result: IDiffResult = {
|
|
422
|
+
* changes: [
|
|
423
|
+
* { path: "name", type: "modified", oldValue: "John", newValue: "Jane" },
|
|
424
|
+
* { path: "hobbies.1", type: "added", newValue: "gaming" }
|
|
425
|
+
* ],
|
|
426
|
+
* identical: false
|
|
427
|
+
* };
|
|
428
|
+
* ```
|
|
429
|
+
*
|
|
430
|
+
* @see {@link IDiffChange} for details about individual change objects
|
|
431
|
+
* @see {@link Diff.jsonDiff} for the function that produces this result
|
|
432
|
+
* @public
|
|
433
|
+
*/
|
|
434
|
+
declare interface IDiffResult {
|
|
435
|
+
/**
|
|
436
|
+
* Array of all changes detected between the two JSON objects.
|
|
437
|
+
*
|
|
438
|
+
* Changes are ordered by the path where they occur. For nested structures,
|
|
439
|
+
* parent changes appear before child changes.
|
|
440
|
+
*/
|
|
441
|
+
changes: IDiffChange[];
|
|
442
|
+
/**
|
|
443
|
+
* True if the objects are identical, false otherwise.
|
|
444
|
+
*
|
|
445
|
+
* When true, the `changes` array will be empty (unless `includeUnchanged`
|
|
446
|
+
* option was used, in which case it may contain 'unchanged' entries).
|
|
447
|
+
*/
|
|
448
|
+
identical: boolean;
|
|
449
|
+
}
|
|
450
|
+
|
|
279
451
|
/**
|
|
280
452
|
* A specialized JSON editor which does a deep clone of a supplied `JsonValue`.
|
|
281
453
|
* @public
|
|
@@ -397,6 +569,64 @@ export declare interface IJsonConverterOptions {
|
|
|
397
569
|
onUndefinedPropertyValue: 'error' | 'ignore';
|
|
398
570
|
}
|
|
399
571
|
|
|
572
|
+
/**
|
|
573
|
+
* Options for customizing JSON diff behavior.
|
|
574
|
+
*
|
|
575
|
+
* These options allow you to control how the diff algorithm processes
|
|
576
|
+
* different types of JSON structures and what information is included
|
|
577
|
+
* in the results.
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* ```typescript
|
|
581
|
+
* // Include unchanged values and use custom path separator
|
|
582
|
+
* const options: IJsonDiffOptions = {
|
|
583
|
+
* includeUnchanged: true,
|
|
584
|
+
* pathSeparator: '/',
|
|
585
|
+
* arrayOrderMatters: false
|
|
586
|
+
* };
|
|
587
|
+
*
|
|
588
|
+
* const result = jsonDiff(obj1, obj2, options);
|
|
589
|
+
* ```
|
|
590
|
+
*
|
|
591
|
+
* @public
|
|
592
|
+
*/
|
|
593
|
+
declare interface IJsonDiffOptions {
|
|
594
|
+
/**
|
|
595
|
+
* If true, includes unchanged values in the result.
|
|
596
|
+
*
|
|
597
|
+
* When enabled, the diff result will include entries with `type: 'unchanged'`
|
|
598
|
+
* for properties that exist in both objects with identical values. This can
|
|
599
|
+
* be useful for displaying complete side-by-side comparisons.
|
|
600
|
+
*
|
|
601
|
+
* @defaultValue false
|
|
602
|
+
*/
|
|
603
|
+
includeUnchanged?: boolean;
|
|
604
|
+
/**
|
|
605
|
+
* Custom path separator for nested property paths.
|
|
606
|
+
*
|
|
607
|
+
* Controls the character used to separate levels in nested object paths.
|
|
608
|
+
* For example, with separator `'/'`, a nested property would be reported
|
|
609
|
+
* as `"user/profile/name"` instead of `"user.profile.name"`.
|
|
610
|
+
*
|
|
611
|
+
* @defaultValue "."
|
|
612
|
+
* @example "/", "-\>", "::"
|
|
613
|
+
*/
|
|
614
|
+
pathSeparator?: string;
|
|
615
|
+
/**
|
|
616
|
+
* If true, treats arrays as ordered lists where position matters.
|
|
617
|
+
* If false, treats arrays as unordered sets.
|
|
618
|
+
*
|
|
619
|
+
* When `true` (default), array changes are reported by index position:
|
|
620
|
+
* `[1,2,3]` vs `[1,3,2]` shows modifications at indices 1 and 2.
|
|
621
|
+
*
|
|
622
|
+
* When `false`, arrays are compared as sets: `[1,2,3]` vs `[1,3,2]`
|
|
623
|
+
* may be considered equivalent (simplified unordered comparison).
|
|
624
|
+
*
|
|
625
|
+
* @defaultValue true
|
|
626
|
+
*/
|
|
627
|
+
arrayOrderMatters?: boolean;
|
|
628
|
+
}
|
|
629
|
+
|
|
400
630
|
/**
|
|
401
631
|
* Merge options for a {@link JsonEditor | JsonEditor}.
|
|
402
632
|
* @public
|
|
@@ -607,6 +837,151 @@ declare interface ITemplatedJsonRuleOptions extends Partial<IJsonEditorOptions>
|
|
|
607
837
|
useValueTemplates?: boolean;
|
|
608
838
|
}
|
|
609
839
|
|
|
840
|
+
/**
|
|
841
|
+
* Result of a three-way JSON diff operation.
|
|
842
|
+
*
|
|
843
|
+
* This interface provides an actionable representation of differences between
|
|
844
|
+
* two JSON values by separating them into three distinct objects. This approach
|
|
845
|
+
* makes it easy to apply changes, display side-by-side comparisons, perform
|
|
846
|
+
* merges, or programmatically work with the differences.
|
|
847
|
+
*
|
|
848
|
+
* **Key Benefits:**
|
|
849
|
+
* - **Actionable Results**: Objects can be directly used for merging or applying changes
|
|
850
|
+
* - **UI-Friendly**: Perfect for side-by-side diff displays with clear visual separation
|
|
851
|
+
* - **Merge-Ready**: Simplified three-way merge operations
|
|
852
|
+
* - **Structured Data**: Maintains original JSON structure rather than flattened paths
|
|
853
|
+
*
|
|
854
|
+
* @example Basic usage
|
|
855
|
+
* ```typescript
|
|
856
|
+
* const result: IThreeWayDiff = {
|
|
857
|
+
* onlyInA: { name: "John", city: "NYC" }, // Original or removed data
|
|
858
|
+
* unchanged: { age: 30 }, // Stable data
|
|
859
|
+
* onlyInB: { name: "Jane", country: "USA" }, // New or modified data
|
|
860
|
+
* metadata: { added: 1, removed: 1, modified: 1, unchanged: 1 },
|
|
861
|
+
* identical: false
|
|
862
|
+
* };
|
|
863
|
+
*
|
|
864
|
+
* // Apply changes: merge unchanged + onlyInB
|
|
865
|
+
* const updated = { ...result.unchanged, ...result.onlyInB };
|
|
866
|
+
* // Result: { age: 30, name: "Jane", country: "USA" }
|
|
867
|
+
*
|
|
868
|
+
* // Revert changes: merge unchanged + onlyInA
|
|
869
|
+
* const reverted = { ...result.unchanged, ...result.onlyInA };
|
|
870
|
+
* // Result: { age: 30, name: "John", city: "NYC" }
|
|
871
|
+
* ```
|
|
872
|
+
*
|
|
873
|
+
* @see {@link IThreeWayDiffMetadata} for metadata structure details
|
|
874
|
+
* @see {@link jsonThreeWayDiff} for the function that produces this result
|
|
875
|
+
* @see {@link Diff.jsonDiff} for an alternative detailed change-list approach
|
|
876
|
+
*
|
|
877
|
+
* @public
|
|
878
|
+
*/
|
|
879
|
+
declare interface IThreeWayDiff {
|
|
880
|
+
/**
|
|
881
|
+
* Contains properties that exist only in the first object, plus the first object's
|
|
882
|
+
* version of any properties that exist in both but have different values.
|
|
883
|
+
*
|
|
884
|
+
* This object represents the "old" or "source" state and can be used for:
|
|
885
|
+
* - Reverting changes by merging with `unchanged`
|
|
886
|
+
* - Displaying what was removed or changed from the original
|
|
887
|
+
* - Understanding the baseline state before modifications
|
|
888
|
+
*
|
|
889
|
+
* Will be `null` if no properties are unique to the first object.
|
|
890
|
+
*/
|
|
891
|
+
onlyInA: JsonValue;
|
|
892
|
+
/**
|
|
893
|
+
* Contains properties that exist in both objects with identical values.
|
|
894
|
+
*
|
|
895
|
+
* This object represents the stable, consistent data between both inputs
|
|
896
|
+
* and can be used for:
|
|
897
|
+
* - The foundation for merging operations
|
|
898
|
+
* - Identifying what remained constant during changes
|
|
899
|
+
* - Building complete objects by combining with other parts
|
|
900
|
+
*
|
|
901
|
+
* Will be `null` if no properties are shared between the objects.
|
|
902
|
+
*/
|
|
903
|
+
unchanged: JsonValue;
|
|
904
|
+
/**
|
|
905
|
+
* Contains properties that exist only in the second object, plus the second object's
|
|
906
|
+
* version of any properties that exist in both but have different values.
|
|
907
|
+
*
|
|
908
|
+
* This object represents the "new" or "target" state and can be used for:
|
|
909
|
+
* - Applying changes by merging with `unchanged`
|
|
910
|
+
* - Displaying what was added or changed in the update
|
|
911
|
+
* - Understanding the desired end state after modifications
|
|
912
|
+
*
|
|
913
|
+
* Will be `null` if no properties are unique to the second object.
|
|
914
|
+
*/
|
|
915
|
+
onlyInB: JsonValue;
|
|
916
|
+
/**
|
|
917
|
+
* Summary metadata about the differences found.
|
|
918
|
+
*
|
|
919
|
+
* Provides counts of added, removed, modified, and unchanged properties
|
|
920
|
+
* for quick assessment of the scope and nature of changes.
|
|
921
|
+
*/
|
|
922
|
+
metadata: IThreeWayDiffMetadata;
|
|
923
|
+
/**
|
|
924
|
+
* True if the objects are identical, false otherwise.
|
|
925
|
+
*
|
|
926
|
+
* When `true`, both `onlyInA` and `onlyInB` will be `null`, and `unchanged`
|
|
927
|
+
* will contain the complete shared structure. The metadata will show zero
|
|
928
|
+
* added, removed, and modified properties.
|
|
929
|
+
*/
|
|
930
|
+
identical: boolean;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/**
|
|
934
|
+
* Metadata about the differences found in a three-way diff.
|
|
935
|
+
*
|
|
936
|
+
* Provides summary statistics about the types and quantities of changes
|
|
937
|
+
* detected between two JSON values, making it easy to understand the
|
|
938
|
+
* overall scope of differences at a glance.
|
|
939
|
+
*
|
|
940
|
+
* @example
|
|
941
|
+
* ```typescript
|
|
942
|
+
* const metadata: IThreeWayDiffMetadata = {
|
|
943
|
+
* removed: 2, // 2 properties only in first object
|
|
944
|
+
* added: 1, // 1 property only in second object
|
|
945
|
+
* modified: 3, // 3 properties changed between objects
|
|
946
|
+
* unchanged: 5 // 5 properties identical in both objects
|
|
947
|
+
* };
|
|
948
|
+
*
|
|
949
|
+
* console.log(`Total changes: ${metadata.added + metadata.removed + metadata.modified}`);
|
|
950
|
+
* console.log(`Stability: ${metadata.unchanged / (metadata.unchanged + metadata.modified) * 100}%`);
|
|
951
|
+
* ```
|
|
952
|
+
*
|
|
953
|
+
* @public
|
|
954
|
+
*/
|
|
955
|
+
declare interface IThreeWayDiffMetadata {
|
|
956
|
+
/**
|
|
957
|
+
* Number of properties that exist only in the first object.
|
|
958
|
+
*
|
|
959
|
+
* These represent data that was removed when transitioning from
|
|
960
|
+
* the first object to the second object.
|
|
961
|
+
*/
|
|
962
|
+
removed: number;
|
|
963
|
+
/**
|
|
964
|
+
* Number of properties that exist only in the second object.
|
|
965
|
+
*
|
|
966
|
+
* These represent new data that was added when transitioning from
|
|
967
|
+
* the first object to the second object.
|
|
968
|
+
*/
|
|
969
|
+
added: number;
|
|
970
|
+
/**
|
|
971
|
+
* Number of properties that exist in both objects but have different values.
|
|
972
|
+
*
|
|
973
|
+
* These represent data that was modified during the transition between objects.
|
|
974
|
+
* For arrays, this counts entire array replacements as single modifications.
|
|
975
|
+
*/
|
|
976
|
+
modified: number;
|
|
977
|
+
/**
|
|
978
|
+
* Number of properties that exist in both objects with identical values.
|
|
979
|
+
*
|
|
980
|
+
* These represent stable data that remained consistent between the two objects.
|
|
981
|
+
*/
|
|
982
|
+
unchanged: number;
|
|
983
|
+
}
|
|
984
|
+
|
|
610
985
|
/**
|
|
611
986
|
* A simple validating {@link JsonConverter | JSON converter}. Converts unknown to
|
|
612
987
|
* JSON or fails if the unknown contains any invalid JSON values.
|
|
@@ -759,6 +1134,92 @@ export declare class JsonConverter extends JsonEditorConverter {
|
|
|
759
1134
|
static create(options?: Partial<IJsonConverterOptions>): Result<JsonConverter>;
|
|
760
1135
|
}
|
|
761
1136
|
|
|
1137
|
+
/**
|
|
1138
|
+
* Performs a deep diff comparison between two JSON values.
|
|
1139
|
+
*
|
|
1140
|
+
* This function provides detailed change tracking by analyzing every difference
|
|
1141
|
+
* between two JSON structures. It returns a list of specific changes with paths,
|
|
1142
|
+
* making it ideal for debugging, logging, change analysis, and understanding
|
|
1143
|
+
* exactly what has changed between two data states.
|
|
1144
|
+
*
|
|
1145
|
+
* **Key Features:**
|
|
1146
|
+
* - Deep recursive comparison of nested objects and arrays
|
|
1147
|
+
* - Precise path tracking using dot notation (e.g., "user.profile.name")
|
|
1148
|
+
* - Support for all JSON value types: objects, arrays, primitives, null
|
|
1149
|
+
* - Configurable array comparison (ordered vs unordered)
|
|
1150
|
+
* - Optional inclusion of unchanged values for complete comparisons
|
|
1151
|
+
*
|
|
1152
|
+
* **Use Cases:**
|
|
1153
|
+
* - Debugging data changes in applications
|
|
1154
|
+
* - Generating change logs or audit trails
|
|
1155
|
+
* - Validating API responses against expected data
|
|
1156
|
+
* - Creating detailed diff reports for data synchronization
|
|
1157
|
+
*
|
|
1158
|
+
* @param obj1 - The first JSON value to compare (often the "before" state)
|
|
1159
|
+
* @param obj2 - The second JSON value to compare (often the "after" state)
|
|
1160
|
+
* @param options - Optional configuration for customizing diff behavior
|
|
1161
|
+
* @returns A Result containing the diff result with all detected changes
|
|
1162
|
+
*
|
|
1163
|
+
* @example Basic usage with objects
|
|
1164
|
+
* ```typescript
|
|
1165
|
+
* const before = { name: "John", age: 30, city: "NYC" };
|
|
1166
|
+
* const after = { name: "Jane", age: 30, country: "USA" };
|
|
1167
|
+
*
|
|
1168
|
+
* const result = jsonDiff(before, after);
|
|
1169
|
+
* if (result.success) {
|
|
1170
|
+
* result.value.changes.forEach(change => {
|
|
1171
|
+
* console.log(`${change.path}: ${change.type}`);
|
|
1172
|
+
* // Output:
|
|
1173
|
+
* // name: modified
|
|
1174
|
+
* // city: removed
|
|
1175
|
+
* // country: added
|
|
1176
|
+
* });
|
|
1177
|
+
* }
|
|
1178
|
+
* ```
|
|
1179
|
+
*
|
|
1180
|
+
* @example With arrays and nested structures
|
|
1181
|
+
* ```typescript
|
|
1182
|
+
* const user1 = {
|
|
1183
|
+
* profile: { name: "John", hobbies: ["reading"] },
|
|
1184
|
+
* settings: { theme: "dark" }
|
|
1185
|
+
* };
|
|
1186
|
+
* const user2 = {
|
|
1187
|
+
* profile: { name: "John", hobbies: ["reading", "gaming"] },
|
|
1188
|
+
* settings: { theme: "light", notifications: true }
|
|
1189
|
+
* };
|
|
1190
|
+
*
|
|
1191
|
+
* const result = jsonDiff(user1, user2);
|
|
1192
|
+
* if (result.success) {
|
|
1193
|
+
* console.log(result.value.changes);
|
|
1194
|
+
* // [
|
|
1195
|
+
* // { path: "profile.hobbies.1", type: "added", newValue: "gaming" },
|
|
1196
|
+
* // { path: "settings.theme", type: "modified", oldValue: "dark", newValue: "light" },
|
|
1197
|
+
* // { path: "settings.notifications", type: "added", newValue: true }
|
|
1198
|
+
* // ]
|
|
1199
|
+
* }
|
|
1200
|
+
* ```
|
|
1201
|
+
*
|
|
1202
|
+
* @example Using options for custom behavior
|
|
1203
|
+
* ```typescript
|
|
1204
|
+
* const options: IJsonDiffOptions = {
|
|
1205
|
+
* includeUnchanged: true, // Include unchanged properties
|
|
1206
|
+
* pathSeparator: '/', // Use '/' instead of '.' in paths
|
|
1207
|
+
* arrayOrderMatters: false // Treat arrays as unordered sets
|
|
1208
|
+
* };
|
|
1209
|
+
*
|
|
1210
|
+
* const result = jsonDiff(obj1, obj2, options);
|
|
1211
|
+
* ```
|
|
1212
|
+
*
|
|
1213
|
+
* @see {@link IDiffResult} for the structure of returned results
|
|
1214
|
+
* @see {@link IDiffChange} for details about individual changes
|
|
1215
|
+
* @see {@link IJsonDiffOptions} for available configuration options
|
|
1216
|
+
* @see {@link jsonThreeWayDiff} for an alternative API focused on actionable results
|
|
1217
|
+
* @see {@link jsonEquals} for simple equality checking without change details
|
|
1218
|
+
*
|
|
1219
|
+
* @public
|
|
1220
|
+
*/
|
|
1221
|
+
declare function jsonDiff(obj1: JsonValue, obj2: JsonValue, options?: IJsonDiffOptions): Result<IDiffResult>;
|
|
1222
|
+
|
|
762
1223
|
/**
|
|
763
1224
|
* Possible `DetailedResult` details for various editor operations.
|
|
764
1225
|
* @public
|
|
@@ -1091,6 +1552,83 @@ export declare class JsonEditorState {
|
|
|
1091
1552
|
*/
|
|
1092
1553
|
export declare type JsonEditorValidationRules = 'invalidPropertyName' | 'invalidPropertyValue' | 'undefinedPropertyValue';
|
|
1093
1554
|
|
|
1555
|
+
/**
|
|
1556
|
+
* A simpler helper function that returns true if two JSON values are deeply equal.
|
|
1557
|
+
*
|
|
1558
|
+
* This function provides a fast boolean check for JSON equality without the overhead
|
|
1559
|
+
* of tracking individual changes. It performs the same deep comparison logic as
|
|
1560
|
+
* {@link Diff.jsonDiff} but returns only a true/false result, making it ideal for
|
|
1561
|
+
* conditional logic and validation scenarios.
|
|
1562
|
+
*
|
|
1563
|
+
* **Key Features:**
|
|
1564
|
+
* - Deep recursive comparison of all nested structures
|
|
1565
|
+
* - Handles all JSON types: objects, arrays, primitives, null
|
|
1566
|
+
* - Object property order independence
|
|
1567
|
+
* - Array order significance (index positions matter)
|
|
1568
|
+
* - Performance optimized for equality checking
|
|
1569
|
+
*
|
|
1570
|
+
* **Use Cases:**
|
|
1571
|
+
* - Conditional logic based on data equality
|
|
1572
|
+
* - Input validation and testing assertions
|
|
1573
|
+
* - Caching and memoization keys
|
|
1574
|
+
* - Quick checks before expensive diff operations
|
|
1575
|
+
*
|
|
1576
|
+
* @param obj1 - The first JSON value to compare
|
|
1577
|
+
* @param obj2 - The second JSON value to compare
|
|
1578
|
+
* @returns True if the values are deeply equal, false otherwise
|
|
1579
|
+
*
|
|
1580
|
+
* @example Basic equality checking
|
|
1581
|
+
* ```typescript
|
|
1582
|
+
* // Objects with same structure and values
|
|
1583
|
+
* const user1 = { name: "John", hobbies: ["reading", "gaming"] };
|
|
1584
|
+
* const user2 = { name: "John", hobbies: ["reading", "gaming"] };
|
|
1585
|
+
* console.log(jsonEquals(user1, user2)); // true
|
|
1586
|
+
*
|
|
1587
|
+
* // Different property order (still equal)
|
|
1588
|
+
* const obj1 = { a: 1, b: 2 };
|
|
1589
|
+
* const obj2 = { b: 2, a: 1 };
|
|
1590
|
+
* console.log(jsonEquals(obj1, obj2)); // true
|
|
1591
|
+
*
|
|
1592
|
+
* // Different values
|
|
1593
|
+
* const before = { status: "pending" };
|
|
1594
|
+
* const after = { status: "completed" };
|
|
1595
|
+
* console.log(jsonEquals(before, after)); // false
|
|
1596
|
+
* ```
|
|
1597
|
+
*
|
|
1598
|
+
* @example With nested structures
|
|
1599
|
+
* ```typescript
|
|
1600
|
+
* const config1 = {
|
|
1601
|
+
* database: { host: "localhost", port: 5432 },
|
|
1602
|
+
* features: ["auth", "cache"]
|
|
1603
|
+
* };
|
|
1604
|
+
* const config2 = {
|
|
1605
|
+
* database: { host: "localhost", port: 5432 },
|
|
1606
|
+
* features: ["auth", "cache"]
|
|
1607
|
+
* };
|
|
1608
|
+
*
|
|
1609
|
+
* if (jsonEquals(config1, config2)) {
|
|
1610
|
+
* console.log("Configurations are identical");
|
|
1611
|
+
* }
|
|
1612
|
+
* ```
|
|
1613
|
+
*
|
|
1614
|
+
* @example Array order sensitivity
|
|
1615
|
+
* ```typescript
|
|
1616
|
+
* const list1 = [1, 2, 3];
|
|
1617
|
+
* const list2 = [3, 2, 1];
|
|
1618
|
+
* console.log(jsonEquals(list1, list2)); // false - order matters
|
|
1619
|
+
*
|
|
1620
|
+
* const list3 = [1, 2, 3];
|
|
1621
|
+
* const list4 = [1, 2, 3];
|
|
1622
|
+
* console.log(jsonEquals(list3, list4)); // true - same order
|
|
1623
|
+
* ```
|
|
1624
|
+
*
|
|
1625
|
+
* @see {@link Diff.jsonDiff} for detailed change analysis when equality fails
|
|
1626
|
+
* @see {@link jsonThreeWayDiff} for actionable difference results
|
|
1627
|
+
*
|
|
1628
|
+
* @public
|
|
1629
|
+
*/
|
|
1630
|
+
declare function jsonEquals(obj1: JsonValue, obj2: JsonValue): boolean;
|
|
1631
|
+
|
|
1094
1632
|
/**
|
|
1095
1633
|
* A simple validating {@link JsonConverter | JSON converter}. Converts unknown
|
|
1096
1634
|
* to a `JsonObject`, or fails if the `unknown` contains invalid
|
|
@@ -1113,6 +1651,124 @@ export declare type JsonPropertyEditFailureReason = JsonEditFailureReason | 'def
|
|
|
1113
1651
|
*/
|
|
1114
1652
|
export declare type JsonReferenceMapFailureReason = 'unknown' | 'error';
|
|
1115
1653
|
|
|
1654
|
+
/**
|
|
1655
|
+
* Performs a three-way diff comparison between two JSON values, returning separate
|
|
1656
|
+
* objects containing the differences and similarities.
|
|
1657
|
+
*
|
|
1658
|
+
* This function provides an alternative to {@link Diff.jsonDiff} that focuses on actionable
|
|
1659
|
+
* results rather than detailed change analysis. Instead of a list of individual changes,
|
|
1660
|
+
* it returns three objects that can be directly used for merging, UI display, or
|
|
1661
|
+
* programmatic manipulation.
|
|
1662
|
+
*
|
|
1663
|
+
* **Key Features:**
|
|
1664
|
+
* - **Actionable Results**: Returns objects ready for immediate use in merging operations
|
|
1665
|
+
* - **Simplified Array Handling**: Arrays are treated as atomic values for cleaner results
|
|
1666
|
+
* - **Structural Preservation**: Maintains original JSON structure rather than flattened paths
|
|
1667
|
+
* - **UI-Optimized**: Perfect for side-by-side diff displays and change visualization
|
|
1668
|
+
* - **Merge-Friendly**: Designed specifically for three-way merge scenarios
|
|
1669
|
+
*
|
|
1670
|
+
* **Array Handling:**
|
|
1671
|
+
* Unlike {@link Diff.jsonDiff}, this function treats arrays as complete units. If arrays differ,
|
|
1672
|
+
* the entire array appears in the appropriate result object rather than computing
|
|
1673
|
+
* element-by-element deltas. This approach is simpler and more predictable for most
|
|
1674
|
+
* use cases involving data updates and synchronization.
|
|
1675
|
+
*
|
|
1676
|
+
* **Use Cases:**
|
|
1677
|
+
* - Applying configuration updates while preserving unchanged settings
|
|
1678
|
+
* - Creating side-by-side diff displays in user interfaces
|
|
1679
|
+
* - Building three-way merge tools for data synchronization
|
|
1680
|
+
* - Implementing undo/redo functionality with granular control
|
|
1681
|
+
* - Generating patch objects for API updates
|
|
1682
|
+
*
|
|
1683
|
+
* @param obj1 - The first JSON value to compare (often the "before" or "source" state)
|
|
1684
|
+
* @param obj2 - The second JSON value to compare (often the "after" or "target" state)
|
|
1685
|
+
* @returns A Result containing the three-way diff with separate objects and metadata
|
|
1686
|
+
*
|
|
1687
|
+
* @example Basic usage for applying changes
|
|
1688
|
+
* ```typescript
|
|
1689
|
+
* const original = { name: "John", age: 30, city: "NYC", active: true };
|
|
1690
|
+
* const updated = { name: "Jane", age: 30, country: "USA", active: true };
|
|
1691
|
+
*
|
|
1692
|
+
* const result = jsonThreeWayDiff(original, updated);
|
|
1693
|
+
* if (result.success) {
|
|
1694
|
+
* const { onlyInA, unchanged, onlyInB } = result.value;
|
|
1695
|
+
*
|
|
1696
|
+
* // Apply changes: merge unchanged + onlyInB
|
|
1697
|
+
* const applied = { ...unchanged, ...onlyInB };
|
|
1698
|
+
* console.log(applied); // { age: 30, active: true, name: "Jane", country: "USA" }
|
|
1699
|
+
*
|
|
1700
|
+
* // Revert changes: merge unchanged + onlyInA
|
|
1701
|
+
* const reverted = { ...unchanged, ...onlyInA };
|
|
1702
|
+
* console.log(reverted); // { age: 30, active: true, name: "John", city: "NYC" }
|
|
1703
|
+
* }
|
|
1704
|
+
* ```
|
|
1705
|
+
*
|
|
1706
|
+
* @example UI-friendly diff display
|
|
1707
|
+
* ```typescript
|
|
1708
|
+
* const result = jsonThreeWayDiff(userBefore, userAfter);
|
|
1709
|
+
* if (result.success) {
|
|
1710
|
+
* const { onlyInA, unchanged, onlyInB, metadata } = result.value;
|
|
1711
|
+
*
|
|
1712
|
+
* // Display summary
|
|
1713
|
+
* console.log(`Changes: ${metadata.added} added, ${metadata.removed} removed, ${metadata.modified} modified`);
|
|
1714
|
+
*
|
|
1715
|
+
* // Show removed/old values in red
|
|
1716
|
+
* if (onlyInA) displayInColor(onlyInA, 'red');
|
|
1717
|
+
*
|
|
1718
|
+
* // Show unchanged values in gray
|
|
1719
|
+
* if (unchanged) displayInColor(unchanged, 'gray');
|
|
1720
|
+
*
|
|
1721
|
+
* // Show added/new values in green
|
|
1722
|
+
* if (onlyInB) displayInColor(onlyInB, 'green');
|
|
1723
|
+
* }
|
|
1724
|
+
* ```
|
|
1725
|
+
*
|
|
1726
|
+
* @example Nested objects and array handling
|
|
1727
|
+
* ```typescript
|
|
1728
|
+
* const config1 = {
|
|
1729
|
+
* database: { host: "localhost", port: 5432 },
|
|
1730
|
+
* features: ["auth", "logging"],
|
|
1731
|
+
* version: "1.0"
|
|
1732
|
+
* };
|
|
1733
|
+
* const config2 = {
|
|
1734
|
+
* database: { host: "production.db", port: 5432 },
|
|
1735
|
+
* features: ["auth", "logging", "metrics"], // Array treated as complete unit
|
|
1736
|
+
* version: "1.1"
|
|
1737
|
+
* };
|
|
1738
|
+
*
|
|
1739
|
+
* const result = jsonThreeWayDiff(config1, config2);
|
|
1740
|
+
* if (result.success) {
|
|
1741
|
+
* // result.value.onlyInA = { database: { host: "localhost" }, features: ["auth", "logging"], version: "1.0" }
|
|
1742
|
+
* // result.value.unchanged = { database: { port: 5432 } }
|
|
1743
|
+
* // result.value.onlyInB = { database: { host: "production.db" }, features: ["auth", "logging", "metrics"], version: "1.1" }
|
|
1744
|
+
* }
|
|
1745
|
+
* ```
|
|
1746
|
+
*
|
|
1747
|
+
* @example Conditional updates based on changes
|
|
1748
|
+
* ```typescript
|
|
1749
|
+
* const result = jsonThreeWayDiff(currentState, newState);
|
|
1750
|
+
* if (result.success && !result.value.identical) {
|
|
1751
|
+
* const { metadata } = result.value;
|
|
1752
|
+
*
|
|
1753
|
+
* if (metadata.modified > 0) {
|
|
1754
|
+
* console.log("Critical settings changed - requires restart");
|
|
1755
|
+
* } else if (metadata.added > 0) {
|
|
1756
|
+
* console.log("New features enabled");
|
|
1757
|
+
* } else if (metadata.removed > 0) {
|
|
1758
|
+
* console.log("Features disabled");
|
|
1759
|
+
* }
|
|
1760
|
+
* }
|
|
1761
|
+
* ```
|
|
1762
|
+
*
|
|
1763
|
+
* @see {@link IThreeWayDiff} for the structure of returned results
|
|
1764
|
+
* @see {@link IThreeWayDiffMetadata} for metadata details
|
|
1765
|
+
* @see {@link Diff.jsonDiff} for detailed change-by-change analysis
|
|
1766
|
+
* @see {@link jsonEquals} for simple equality checking
|
|
1767
|
+
*
|
|
1768
|
+
* @public
|
|
1769
|
+
*/
|
|
1770
|
+
declare function jsonThreeWayDiff(obj1: JsonValue, obj2: JsonValue): Result<IThreeWayDiff>;
|
|
1771
|
+
|
|
1116
1772
|
/**
|
|
1117
1773
|
* Type representing either a `Map\<string, T\>` or a `Record\<string, T\>`.
|
|
1118
1774
|
* @public
|