Next.js Conf 2024: Your app should be Live by Default – Watch Keynote

Adding type to unique slug validation in Sanity.io

4 replies
Last updated: Mar 29, 2024
I'm trying to implement a unique slug validation, but I only need them unique among the same doc type (name, document._type value). The example function for this is across all documents. Does anyone have an idea how to add the type to this? (details in) 🧵
Mar 27, 2024, 11:10 PM
This is the example I have been using, taken right from the docs here
// /lib/isUniqueAcrossAllDocuments.js

// Note: this assumes that every document that has a slug field
// have it on the `slug` field at the root
export async function isUniqueAcrossAllDocuments(slug, context) {
  const {document, getClient} = context
  const client = getClient({apiVersion: '2022-12-07'})
  const id = document._id.replace(/^drafts\./, '')
  const params = {
    draft: `drafts.${id}`,
    published: id,
    slug,
  }
  const query = `!defined(*[!(_id in [$draft, $published]) && slug.current == $slug][0]._id)`
  const result = await client.fetch(query, params)
  return result
}
But the update I am trying to make I cannot get dialed in. Basically I need to only enforce this if both documents are the same type. So if it s a 'presentation' and a 'video' (name values) and the url is the same that does not matter to me, only if both are 'video' (or whatever the template name is)
Mar 27, 2024, 11:12 PM
The behaviour you’re explaining (uniqueness across document types) should be the default. Getting rid of this function should get you what you’re after.
Mar 27, 2024, 11:52 PM
Hi there! I'm using this validation code below, but I have a difference in the return statement compared to yours. While you exclude draft documents and return an empty array, mine return a boolean value (
true
or
false
). Here's my code for your reference:

defineField({
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: {
        source: 'title',
        maxLength: 96,
        isUnique: async (slug, context) => {
         // Search for all documents with the same slug
          const query = `*[_type == "post" && slug.current == $slug]`;
          
          const documents = await context.getClient({ apiVersion }).fetch<Post[]>(query, {
            slug,
          });
          // Returns true if no documents are found, false otherwise
          return documents.length <= 1;
        },
      },
    }),
Mar 28, 2024, 11:58 AM
user A
Did not even realize that, thanks for pointing that out, worked exactly how I was expecting it too, thanks!
Mar 29, 2024, 10:10 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?