json-diff-ts 5.0.0-alpha.1 → 5.0.0-alpha.2

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/index.d.cts CHANGED
@@ -1,11 +1,11 @@
1
- type FunctionKey = (obj: any, shouldReturnKeyName?: boolean) => any;
1
+ type FunctionKey<T = any> = (obj: T, shouldReturnKeyName?: boolean, index?: number) => any;
2
+
2
3
  type EmbeddedObjKeysType = Record<string, string | FunctionKey>;
3
4
  type EmbeddedObjKeysMapType = Map<string | RegExp, string | FunctionKey>;
4
5
  declare enum Operation {
5
6
  REMOVE = "REMOVE",
6
7
  ADD = "ADD",
7
- UPDATE = "UPDATE",
8
- MOVE = "MOVE"
8
+ UPDATE = "UPDATE"
9
9
  }
10
10
  interface IChange {
11
11
  type: Operation;
@@ -13,8 +13,6 @@ interface IChange {
13
13
  embeddedKey?: string | FunctionKey;
14
14
  value?: any;
15
15
  oldValue?: any;
16
- oldIndex?: number;
17
- newIndex?: number;
18
16
  changes?: IChange[];
19
17
  }
20
18
  type Changeset = IChange[];
@@ -25,14 +23,14 @@ interface IAtomicChange {
25
23
  valueType: string | null;
26
24
  value?: any;
27
25
  oldValue?: any;
28
- oldIndex?: number;
29
- newIndex?: number;
30
26
  }
31
27
  interface Options {
28
+ /** Identify array elements by a stable key instead of index. */
29
+ arrayIdentityKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType;
30
+ /** @deprecated Use `arrayIdentityKeys` instead. */
32
31
  embeddedObjKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType;
33
- keysToSkip?: string[];
32
+ keysToSkip?: readonly string[];
34
33
  treatTypeChangeAsReplace?: boolean;
35
- detectArrayMoves?: boolean;
36
34
  }
37
35
  /**
38
36
  * Computes the difference between two objects.
@@ -123,5 +121,185 @@ declare const createContainer: (value: object | []) => IComparisonEnrichedNode;
123
121
  declare const enrich: (object: any) => IComparisonEnrichedNode;
124
122
  declare const applyChangelist: (object: IComparisonEnrichedNode, changelist: IAtomicChange[]) => IComparisonEnrichedNode;
125
123
  declare const compare: (oldObject: any, newObject: any) => IComparisonEnrichedNode;
124
+ interface IComparisonDict {
125
+ type: string;
126
+ value?: any;
127
+ oldValue?: any;
128
+ }
129
+ interface IFlatChange {
130
+ path: string;
131
+ type: string;
132
+ value?: any;
133
+ oldValue?: any;
134
+ }
135
+ /**
136
+ * Recursively serializes an enriched comparison tree to a plain JS object.
137
+ * The result is JSON-serializable when contained `value`/`oldValue` are
138
+ * themselves JSON-serializable. Includes `value`/`oldValue` based on change
139
+ * type, not truthiness — `null` is preserved as a valid JSON value.
140
+ */
141
+ declare const comparisonToDict: (node: IComparisonEnrichedNode) => IComparisonDict;
142
+ /**
143
+ * Flattens an enriched comparison tree to a list of leaf changes with paths.
144
+ * Uses dot notation for identifier keys and bracket-quote notation for
145
+ * non-identifier keys (per spec Section 5.5).
146
+ *
147
+ * By default, `UNCHANGED` entries are excluded. Set `includeUnchanged: true`
148
+ * to include them.
149
+ */
150
+ declare const comparisonToFlatList: (node: IComparisonEnrichedNode, options?: {
151
+ includeUnchanged?: boolean;
152
+ }) => IFlatChange[];
153
+
154
+ type DeltaPathSegment = {
155
+ type: 'root';
156
+ } | {
157
+ type: 'property';
158
+ name: string;
159
+ } | {
160
+ type: 'index';
161
+ index: number;
162
+ } | {
163
+ type: 'keyFilter';
164
+ property: string;
165
+ value: unknown;
166
+ } | {
167
+ type: 'valueFilter';
168
+ value: unknown;
169
+ };
170
+ /**
171
+ * Format a value as a canonical JSON Delta filter literal.
172
+ * Strings → single-quoted with doubled-quote escaping.
173
+ * Numbers, booleans, null → plain JSON representation.
174
+ */
175
+ declare function formatFilterLiteral(value: unknown): string;
176
+ /**
177
+ * Parse a filter literal string into a typed JS value.
178
+ * Reverse of formatFilterLiteral.
179
+ */
180
+ declare function parseFilterLiteral(s: string): unknown;
181
+ /**
182
+ * Parse a JSON Delta Path string into an array of typed segments.
183
+ * Follows the grammar from the JSON Delta spec Section 5.1.
184
+ */
185
+ declare function parseDeltaPath(path: string): DeltaPathSegment[];
186
+ /**
187
+ * Build a canonical JSON Delta Path string from an array of segments.
188
+ */
189
+ declare function buildDeltaPath(segments: DeltaPathSegment[]): string;
190
+
191
+ type DeltaOp = 'add' | 'remove' | 'replace';
192
+ interface IDeltaOperation {
193
+ op: DeltaOp;
194
+ path: string;
195
+ value?: any;
196
+ oldValue?: any;
197
+ [key: string]: any;
198
+ }
199
+ interface IJsonDelta {
200
+ format: 'json-delta';
201
+ version: number;
202
+ operations: IDeltaOperation[];
203
+ [key: string]: any;
204
+ }
205
+ interface DeltaOptions extends Options {
206
+ /** Include oldValue for reversibility. Default: true */
207
+ reversible?: boolean;
208
+ }
209
+ declare function validateDelta(delta: unknown): {
210
+ valid: boolean;
211
+ errors: string[];
212
+ };
213
+ /**
214
+ * Compute a canonical JSON Delta between two objects.
215
+ * This is the spec-conformant delta producer.
216
+ */
217
+ declare function diffDelta(oldObj: any, newObj: any, options?: DeltaOptions): IJsonDelta;
218
+ /**
219
+ * Convert an existing v4 changeset or atomic changes to a JSON Delta document.
220
+ * Best-effort bridge — filter literals will always be string-quoted.
221
+ * Use `diffDelta()` for canonical spec-conformant output.
222
+ */
223
+ declare function toDelta(changeset: Changeset | IAtomicChange[], options?: {
224
+ reversible?: boolean;
225
+ }): IJsonDelta;
226
+ /**
227
+ * Convert a JSON Delta document to v4 atomic changes.
228
+ * Returns IAtomicChange[] — one atom per delta operation.
229
+ * Use `unatomizeChangeset(fromDelta(delta))` if you need a hierarchical Changeset.
230
+ */
231
+ declare function fromDelta(delta: IJsonDelta): IAtomicChange[];
232
+ /**
233
+ * Compute the inverse of a JSON Delta document (spec Section 9.2).
234
+ * Requires all replace/remove operations to have oldValue.
235
+ */
236
+ declare function invertDelta(delta: IJsonDelta): IJsonDelta;
237
+ /**
238
+ * Apply a JSON Delta document to an object.
239
+ * Processes operations sequentially. Handles root operations directly.
240
+ * Returns the result (MUST use return value for root primitive replacements).
241
+ */
242
+ declare function applyDelta(obj: any, delta: IJsonDelta): any;
243
+ /**
244
+ * Revert a JSON Delta by computing its inverse and applying it.
245
+ * Requires all replace/remove operations to have oldValue.
246
+ */
247
+ declare function revertDelta(obj: any, delta: IJsonDelta): any;
248
+
249
+ /**
250
+ * Returns a copy of the operation containing only spec-defined keys
251
+ * (`op`, `path`, `value`, `oldValue`). Complement of `operationExtensions`.
252
+ */
253
+ declare function operationSpecDict(op: IDeltaOperation): IDeltaOperation;
254
+ /**
255
+ * Returns a record of non-spec keys from the operation (extension properties).
256
+ * Complement of `operationSpecDict`.
257
+ */
258
+ declare function operationExtensions(op: IDeltaOperation): Record<string, any>;
259
+ /**
260
+ * Returns the terminal property name from the operation's path, or `null`
261
+ * for root, index, and filter segments.
262
+ */
263
+ declare function leafProperty(op: IDeltaOperation): string | null;
264
+ /**
265
+ * Returns a copy of the delta with only spec-defined keys in the envelope
266
+ * and each operation. Strips all extension properties.
267
+ */
268
+ declare function deltaSpecDict(delta: IJsonDelta): IJsonDelta;
269
+ /**
270
+ * Returns a record of non-spec keys from the delta envelope.
271
+ * Complement of `deltaSpecDict`.
272
+ */
273
+ declare function deltaExtensions(delta: IJsonDelta): Record<string, any>;
274
+ /**
275
+ * Transforms each operation in the delta using the provided function.
276
+ * Returns a new delta (immutable). Preserves all envelope properties.
277
+ */
278
+ declare function deltaMap(delta: IJsonDelta, fn: (op: IDeltaOperation, index: number) => IDeltaOperation): IJsonDelta;
279
+ /**
280
+ * Returns a new delta with the given extension properties merged onto every
281
+ * operation. Immutable — the original delta is not modified.
282
+ */
283
+ declare function deltaStamp(delta: IJsonDelta, extensions: Record<string, any>): IJsonDelta;
284
+ /**
285
+ * Groups operations in the delta by the result of `keyFn`. Returns a record
286
+ * mapping each key to a sub-delta containing only the matching operations.
287
+ * Each sub-delta preserves all envelope properties.
288
+ */
289
+ declare function deltaGroupBy(delta: IJsonDelta, keyFn: (op: IDeltaOperation) => string): Record<string, IJsonDelta>;
290
+ interface SquashDeltasOptions extends DeltaOptions {
291
+ /** Pre-computed final state. When provided with deltas, used instead of computing. */
292
+ target?: any;
293
+ /** Verify that `target` matches sequential application of deltas. Default: true. */
294
+ verifyTarget?: boolean;
295
+ }
296
+ /**
297
+ * Compacts multiple deltas into a single net-effect delta. The result is
298
+ * equivalent to applying all deltas sequentially, but expressed as a single
299
+ * `source → final` diff.
300
+ *
301
+ * Envelope extensions from all input deltas are merged (last-wins on conflict).
302
+ */
303
+ declare function squashDeltas(source: any, deltas: IJsonDelta[], options?: SquashDeltasOptions): IJsonDelta;
126
304
 
127
- export { type Changeset, CompareOperation, type EmbeddedObjKeysMapType, type EmbeddedObjKeysType, type IAtomicChange, type IChange, type IComparisonEnrichedNode, Operation, type Options, applyChangelist, applyChangeset, atomizeChangeset, compare, createContainer, createValue, diff, enrich, getTypeOfObj, revertChangeset, unatomizeChangeset };
305
+ export { type Changeset, CompareOperation, type DeltaOp, type DeltaOptions, type DeltaPathSegment, type EmbeddedObjKeysMapType, type EmbeddedObjKeysType, type IAtomicChange, type IChange, type IComparisonDict, type IComparisonEnrichedNode, type IDeltaOperation, type IFlatChange, type IJsonDelta, Operation, type Options, type SquashDeltasOptions, applyChangelist, applyChangeset, applyDelta, atomizeChangeset, buildDeltaPath, compare, comparisonToDict, comparisonToFlatList, createContainer, createValue, deltaExtensions, deltaGroupBy, deltaMap, deltaSpecDict, deltaStamp, diff, diffDelta, enrich, formatFilterLiteral, fromDelta, getTypeOfObj, invertDelta, leafProperty, operationExtensions, operationSpecDict, parseDeltaPath, parseFilterLiteral, revertChangeset, revertDelta, squashDeltas, toDelta, unatomizeChangeset, validateDelta };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- type FunctionKey = (obj: any, shouldReturnKeyName?: boolean) => any;
1
+ type FunctionKey<T = any> = (obj: T, shouldReturnKeyName?: boolean, index?: number) => any;
2
+
2
3
  type EmbeddedObjKeysType = Record<string, string | FunctionKey>;
3
4
  type EmbeddedObjKeysMapType = Map<string | RegExp, string | FunctionKey>;
4
5
  declare enum Operation {
5
6
  REMOVE = "REMOVE",
6
7
  ADD = "ADD",
7
- UPDATE = "UPDATE",
8
- MOVE = "MOVE"
8
+ UPDATE = "UPDATE"
9
9
  }
10
10
  interface IChange {
11
11
  type: Operation;
@@ -13,8 +13,6 @@ interface IChange {
13
13
  embeddedKey?: string | FunctionKey;
14
14
  value?: any;
15
15
  oldValue?: any;
16
- oldIndex?: number;
17
- newIndex?: number;
18
16
  changes?: IChange[];
19
17
  }
20
18
  type Changeset = IChange[];
@@ -25,14 +23,14 @@ interface IAtomicChange {
25
23
  valueType: string | null;
26
24
  value?: any;
27
25
  oldValue?: any;
28
- oldIndex?: number;
29
- newIndex?: number;
30
26
  }
31
27
  interface Options {
28
+ /** Identify array elements by a stable key instead of index. */
29
+ arrayIdentityKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType;
30
+ /** @deprecated Use `arrayIdentityKeys` instead. */
32
31
  embeddedObjKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType;
33
- keysToSkip?: string[];
32
+ keysToSkip?: readonly string[];
34
33
  treatTypeChangeAsReplace?: boolean;
35
- detectArrayMoves?: boolean;
36
34
  }
37
35
  /**
38
36
  * Computes the difference between two objects.
@@ -123,5 +121,185 @@ declare const createContainer: (value: object | []) => IComparisonEnrichedNode;
123
121
  declare const enrich: (object: any) => IComparisonEnrichedNode;
124
122
  declare const applyChangelist: (object: IComparisonEnrichedNode, changelist: IAtomicChange[]) => IComparisonEnrichedNode;
125
123
  declare const compare: (oldObject: any, newObject: any) => IComparisonEnrichedNode;
124
+ interface IComparisonDict {
125
+ type: string;
126
+ value?: any;
127
+ oldValue?: any;
128
+ }
129
+ interface IFlatChange {
130
+ path: string;
131
+ type: string;
132
+ value?: any;
133
+ oldValue?: any;
134
+ }
135
+ /**
136
+ * Recursively serializes an enriched comparison tree to a plain JS object.
137
+ * The result is JSON-serializable when contained `value`/`oldValue` are
138
+ * themselves JSON-serializable. Includes `value`/`oldValue` based on change
139
+ * type, not truthiness — `null` is preserved as a valid JSON value.
140
+ */
141
+ declare const comparisonToDict: (node: IComparisonEnrichedNode) => IComparisonDict;
142
+ /**
143
+ * Flattens an enriched comparison tree to a list of leaf changes with paths.
144
+ * Uses dot notation for identifier keys and bracket-quote notation for
145
+ * non-identifier keys (per spec Section 5.5).
146
+ *
147
+ * By default, `UNCHANGED` entries are excluded. Set `includeUnchanged: true`
148
+ * to include them.
149
+ */
150
+ declare const comparisonToFlatList: (node: IComparisonEnrichedNode, options?: {
151
+ includeUnchanged?: boolean;
152
+ }) => IFlatChange[];
153
+
154
+ type DeltaPathSegment = {
155
+ type: 'root';
156
+ } | {
157
+ type: 'property';
158
+ name: string;
159
+ } | {
160
+ type: 'index';
161
+ index: number;
162
+ } | {
163
+ type: 'keyFilter';
164
+ property: string;
165
+ value: unknown;
166
+ } | {
167
+ type: 'valueFilter';
168
+ value: unknown;
169
+ };
170
+ /**
171
+ * Format a value as a canonical JSON Delta filter literal.
172
+ * Strings → single-quoted with doubled-quote escaping.
173
+ * Numbers, booleans, null → plain JSON representation.
174
+ */
175
+ declare function formatFilterLiteral(value: unknown): string;
176
+ /**
177
+ * Parse a filter literal string into a typed JS value.
178
+ * Reverse of formatFilterLiteral.
179
+ */
180
+ declare function parseFilterLiteral(s: string): unknown;
181
+ /**
182
+ * Parse a JSON Delta Path string into an array of typed segments.
183
+ * Follows the grammar from the JSON Delta spec Section 5.1.
184
+ */
185
+ declare function parseDeltaPath(path: string): DeltaPathSegment[];
186
+ /**
187
+ * Build a canonical JSON Delta Path string from an array of segments.
188
+ */
189
+ declare function buildDeltaPath(segments: DeltaPathSegment[]): string;
190
+
191
+ type DeltaOp = 'add' | 'remove' | 'replace';
192
+ interface IDeltaOperation {
193
+ op: DeltaOp;
194
+ path: string;
195
+ value?: any;
196
+ oldValue?: any;
197
+ [key: string]: any;
198
+ }
199
+ interface IJsonDelta {
200
+ format: 'json-delta';
201
+ version: number;
202
+ operations: IDeltaOperation[];
203
+ [key: string]: any;
204
+ }
205
+ interface DeltaOptions extends Options {
206
+ /** Include oldValue for reversibility. Default: true */
207
+ reversible?: boolean;
208
+ }
209
+ declare function validateDelta(delta: unknown): {
210
+ valid: boolean;
211
+ errors: string[];
212
+ };
213
+ /**
214
+ * Compute a canonical JSON Delta between two objects.
215
+ * This is the spec-conformant delta producer.
216
+ */
217
+ declare function diffDelta(oldObj: any, newObj: any, options?: DeltaOptions): IJsonDelta;
218
+ /**
219
+ * Convert an existing v4 changeset or atomic changes to a JSON Delta document.
220
+ * Best-effort bridge — filter literals will always be string-quoted.
221
+ * Use `diffDelta()` for canonical spec-conformant output.
222
+ */
223
+ declare function toDelta(changeset: Changeset | IAtomicChange[], options?: {
224
+ reversible?: boolean;
225
+ }): IJsonDelta;
226
+ /**
227
+ * Convert a JSON Delta document to v4 atomic changes.
228
+ * Returns IAtomicChange[] — one atom per delta operation.
229
+ * Use `unatomizeChangeset(fromDelta(delta))` if you need a hierarchical Changeset.
230
+ */
231
+ declare function fromDelta(delta: IJsonDelta): IAtomicChange[];
232
+ /**
233
+ * Compute the inverse of a JSON Delta document (spec Section 9.2).
234
+ * Requires all replace/remove operations to have oldValue.
235
+ */
236
+ declare function invertDelta(delta: IJsonDelta): IJsonDelta;
237
+ /**
238
+ * Apply a JSON Delta document to an object.
239
+ * Processes operations sequentially. Handles root operations directly.
240
+ * Returns the result (MUST use return value for root primitive replacements).
241
+ */
242
+ declare function applyDelta(obj: any, delta: IJsonDelta): any;
243
+ /**
244
+ * Revert a JSON Delta by computing its inverse and applying it.
245
+ * Requires all replace/remove operations to have oldValue.
246
+ */
247
+ declare function revertDelta(obj: any, delta: IJsonDelta): any;
248
+
249
+ /**
250
+ * Returns a copy of the operation containing only spec-defined keys
251
+ * (`op`, `path`, `value`, `oldValue`). Complement of `operationExtensions`.
252
+ */
253
+ declare function operationSpecDict(op: IDeltaOperation): IDeltaOperation;
254
+ /**
255
+ * Returns a record of non-spec keys from the operation (extension properties).
256
+ * Complement of `operationSpecDict`.
257
+ */
258
+ declare function operationExtensions(op: IDeltaOperation): Record<string, any>;
259
+ /**
260
+ * Returns the terminal property name from the operation's path, or `null`
261
+ * for root, index, and filter segments.
262
+ */
263
+ declare function leafProperty(op: IDeltaOperation): string | null;
264
+ /**
265
+ * Returns a copy of the delta with only spec-defined keys in the envelope
266
+ * and each operation. Strips all extension properties.
267
+ */
268
+ declare function deltaSpecDict(delta: IJsonDelta): IJsonDelta;
269
+ /**
270
+ * Returns a record of non-spec keys from the delta envelope.
271
+ * Complement of `deltaSpecDict`.
272
+ */
273
+ declare function deltaExtensions(delta: IJsonDelta): Record<string, any>;
274
+ /**
275
+ * Transforms each operation in the delta using the provided function.
276
+ * Returns a new delta (immutable). Preserves all envelope properties.
277
+ */
278
+ declare function deltaMap(delta: IJsonDelta, fn: (op: IDeltaOperation, index: number) => IDeltaOperation): IJsonDelta;
279
+ /**
280
+ * Returns a new delta with the given extension properties merged onto every
281
+ * operation. Immutable — the original delta is not modified.
282
+ */
283
+ declare function deltaStamp(delta: IJsonDelta, extensions: Record<string, any>): IJsonDelta;
284
+ /**
285
+ * Groups operations in the delta by the result of `keyFn`. Returns a record
286
+ * mapping each key to a sub-delta containing only the matching operations.
287
+ * Each sub-delta preserves all envelope properties.
288
+ */
289
+ declare function deltaGroupBy(delta: IJsonDelta, keyFn: (op: IDeltaOperation) => string): Record<string, IJsonDelta>;
290
+ interface SquashDeltasOptions extends DeltaOptions {
291
+ /** Pre-computed final state. When provided with deltas, used instead of computing. */
292
+ target?: any;
293
+ /** Verify that `target` matches sequential application of deltas. Default: true. */
294
+ verifyTarget?: boolean;
295
+ }
296
+ /**
297
+ * Compacts multiple deltas into a single net-effect delta. The result is
298
+ * equivalent to applying all deltas sequentially, but expressed as a single
299
+ * `source → final` diff.
300
+ *
301
+ * Envelope extensions from all input deltas are merged (last-wins on conflict).
302
+ */
303
+ declare function squashDeltas(source: any, deltas: IJsonDelta[], options?: SquashDeltasOptions): IJsonDelta;
126
304
 
127
- export { type Changeset, CompareOperation, type EmbeddedObjKeysMapType, type EmbeddedObjKeysType, type IAtomicChange, type IChange, type IComparisonEnrichedNode, Operation, type Options, applyChangelist, applyChangeset, atomizeChangeset, compare, createContainer, createValue, diff, enrich, getTypeOfObj, revertChangeset, unatomizeChangeset };
305
+ export { type Changeset, CompareOperation, type DeltaOp, type DeltaOptions, type DeltaPathSegment, type EmbeddedObjKeysMapType, type EmbeddedObjKeysType, type IAtomicChange, type IChange, type IComparisonDict, type IComparisonEnrichedNode, type IDeltaOperation, type IFlatChange, type IJsonDelta, Operation, type Options, type SquashDeltasOptions, applyChangelist, applyChangeset, applyDelta, atomizeChangeset, buildDeltaPath, compare, comparisonToDict, comparisonToFlatList, createContainer, createValue, deltaExtensions, deltaGroupBy, deltaMap, deltaSpecDict, deltaStamp, diff, diffDelta, enrich, formatFilterLiteral, fromDelta, getTypeOfObj, invertDelta, leafProperty, operationExtensions, operationSpecDict, parseDeltaPath, parseFilterLiteral, revertChangeset, revertDelta, squashDeltas, toDelta, unatomizeChangeset, validateDelta };