Problem encountered while revalidating Next.js and Sanity documents through a webhook

I'm currently developing a Next.js 13 project that utilizes Sanity as its CMS and is deployed on Vercel. To ensure that components and pages are revalidated whenever a new testimonial is added, updated, or removed in Sanity, I have configured a webhook. However, I am facing a TypeError stating "resolver is not a function," and I am uncertain how to resolve this issue.

Below is the code snippet for the webhook:

import { SIGNATURE_HEADER_NAME, isValidSignature } from "@sanity/webhook";

const handler = async (req: any, res: any) => {
    try {
        const signature = req.headers[SIGNATURE_HEADER_NAME].toString();
        if (
            !isValidSignature(
                JSON.stringify(req.body),
                signature,
                process.env.NEXT_PUBLIC_SECRET_TOKEN as string
            )
        ) {
            return res.status(401).json({ message: "Invalid request" });
        }
        await res.revalidate("/");
        res.status(200).json({ revalidated: true });
        console.log("testimonial revalidated");
        
    } catch (error) {
        res.status(500).json({ revalidated: false, error });
    }
};

The error message I am encountering reads:

TypeError: resolver is not a function
    at /var/task/node_modules/next/dist/server/api-utils/node.js:463:16
    // ...

I suspect that the error could be related to the usage of the res.revalidate function or potentially an issue with my imports. Can someone offer guidance on correctly configuring the webhook to trigger revalidation upon updates from Sanity?

Additional Details:

  • I am using Next.js version 13 with the new app directory structure.
  • The @sanity/webhook package is being employed for managing the webhook functionality.
  • The webhook must initiate revalidation of components and pages when changes occur in Sanity documents.
  • The revalidation should specifically occur without necessitating a complete project rebuild, only when there are updates in Sanity.

Update:

Progress has been made regarding the initial issue of "resolver is not a function," which was attributed to a missing export for the function. Nevertheless, a new challenge has emerged. Upon sending a request to the API, consistently receiving a "401 Unauthorized" response along with the following message:

{
  "message": "Invalid request"
}

Despite trying different approaches such as defining the signature and secret token within the code directly, the same outcome persists. It appears that the webhook is struggling to properly authenticate the requests.

Answer №1

It appears that the signature validation is being tampered with. Ensure that you correctly input the validation secret in both your Sanity webhook and environment variables.

I can provide my code as an example of how I approached this, utilizing the app router:

import { revalidateTag } from "next/cache";
import { type NextRequest, NextResponse } from "next/server";
import { parseBody } from "next-sanity/webhook";

