Skip to content

Commit

Permalink
fix: handle revalidate on post delete (#94)
Browse files Browse the repository at this point in the history
Co-authored-by: Cody Olsen <81981+stipsan@users.noreply.github.com>
  • Loading branch information
stipsan and stipsan authored Nov 22, 2022
1 parent e43759b commit 419ada2
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 30 deletions.
30 changes: 26 additions & 4 deletions pages/api/revalidate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,13 @@ export default async function revalidate(
return res.status(401).send(message)
}

const { _id, _type } = body
if (typeof _id !== 'string' || !_id) {
if (typeof body._id !== 'string' || !body._id) {
const invalidId = 'Invalid _id'
console.error(invalidId, { body })
return res.status(400).send(invalidId)
}

const staleRoutes = await queryStaleRoutes({ _id, _type })
const staleRoutes = await queryStaleRoutes(body as any)
await Promise.all(staleRoutes.map((route) => res.revalidate(route)))

const updatedRoutes = `Updated routes: ${staleRoutes.join(', ')}`
Expand All @@ -64,10 +63,33 @@ export default async function revalidate(
type StaleRoute = '/' | `/posts/${string}`

async function queryStaleRoutes(
body: Pick<ParseBody['body'], '_type' | '_id'>
body: Pick<ParseBody['body'], '_type' | '_id' | 'date' | 'slug'>
): Promise<StaleRoute[]> {
const client = createClient({ projectId, dataset, apiVersion, useCdn: false })

// Handle possible deletions
if (body._type === 'post') {
const exists = await client.fetch(groq`*[_id == $id][0]`, { id: body._id })
if (!exists) {
let staleRoutes: StaleRoute[] = ['/']
if ((body.slug as any)?.current) {
staleRoutes.push(`/posts/${(body.slug as any).current}`)
}
// Assume that the post document was deleted. Query the datetime used to sort "More stories" to determine if the post was in the list.
const moreStories = await client.fetch(
groq`count(
*[_type == "post"] | order(date desc, _updatedAt desc) [0...3] [dateTime(date) > dateTime($date)]
)`,
{ date: body.date }
)
// If there's less than 3 posts with a newer date, we need to revalidate everything
if (moreStories < 3) {
return [...new Set([...(await queryAllRoutes(client)), ...staleRoutes])]
}
return staleRoutes
}
}

switch (body._type) {
case 'author':
return await queryStaleAuthorRoutes(client, body._id)
Expand Down
10 changes: 5 additions & 5 deletions schemas/author.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { UserIcon } from '@sanity/icons'
import { defineType } from 'sanity'
import { defineField, defineType } from 'sanity'

export default defineType({
name: 'author',
title: 'Author',
icon: UserIcon,
type: 'document',
fields: [
{
defineField({
name: 'name',
title: 'Name',
type: 'string',
validation: (Rule) => Rule.required(),
},
{
}),
defineField({
name: 'picture',
title: 'Picture',
type: 'image',
options: { hotspot: true },
validation: (Rule) => Rule.required(),
},
}),
],
})
44 changes: 26 additions & 18 deletions schemas/post.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BookIcon } from '@sanity/icons'
import { defineType } from 'sanity'
import { format, parseISO } from 'date-fns'
import { defineField, defineType } from 'sanity'

import authorType from './author'

Expand All @@ -21,62 +22,69 @@ export default defineType({
icon: BookIcon,
type: 'document',
fields: [
{
defineField({
name: 'title',
title: 'Title',
type: 'string',
validation: (Rule) => Rule.required(),
},
{
}),
defineField({
name: 'slug',
title: 'Slug',
type: 'slug',
options: {
source: 'title',
maxLength: 96,
isUnique: (value, context) => context.defaultIsUnique(value, context),
},
validation: (Rule) => Rule.required(),
},
{
}),
defineField({
name: 'content',
title: 'Content',
type: 'array',
of: [{ type: 'block' }],
},
{
}),
defineField({
name: 'excerpt',
title: 'Excerpt',
type: 'text',
},
{
}),
defineField({
name: 'coverImage',
title: 'Cover Image',
type: 'image',
options: {
hotspot: true,
},
},
{
}),
defineField({
name: 'date',
title: 'Date',
type: 'datetime',
},
{
initialValue: () => new Date().toISOString(),
}),
defineField({
name: 'author',
title: 'Author',
type: 'reference',
to: [{ type: authorType.name }],
},
}),
],
preview: {
select: {
title: 'title',
author: 'author.name',
date: 'date',
media: 'coverImage',
},
prepare(selection) {
const { author } = selection
return { ...selection, subtitle: author && `by ${author}` }
prepare({ title, media, author, date }) {
const subtitles = [
author && `by ${author}`,
date && `on ${format(parseISO(date), 'LLL d, yyyy')}`,
].filter(Boolean)

return { title, media, subtitle: subtitles.join(' ') }
},
},
})
6 changes: 3 additions & 3 deletions schemas/settings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CogIcon } from '@sanity/icons'
import { defineType } from 'sanity'
import { defineField, defineType } from 'sanity'

export default defineType({
name: 'settings',
Expand All @@ -9,13 +9,13 @@ export default defineType({
// Uncomment below to have edits publish automatically as you type
// liveEdit: true,
fields: [
{
defineField({
name: 'title',
description: 'This field is the title of your blog.',
title: 'Title',
type: 'string',
initialValue: 'Blog.',
validation: (rule) => rule.required(),
},
}),
],
})

1 comment on commit 419ada2

@vercel
Copy link

@vercel vercel bot commented on 419ada2 Nov 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.