UNPKG

@sanity/import

Version:

Import documents to a Sanity dataset

94 lines (76 loc) 2.73 kB
import {pathToFileURL} from 'node:url' import {extractWithPath} from '@sanity/mutator' import {serializePath} from './serializePath.js' import {type SanityDocument} from './types.js' import {deepGet, deepSet, deepUnset} from './util/deepGet.js' const assetKey = '_sanityAsset' const assetMatcher = /^(file|image)@([a-z]+:\/\/.*)/ interface AssetRef { documentId: string path: string type: string url: string } // Note: mutates in-place export function unsetAssetRefs(doc: SanityDocument): SanityDocument { for (const path of findAssetRefs(doc)) { const parentPath = path.slice(0, -1) const parent = deepGet(doc, parentPath) as Record<string, unknown> // If the only key in the object is `_sanityAsset`, unset the whole thing, // as we will be using a `setIfMissing({[path]: {}})` patch to enforce it. // Prevents empty objects from appearing while import is running const isOnlyKey = parent && Object.keys(parent).length === 1 && parent[assetKey] const unsetPath = isOnlyKey ? parentPath : path deepUnset(doc, unsetPath) } return doc } // Note: mutates in-place export function absolutifyPaths(doc: SanityDocument, absPath?: string): SanityDocument { if (!absPath) { return doc } const modifier = (value: string): string => value .replace(/file:\/\/\.\//i, `${pathToFileURL(absPath).href}/`) .replace(/(https?):\/\/\.\//, `$1://${absPath}/`) for (const path of findAssetRefs(doc)) { const value = deepGet(doc, path) as string deepSet(doc, path, modifier(value)) } return doc } export function getAssetRefs(doc: SanityDocument): AssetRef[] { return findAssetRefs(doc) .map((path) => validateAssetImportKey(path, doc)) .map((path) => { const value = deepGet(doc, path) as string return { documentId: doc._id, path: serializePath({path: path.filter((segment) => isNotAssetKey(segment))}), type: value.replace(assetMatcher, '$1'), url: value.replace(assetMatcher, '$2'), } }) } function isNotAssetKey(segment: number | string): boolean { return segment !== assetKey } function findAssetRefs(doc: SanityDocument): (number | string)[][] { return extractWithPath(`..[${assetKey}]`, doc).map((match) => match.path) } function validateAssetImportKey( path: (number | string)[], doc: SanityDocument, ): (number | string)[] { if (!assetMatcher.test(deepGet(doc, path) as string)) { throw new Error( [ 'Asset type is not specified.', '`_sanityAsset` values must be prefixed with a type, eg image@url or file@url.', `See document with ID "${doc._id}", path: ${serializePath({path})}`, ].join('\n'), ) } return path }