export async function POST(req: NextRequest) {
  try {
    const { isValidSignature, body } = await parseBody<{ _type: string }>(
      req,
      process.env.SANITY_REVALIDATE_SECRET
    );
    
    if (!isValidSignature) {
      const message = "Invalid signature";
      return new Response(JSON.stringify({ message, isValidSignature, body }), {
        status: 401,
      });
    }
    
    if (!body?._type) {
      revalidateTag("page");
    } else {
      revalidateTag(body?._type);
    }
    
    return NextResponse.json({ body });

  } catch (err) {
    console.error(err);
    return new Response(JSON.stringify(err), { status: 500 });
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having trouble getting Vue.js to cooperate with a brand new Laravel 5.8 setup?

I set up a fresh Laravel project using laravel new sample. Then I executed npm install followed by npm run dev. Next, I modified the welcome.blade.php file as shown below: <!DOCTYPE html> <html> <head> <script type="text/j ...

The method $event.stopPropogation doesn't seem to be functioning properly

I am facing an issue where the functionality of a div is affected when clicking on an input box inside it. When the div is selected and colored red, clicking on the input box within the selected div causes the div to become unselected (grey in color). I ...

What steps can be taken to ensure that all object properties become reactive?

Let's dive into this simplified scenario: interface Pup { name: string; age: number; } const puppy: Pup = { name: 'Rex', age: 3, }; The goal here is to establish a reactive link for each attribute within the puppy object. The usua ...

Increasing space at the top with heading

As I scroll down, the header on my website remains in a static position and disappears. However, when I scroll back up, the header reappears wherever the user is on the page. While this functionality works well, I have noticed that as I scroll all the way ...

Encapsulate the HTTP request within a common function for reus

My rest-provider service handles all of my http calls, but I've noticed that each function is repeating a lot of the same http code. It seems like I should create a shared function to avoid this repetition and make it easier to update in the future. ...

Events in d3.js are properly registered, however they are not being triggered as

After creating an enter section that transitions to set the opacity to 1, I encountered an issue where the 'click' event on the circle worked but not on the text. Interestingly, when I replaced the 'text' with a 'rect' and se ...

I'm encountering an issue while trying to retrieve NFTs from a contract on the marketplace

Unhandled Issue at Runtime Error Type: TypeError - contract?.getAddress is not a function Stack Trace: useActiveListings Error occurred in webpack-internal:///./node_modules/@thirdweb-dev/react-core/dist/useTransactions-07d3933d.browser.esm.js (3764:37) ...

Adjust camera to align with the loaded object in Three.js

I've been struggling to center the camera around the model loaded through the stl loader. I've tried adjusting variables and setting different positions for the mesh and camera, but the camera still isn't centered on the design! Here's ...

Avoid nesting ternary expressions when possible - consider alternative solutions

I am currently working on a React component that has 4 different states: advisoryResults, results, noResults, and newAccount. While I initially thought about using a ternary expression for this, it turns out that it is not allowed in this case. Can you su ...

Prevent image upload until text is clicked on

When the user clicks on the mask image, a file upload dialog box is displayed. Once the user uploads an image, the text "Remove Image" is shown. Issue: Currently, users can upload another image before clicking on "Remove image". However, after clicking o ...

Everything in my middleware is functioning correctly, however, it is failing to redirect to the designated route

In my code, everything seems to be working fine without any errors, but I'm encountering an issue with the response not redirecting to the expected route. I need some help resolving this issue. I've double-checked for any coding errors or except ...

Using null or undefined for ternary operator formatting in React applications

When styling a component, what should be used if a specific condition is not fulfilled: null, undefined, or something else? For example: errorStyle: { right: locale === Locales.ARABIC ? 0 : null, left: locale !== Locales.ARABIC ? 0 : null, .. ...

Is it possible to swap images by clicking on them?

Let's say I'm working with 3 images. Image A, B and C. A is the main image initially. If I click on image B, it will become the main image and image A will take its place in the old position. The same condition applies when B is the main image a ...

Implementing the withAuthenitcationProps method in all page.tsx files to integrate Amazon Cognito authentication

I have been working on my Next.js app and wanted to share the project structure with you: ├── README.md ├── amplify │ ├── #current-cloud-backend │ ├── README.md │ ├── auth │ ├── backend │ ├── cl ...

Differences: Angular ngController vs Controller embedded in Directive

I'm interested in exploring the various scenarios where these two methods of creating a controller can be used: Using ngController: myApp.controller('myController', ['$scope', function ( $scope ) { }]); Creating the controller ...

Filtering a table with a customized set of strings and their specific order using pure JavaScript

Recently, I've been diving into APIs and managed to create a table using pure vanilla javascript along with a long list of sorting commands that can filter the table based on strings. My goal is to establish an object containing strings in a specific ...

Complete a checkbox entry form and showcase it within a "division" on the current page

Hello everyone, I need some help. I have a form that I want to send to a specific div on the same page. This is what I am aiming for. I have a floating div named "basket" in the top right corner of my page where I want the form data to be displayed after s ...

Having trouble sending a picture to AWS S3 from a NextJS app when running on the server

I've encountered an issue with my NextJS application. Uploading files from localhost works perfectly fine, but the problem arises when attempting to upload remotely. I have hosted my app on Github Pages and whenever I try to upload files remotely, I a ...

Transferring a JavaScript element's ID to PHP

Recently, I came across a JavaScript function that automatically updates the date and time for me. I found the script on this URL: http://jsfiddle.net/pLsgJ/1/ setInterval(function() { var currentTime = new Date ( ); var currentHours = curren ...

Issue with authentication when accessing Google Video API

I'm attempting to utilize the Google API provided: I have downloaded the Sample Project and followed these steps: 1) Navigate to the Project Folder named API Video 2) Run npm install 3) Set GCLOUD_PROJECT = neorisvideo 4) Download Json from the C ...