UNPKG

@sanity/diff

Version:

Generates diffs between documents and primitive types

114 lines (98 loc) 2.78 kB
import {replaceProperty} from '../helpers' import {type DiffOptions, type ObjectDiff, type ObjectInput} from '../types' import {addedInput, diffInput, removedInput} from './diffInput' const ignoredFields = new Set(['_id', '_type', '_createdAt', '_updatedAt', '_rev', '_weak']) export function diffObject<A>( fromInput: ObjectInput<A>, toInput: ObjectInput<A>, options: DiffOptions, ): ObjectDiff<A> { const fields: ObjectDiff<A>['fields'] = {} let isChanged = false for (const key of fromInput.keys) { if (ignoredFields.has(key)) continue const fromField = fromInput.get(key)! const toField = toInput.get(key) if (toField) { const fieldDiff = diffInput(fromField, toField, options) fields[key] = fieldDiff if (fieldDiff.isChanged) isChanged = true } else { fields[key] = removedInput(fromField, undefined, options) isChanged = true } } for (const key of toInput.keys) { if (ignoredFields.has(key)) continue // Already handled above if (fromInput.get(key)) continue const toField = toInput.get(key)! fields[key] = addedInput(toField, undefined, options) isChanged = true } const fromValue = fromInput.value const toValue = toInput.value if (!isChanged) { return { type: 'object', action: 'unchanged', isChanged: false, fromValue, toValue, fields, } } return { type: 'object', action: 'changed', isChanged: true, fromValue, toValue, fields, annotation: toInput.annotation, } } export function removedObject<A>( input: ObjectInput<A>, toValue: null | undefined, options: DiffOptions, ): ObjectDiff<A> & {action: 'removed'} { return { type: 'object', action: 'removed', isChanged: true, fromValue: input.value, toValue, annotation: input.annotation, get fields(): ObjectDiff<A>['fields'] { const fields: ObjectDiff<A>['fields'] = {} for (const key of input.keys) { const value = input.get(key)! fields[key] = removedInput(value, undefined, options) } return replaceProperty(this, 'fields', fields) }, } } export function addedObject<A>( input: ObjectInput<A>, fromValue: null | undefined, options: DiffOptions, ): ObjectDiff<A> & {action: 'added'} { return { type: 'object', action: 'added', isChanged: true, fromValue, toValue: input.value, annotation: input.annotation, get fields(): ObjectDiff<A>['fields'] { const fields: ObjectDiff<A>['fields'] = {} for (const key of input.keys) { const value = input.get(key)! fields[key] = addedInput(value, undefined, options) } return replaceProperty(this, 'fields', fields) }, } }