Skip to content

Instantly share code, notes, and snippets.

@juice49
Last active July 21, 2023 09:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juice49/d40223d9a450a9f07215cc91a570441c to your computer and use it in GitHub Desktop.
Save juice49/d40223d9a450a9f07215cc91a570441c to your computer and use it in GitHub Desktop.
Upload Sanity images with tags
import { type SanityDocument, type Reference } from 'sanity'
import { type UploadBody, type SanityImageAssetDocument } from '@sanity/client'
import { getCliClient } from 'sanity/cli'
const client = getCliClient()
interface Tag extends SanityDocument {
_type: 'media.tag'
name: {
_type: 'slug'
current: string
}
}
interface Options {
source: UploadBody
filename: string
tagNames?: string[]
}
async function uploadImage({
source,
filename,
tagNames = [],
}: Options): Promise<SanityImageAssetDocument> {
const [tagIds, asset] = await Promise.all([
getTagIdsByName(tagNames),
client.assets.upload('image', source, {
filename,
}),
])
return client
.patch(asset._id)
.set({
'opt.media.tags': getTagReferences(tagIds),
})
.commit()
}
async function getTagIdsByName(names: string[]): Promise<string[]> {
const existingTags = await client.fetch<Tag[]>(
'*[_type == "media.tag" && name.current in $names]',
{
names,
},
)
const newTagIds = await createNonExistentTags(names, existingTags)
return existingTags.reduce((tagIds, { _id }) => {
return [...tagIds, _id]
}, newTagIds)
}
async function createNonExistentTags(
names: string[],
existingTags: Tag[],
): Promise<string[]> {
const existingTagNames = existingTags.map(({ name }) => name.current)
const nonExistentNames = names.filter(
name => !existingTagNames.includes(name),
)
const operations = nonExistentNames.reduce((transaction, nonExistentName) => {
return transaction.create({
_type: 'media.tag',
name: {
current: nonExistentName,
},
})
}, client.transaction())
const response = await operations.commit()
return response.documentIds
}
function getTagReferences(tagIds: string[]): Reference[] {
return tagIds.map(tagId => ({
_type: 'reference',
_ref: tagId,
_weak: true,
}))
}
import { createReadStream } from 'node:fs'
import path from 'node:path'
;(async () => {
await uploadImage({
source: createReadStream(path.join(__dirname, 'capybara-squad.jpg')),
filename: 'capybara-squad.jpg',
// If the tags don't yet exist, they'll be created. The tag references will then be
// set on the uploaded image asset document.
tagNames: ['capybara', 'friendship'],
})
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment