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

131 lines (95 loc) 3.06 kB
/* eslint-disable no-loop-func */ import {type Path, type SanityDocument, type SchemaType} from '@sanity/types' import {isArray, isRecord} from 'sanity' export function getPathTitles(options: { path: Path schemaType: SchemaType value: Partial<SanityDocument> | null }): Array<{name: string; title?: string}> { const {path, schemaType, value} = options const result: Array<{name: string; title?: string}> = [] let s = schemaType let v: unknown = value for (const segment of path) { // field name if (typeof segment === 'string') { if (!isRecord(v) && v !== undefined) { throw new Error(`Parent value is not an object, cannot get path segment: .${segment}`) } if (s.jsonType !== 'object') { throw new Error( `Parent type is not an object schema type, cannot get path segment: .${segment}`, ) } v = v?.[segment] const field = s.fields.find((f) => f.name === segment) if (!field) { result.push({name: segment}) return result } s = field.type result.push(s) continue } // array item index if (typeof segment === 'number') { if (!isArray(v) && v !== undefined) { throw new Error(`Parent value is not an array, cannot get path segment: [${segment}]`) } if (s.jsonType !== 'array') { throw new Error( `Parent type is not an array schema type, cannot get path segment: [${segment}]`, ) } v = v?.[segment] const itemType = s.of.find((ofType) => { if (typeof v === 'string') { return ofType.jsonType === 'string' } if (typeof v === 'number') { return ofType.jsonType === 'number' } if (typeof v === 'boolean') { return ofType.jsonType === 'boolean' } if (isRecord(v)) { return ofType.name === v?._type } return false }) if (!itemType) { throw new Error(`Item type not found: [${segment}]`) } s = itemType result.push(s) continue } // array item key if (isRecord(segment) && segment._key) { if (!isArray(v)) { throw new Error( `Parent value is not an array, cannot get path segment: [_key == ${segment}]`, ) } if (s.jsonType !== 'array') { throw new Error( `Parent type is not an array schema type, cannot get path segment: .${segment}`, ) } const values = v ?? [] v = values.find((i) => isRecord(i) && i._key === segment._key) if (!isRecord(v)) { throw new Error(`Array item not found: [_key == ${segment._key}]`) } const ofType = s.of.find((i) => isRecord(v) && i.name === v?._type) if (!ofType) { throw new Error(`Array item type not found: .${v?._type}`) } s = ofType result.push(s) continue } throw new Error(`Invalid path segment: ${JSON.stringify(segment)}`) } return result }