UNPKG

sanity

Version:

Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches

88 lines (76 loc) 2.68 kB
import {findIndex} from 'lodash' import {type FIXME} from '../../FIXME' import {applyPatch} from './applyPatch' import {arrayInsert} from './arrayInsert' const hasOwn = (obj: Record<string, unknown>, property: string) => Object.prototype.hasOwnProperty.call(obj, property) function move(arr: unknown[], from: number, to: number) { const nextValue = arr.slice() const val = nextValue[from] nextValue.splice(from, 1) nextValue.splice(to, 0, val) return nextValue } function findTargetIndex(array: unknown[], pathSegment: FIXME) { if (typeof pathSegment === 'number') { return pathSegment } const index = findIndex(array, pathSegment) return index === -1 ? false : index } export function _arrayApply(value: FIXME, patch: FIXME) { const nextValue = value.slice() // make a copy for internal mutation if (patch.path.length === 0) { // its directed to me if (patch.type === 'setIfMissing') { if (!Array.isArray(patch.value)) { // eslint-disable-line max-depth throw new Error('Cannot set value of an array to a non-array') } return value === undefined ? patch.value : value } else if (patch.type === 'set') { if (!Array.isArray(patch.value)) { // eslint-disable-line max-depth throw new Error('Cannot set value of an array to a non-array') } return patch.value } else if (patch.type === 'unset') { return undefined } else if (patch.type === 'move') { if (!patch.value || !hasOwn(patch.value, 'from') || !hasOwn(patch.value, 'to')) { // eslint-disable-line max-depth throw new Error( `Invalid value of 'move' patch. Expected a value with "from" and "to" indexes, instead got: ${JSON.stringify( patch.value, )}`, ) } return move(nextValue, patch.value.from, patch.value.to) } throw new Error(`Invalid array operation: ${patch.type}`) } const [head, ...tail] = patch.path const index = findTargetIndex(value, head) // If the given selector could not be found, return as-is if (index === false) { return nextValue } if (tail.length === 0) { if (patch.type === 'insert') { const {position, items} = patch return arrayInsert(value, position, index, items) } else if (patch.type === 'unset') { if (typeof index !== 'number') { throw new Error(`Expected array index to be a number, instead got "${index}"`) } nextValue.splice(index, 1) return nextValue } } // The patch is not directed to me nextValue[index] = applyPatch(nextValue[index], { ...patch, path: tail, }) return nextValue }