@sanity/diff
Version:
Generates diffs between documents and primitive types
418 lines (388 loc) • 11.5 kB
TypeScript
/**
* Diff for something that has been added - eg a property in an object,
* an item in an array, a segment of a string or similar.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @typeParam V - Value. The type of the destination (eg `after` or `to`) value.
* @public
*/
export declare interface AddedDiff<A, V> {
action: 'added'
isChanged: true
fromValue: null | undefined
toValue: V
annotation: A
}
/**
* Diff for an array value.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @typeParam V - Item value type.
* @public
*/
export declare type ArrayDiff<A, V = unknown> = FullDiff<A, V[]> & {
type: 'array'
items: ItemDiff<A>[]
}
/**
* Input type for array values. Helper functions are available for getting the item and/or
* annotation at a given index.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare interface ArrayInput<A> extends BaseInput<A> {
type: 'array'
/**
* The actual array value
*/
value: unknown[]
/**
* The length of the array
*/
length: number
/**
* Retrieve the value at the given `index`, automatically wrapping it in an input container.
*
* @param index - The index of the item to retrieve
* @returns Typed input container, or `undefined` if the item does not exist
*/
at(index: number): Input<A>
/**
* Retrieve the _annotation_ for an item at the given index
*
* @param index - The index of the item to fetch the annotation for
* @returns The annotation at the given index, or `undefined` if the item does not exist
*/
annotationAt(index: number): A
}
/**
* Shared properties for all input types
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare interface BaseInput<A> {
annotation: A
}
/**
* Diff of a boolean.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare type BooleanDiff<A> = FullDiff<A, boolean> & {
type: 'boolean'
}
/**
* Input type for booleans.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare interface BooleanInput<A> extends BaseInput<A> {
type: 'boolean'
value: boolean
}
/**
* Diff for something that has changed - eg it was not added or removed, but the
* value has changed "in place". Note that {@link TypeChangeDiff} is used for values that change
* their _type_, thus the `V` type parameter represents both the source and the destination value
* in this type.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @typeParam V - Value. The type of the value.
* @public
*/
export declare interface ChangedDiff<A, V> {
action: 'changed'
isChanged: true
fromValue: V
toValue: V
annotation: A
}
/**
* Diff for any value type.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare type Diff<A> =
| NullDiff<A>
| StringDiff<A>
| NumberDiff<A>
| BooleanDiff<A>
| ObjectDiff<A>
| ArrayDiff<A>
| TypeChangeDiff<A>
/**
* Takes a `from` and `to` input and calulates a diff between the two
*
* @param fromInput - The source (`from`) input - use {@link wrap | the wrap() method} to generate an "input"
* @param toInput - The destination (`to`) input - use {@link wrap | the wrap() method} to generate an "input"
* @param options - Options for the diffing process - currently no options are defined
* @returns A diff object representing the change
* @public
*/
export declare function diffInput<A>(
fromInput: Input<A>,
toInput: Input<A>,
options?: DiffOptions,
): Diff<A>
/**
* Options available for doing diffs. Currently no options are defined.
*
* @public
*/
export declare type DiffOptions = Record<string, never>
/**
* Diff with all the possible diff types.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @typeParam V - Value. Type of the value repesented in the diff.
* @public
*/
export declare type FullDiff<A, V> =
| AddedDiff<A, V>
| RemovedDiff<A, V>
| ChangedDiff<A, V>
| UnchangedDiff<A, V>
/**
* An "input" holds the _type_ of the value, the actual value, an optional annotation,
* along with potential helper methods and properties, which vary dependending on the type
*
* @public
*/
export declare type Input<T> =
| NumberInput<T>
| BooleanInput<T>
| StringInput<T>
| NullInput<T>
| ObjectInput<T>
| ArrayInput<T>
/**
* Diff of an item in an array, representing whether or not it has moved within the array,
* and if so, which index it was moved from/to.
*
* If not moved, `fromIndex` and `toIndex` will have the same value.
* If the item was added, `fromIndex` will be `undefined`.
* If the item was removed, `toIndex` will be `undefined`.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare interface ItemDiff<A> {
fromIndex: number | undefined
toIndex: number | undefined
hasMoved: boolean
diff: Diff<A>
annotation: A
}
/**
* Diff for a `null` value.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare type NullDiff<A> = FullDiff<A, null> & {
type: 'null'
}
/**
* Input type for `null` values.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare interface NullInput<A> extends BaseInput<A> {
type: 'null'
value: null
}
/**
* Diff of a number.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare type NumberDiff<A> = FullDiff<A, number> & {
type: 'number'
}
/**
* Input type for numbers.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare interface NumberInput<A> extends BaseInput<A> {
type: 'number'
value: number
}
/**
* Diff for an object value.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @typeParam T - Value type.
* @public
*/
export declare type ObjectDiff<A, T extends object = Record<string, any>> = FullDiff<A, T> & {
type: 'object'
fields: Record<keyof T, Diff<A>>
}
/**
* Input type for object values. Caches the available keys, and allows retrieval of properties,
* while automatically wrapping the retrieved property in a typed input container.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare interface ObjectInput<A> extends BaseInput<A> {
type: 'object'
/**
* The actual object value
*/
value: Record<string, unknown>
/**
* The keys of the object
*/
keys: string[]
/**
* Retrieve the property with the given `key`, automatically wrapping it in an input container.
*
* @param key - The key of the property you want to retrieve.
* @returns Typed input container, or `undefined` if the property does not exist
*/
get(key: string): Input<A> | undefined
}
/**
* Diff for something that has been removed - eg a property in an object,
* an item in an array, a segment of a string or similar.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @typeParam V - Value. The type of the source (eg `before` or `from`) value.
* @public
*/
export declare interface RemovedDiff<A, V> {
action: 'removed'
isChanged: true
fromValue: V
toValue: null | undefined
annotation: A
}
/**
* Diff of a string. Holds an additional array of string _segments_,
* indicating which portions of the string is changed/unchanged.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare type StringDiff<A> = FullDiff<A, string> & {
type: 'string'
segments: StringDiffSegment<A>[]
}
/**
* Diff of a string segment (eg a portion/slice), and whether or not it was changed or unchanged.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare type StringDiffSegment<A> = StringSegmentChanged<A> | StringSegmentUnchanged
/**
* Input type for strings, which supports slicing parts of the string while maintaining the
* annotation of the parent.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare interface StringInput<A> extends BaseInput<A> {
type: 'string'
value: string
sliceAnnotation(
start: number,
end: number,
): {
text: string
annotation: A
}[]
}
/**
* Diff of a string segment that has changed.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare interface StringSegmentChanged<A> {
type: 'stringSegment'
action: 'added' | 'removed'
text: string
annotation: A
}
/**
* Diff of a string segment that is unchanged.
*
* @public
*/
export declare interface StringSegmentUnchanged {
type: 'stringSegment'
action: 'unchanged'
text: string
}
/**
* Diff for a value that has changed from one type to another.
* For example, an object property going from `null` to `string`.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
export declare interface TypeChangeDiff<A> {
type: 'typeChange'
action: 'changed'
isChanged: true
fromType: string
fromValue: unknown
fromDiff: Diff<A> & {
action: 'removed'
}
toType: string
toValue: unknown
toDiff: Diff<A> & {
action: 'added'
}
annotation: A
}
/**
* Diff (or lack thereof, in this case) for a value that has _not_ changed.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @typeParam V - Value. The type of the destination (eg `after`) value.
* @public
*/
export declare interface UnchangedDiff<A, V> {
action: 'unchanged'
isChanged: false
fromValue: V
toValue: V
}
/**
* The recognized diff value types
*
* @public
*/
export declare type ValueType =
| 'array'
| 'boolean'
| 'null'
| 'number'
| 'object'
| 'string'
| 'undefined'
/**
* Takes an input (any JSON-serializable value) and an annotation, and generates an input
* object for it, to be used with {@link diffInput | the diffInput() method} and others.
*
* @param input - The value to wrap in an input object
* @param annotation - Annotation attached to the input - will be bound to generated diffs
* @returns A input object
* @throws if `input` is not a JSON-serializable type
* @public
*/
export declare function wrap<A>(input: unknown, annotation: A): Input<A>
export {}