UNPKG

@sanity/mutator

Version:

A set of models to make it easier to utilize the powerful real time collaborative features of Sanity

82 lines (72 loc) 2.27 kB
import {max, min} from 'lodash' import {type Expression} from '../jsonpath' import {type ImmutableAccessor} from './ImmutableAccessor' import {targetsToIndicies} from './util' export class InsertPatch { location: string path: string items: unknown[] id: string constructor(id: string, location: string, path: string, items: unknown[]) { this.id = id this.location = location this.path = path this.items = items } apply(targets: Expression[], accessor: ImmutableAccessor): ImmutableAccessor { let result = accessor if (accessor.containerType() !== 'array') { throw new Error('Attempt to apply insert patch to non-array value') } switch (this.location) { case 'before': { const pos = minIndex(targets, accessor) result = result.insertItemsAt(pos, this.items) break } case 'after': { const pos = maxIndex(targets, accessor) result = result.insertItemsAt(pos + 1, this.items) break } case 'replace': { // TODO: Properly implement ranges in compliance with content lake // This will only properly support single contiguous ranges const indicies = targetsToIndicies(targets, accessor) result = result.unsetIndices(indicies) result = result.insertItemsAt(indicies[0], this.items) break } default: { throw new Error(`Unsupported location atm: ${this.location}`) } } return result } } function minIndex(targets: Expression[], accessor: ImmutableAccessor): number { let result = min(targetsToIndicies(targets, accessor)) || 0 // Ranges may be zero-length and not turn up in indices targets.forEach((target) => { if (target.isRange()) { const {start} = target.expandRange() if (start < result) { result = start } } }) return result } function maxIndex(targets: Expression[], accessor: ImmutableAccessor): number { let result = max(targetsToIndicies(targets, accessor)) || 0 // Ranges may be zero-length and not turn up in indices targets.forEach((target) => { if (target.isRange()) { const {end} = target.expandRange() if (end > result) { result = end } } }) return result }