@sanity/diff
Version:
Generates diffs between documents and primitive types
358 lines • 11.6 kB
TypeScript
/**
* Options available for doing diffs. Currently no options are defined.
*
* @public
*/
type DiffOptions = Record<string, never>;
/**
* The recognized diff value types
*
* @public
*/
type ValueType = 'array' | 'boolean' | 'null' | 'number' | 'object' | 'string' | 'undefined';
/**
* 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
*/
type Input<T> = NumberInput<T> | BooleanInput<T> | StringInput<T> | NullInput<T> | ObjectInput<T> | ArrayInput<T>;
/**
* Shared properties for all input types
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
interface BaseInput<A> {
annotation: A;
}
/**
* 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
*/
interface StringInput<A> extends BaseInput<A> {
type: 'string';
value: string;
sliceAnnotation(start: number, end: number): {
text: string;
annotation: A;
}[];
}
/**
* Input type for numbers.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
interface NumberInput<A> extends BaseInput<A> {
type: 'number';
value: number;
}
/**
* Input type for booleans.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
interface BooleanInput<A> extends BaseInput<A> {
type: 'boolean';
value: boolean;
}
/**
* Input type for `null` values.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
interface NullInput<A> extends BaseInput<A> {
type: 'null';
value: null;
}
/**
* 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
*/
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;
}
/**
* 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
*/
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;
}
/**
* 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
*/
interface AddedDiff<A, V> {
action: 'added';
isChanged: true;
fromValue: null | undefined;
toValue: V;
annotation: A;
}
/**
* 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
*/
interface RemovedDiff<A, V> {
action: 'removed';
isChanged: true;
fromValue: V;
toValue: null | undefined;
annotation: A;
}
/**
* 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
*/
interface ChangedDiff<A, V> {
action: 'changed';
isChanged: true;
fromValue: V;
toValue: V;
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
*/
interface UnchangedDiff<A, V> {
action: 'unchanged';
isChanged: false;
fromValue: V;
toValue: V;
}
/**
* 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
*/
type FullDiff<A, V> = AddedDiff<A, V> | RemovedDiff<A, V> | ChangedDiff<A, V> | UnchangedDiff<A, V>;
/**
* 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
*/
type StringDiff<A> = FullDiff<A, string> & {
type: 'string';
segments: StringDiffSegment<A>[];
};
/**
* Diff of a number.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
type NumberDiff<A> = FullDiff<A, number> & {
type: 'number';
};
/**
* Diff of a boolean.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
type BooleanDiff<A> = FullDiff<A, boolean> & {
type: 'boolean';
};
/**
* 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
*/
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 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
*/
type ObjectDiff<A, T extends object = Record<string, any>> = FullDiff<A, T> & {
type: 'object';
fields: Record<keyof T, Diff<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
*/
type ArrayDiff<A, V = unknown> = FullDiff<A, V[]> & {
type: 'array';
items: ItemDiff<A>[];
};
/**
* Diff for a `null` value.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
type NullDiff<A> = FullDiff<A, null> & {
type: 'null';
};
/**
* Diff for any value type.
*
* @typeParam A - Annotation. Timestamps, author and similar info is attached by Sanity, but anything is allowed.
* @public
*/
type Diff<A> = NullDiff<A> | StringDiff<A> | NumberDiff<A> | BooleanDiff<A> | ObjectDiff<A> | ArrayDiff<A> | TypeChangeDiff<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
*/
type StringDiffSegment<A> = StringSegmentChanged<A> | StringSegmentUnchanged;
/**
* 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
*/
interface StringSegmentChanged<A> {
type: 'stringSegment';
action: 'added' | 'removed';
text: string;
annotation: A;
}
/**
* Diff of a string segment that is unchanged.
*
* @public
*/
interface StringSegmentUnchanged {
type: 'stringSegment';
action: 'unchanged';
text: string;
}
/**
* 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
*/
interface ItemDiff<A> {
fromIndex: number | undefined;
toIndex: number | undefined;
hasMoved: boolean;
diff: Diff<A>;
annotation: 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
*/
declare function diffInput<A>(fromInput: Input<A>, toInput: Input<A>, options?: DiffOptions): Diff<A>;
/**
* 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
*/
declare function wrap<A>(input: unknown, annotation: A): Input<A>;
export { type AddedDiff, type ArrayDiff, type ArrayInput, type BaseInput, type BooleanDiff, type BooleanInput, type ChangedDiff, type Diff, type DiffOptions, type FullDiff, type Input, type ItemDiff, type NullDiff, type NullInput, type NumberDiff, type NumberInput, type ObjectDiff, type ObjectInput, type RemovedDiff, type StringDiff, type StringDiffSegment, type StringInput, type StringSegmentChanged, type StringSegmentUnchanged, type TypeChangeDiff, type UnchangedDiff, type ValueType, diffInput, wrap };
//# sourceMappingURL=index.d.ts.map