Skip to content

Commit

Permalink
fix: migrate from next-sanity/webhook to @sanity/webhook
Browse files Browse the repository at this point in the history
  • Loading branch information
stipsan committed Apr 8, 2024
1 parent 17e574d commit 3eed62b
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 4 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -19,6 +19,7 @@
"@sanity/preview-url-secret": "1.6.7",
"@sanity/vision": "3.36.4",
"@sanity/visual-editing": "1.8.7",
"@sanity/webhook": "4.0.2-bc",
"@vercel/og": "0.6.2",
"classnames": "2.5.1",
"date-fns": "3.6.0",
Expand Down
61 changes: 57 additions & 4 deletions pages/api/revalidate.ts
Expand Up @@ -22,17 +22,27 @@
* 16. Redeploy with `npx vercel --prod` to apply the new environment variable
*/

import { isValidSignature, SIGNATURE_HEADER_NAME } from '@sanity/webhook'
import { apiVersion, dataset, projectId } from 'lib/sanity.api'
import type { NextApiRequest, NextApiResponse } from 'next'
import type { PageConfig } from 'next/types'
import {
createClient,
groq,
type SanityClient,
type SanityDocument,
} from 'next-sanity'
import { parseBody, type ParsedBody } from 'next-sanity/webhook'

export { config } from 'next-sanity/webhook'
import type { ParsedBody } from 'next-sanity/webhook'

export const config = {
api: {
/**
* Next.js will by default parse the body, which can lead to invalid signatures.
*/
bodyParser: false,
},
runtime: 'nodejs',
} satisfies PageConfig

export default async function revalidate(
req: NextApiRequest,
Expand Down Expand Up @@ -67,6 +77,49 @@ export default async function revalidate(
}
}

async function parseBody<Body = SanityDocument>(
req: NextApiRequest,
secret?: string,
waitForContentLakeEventualConsistency: boolean = true,
): Promise<ParsedBody<Body>> {
let signature = req.headers[SIGNATURE_HEADER_NAME]
if (Array.isArray(signature)) {
signature = signature[0]
}
if (!signature) {
console.error('Missing signature header')
return { body: null, isValidSignature: null }
}

if (req.readableEnded) {
throw new Error(
`Request already ended and the POST body can't be read. Have you setup \`export {config} from 'next-sanity/webhook' in your webhook API handler?\``,
)
}

const body = await readBody(req)
const validSignature = secret
? await isValidSignature(body, signature, secret.trim())
: null

if (validSignature !== false && waitForContentLakeEventualConsistency) {
await new Promise((resolve) => setTimeout(resolve, 1000))
}

return {
body: body.trim() ? JSON.parse(body) : null,
isValidSignature: validSignature,
}
}

async function readBody(readable: NextApiRequest): Promise<string> {
const chunks = []
for await (const chunk of readable) {
chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk)
}
return Buffer.concat(chunks).toString('utf8')
}

type StaleRoute = '/' | `/posts/${string}`

async function queryStaleRoutes(
Expand All @@ -81,7 +134,7 @@ async function queryStaleRoutes(
if (body._type === 'post') {
const exists = await client.fetch(groq`*[_id == $id][0]`, { id: body._id })
if (!exists) {
let staleRoutes: StaleRoute[] = ['/']
const staleRoutes: StaleRoute[] = ['/']
if ((body.slug as any)?.current) {
staleRoutes.push(`/posts/${(body.slug as any).current}`)
}
Expand Down

0 comments on commit 3eed62b

Please sign in to comment.