UNPKG

sanity-plugin-media

Version:

This version of `sanity-plugin-media` is for Sanity Studio V3.

87 lines (76 loc) 2.52 kB
import type {SanityClient} from '@sanity/client' import groq from 'groq' import {nanoid} from 'nanoid' import {TAG_DOCUMENT_NAME} from '../constants' import type {Tag} from '../types' type ApplyMediaTagsOptions = { client: SanityClient assetId: string mediaTags: string[] createTagsOnUpload?: boolean } // Serialize calls per asset so concurrent fields reading the same asset // don't race each other — the second call always runs after the first commits. const pendingByAsset = new Map<string, Promise<void>>() export function applyMediaTags(options: ApplyMediaTagsOptions): Promise<void> { const {assetId} = options const chain = (pendingByAsset.get(assetId) ?? Promise.resolve()).then(() => doApplyMediaTags(options) ) const cleanup = chain .catch(() => {}) .finally(() => { if (pendingByAsset.get(assetId) === cleanup) pendingByAsset.delete(assetId) }) pendingByAsset.set(assetId, cleanup) return chain } async function doApplyMediaTags({ client, assetId, mediaTags, createTagsOnUpload = true }: ApplyMediaTagsOptions): Promise<void> { if (!mediaTags || mediaTags.length === 0) return const resolvedTags = await Promise.all( mediaTags.map(async tagName => { const existingTag = await client.fetch<Tag | null>( groq`*[_type == "${TAG_DOCUMENT_NAME}" && name.current == $tagName][0]`, {tagName} ) if (existingTag) return existingTag if (createTagsOnUpload) { const newTag = await client.create({ _type: TAG_DOCUMENT_NAME, name: {_type: 'slug', current: tagName} }) return newTag as Tag } return null }) ) const validTags = resolvedTags.filter((tag): tag is Tag => tag !== null) if (validTags.length === 0) return const existing = await client.fetch<{tagIds: string[]} | null>( groq`*[_id == $assetId][0]{'tagIds': opt.media.tags[]._ref}`, {assetId}, {useCdn: false} // bypass CDN cache so we see the latest committed tag refs ) const existingIds = new Set(existing?.tagIds ?? []) const tagReferences = validTags .filter(tag => !existingIds.has(tag._id)) .map(tag => ({ _key: nanoid(), _ref: tag._id, _type: 'reference' as const, _weak: true })) if (tagReferences.length === 0) return await client .patch(assetId) .setIfMissing({opt: {}}) .setIfMissing({'opt.media': {}}) .setIfMissing({'opt.media.tags': []}) .append('opt.media.tags', tagReferences) .commit() }