-1

email.js serverless function generated by chatgpt in my root/api/email.js directory:

//[root]/api/email.js
//just a test function generated by chatgpt
import sendEmail from "../utils/email";

export const config = {
  runtime: "edge",
};

export default async function handler(req) {
  try {
    const { email, subject, html } = await req.json();
    const response = await sendEmail(email, subject, html);

    if (response.error) {
      return new Response(JSON.stringify(response.error), { status: 500 });
    }

    return new Response(JSON.stringify(response.data), { status: 200 });
  } catch (error) {
    console.error(error);
    return new Response("Internal Server Error", { status: 500 });
  }
}

vercel.json in my root directory:

//[root]/vercel.json
{
  "version": 2,
  "functions": {
    "api/email.js": {
      "maxDuration": 60
    }
  }
}

Context: I have a remix.run app where my resend/nodemailer email function is timing out before the email can be sent. I read online somewhere that you can use vercel serverless functions to resolve this issue by configuring the function/file to time out after 60s instead of the default 10s.

Question: Why am I getting the error: "Error: The pattern api/email.js defined in functions doesn't match any Serverless Functions inside the api directory" when I run vercel dev

I tried:

  1. Changing api/email.js to email.js in the vercel.json
  2. Putting the api directory in the app directory

I'm assuming the solution would be to somehow direct vercel to the right api folder using the vercel.json config file?

File structure

1 Answer 1

0

I found that you can just add a config variable to the remix route with a maxDuration property:

Remove the vercel.json file:

//[root]/vercel.json
{
  "version": 2,
  "functions": {
    "api/email.js": {
      "maxDuration": 60
    }
  }
}

Remove the api folder and email.js serverless function:

//[root]/api/email.js
//just a test function generated by chatgpt
import sendEmail from "../utils/email";

export const config = {
  runtime: "edge",
};

export default async function handler(req) {
  try {
    const { email, subject, html } = await req.json();
    const response = await sendEmail(email, subject, html);

    if (response.error) {
      return new Response(JSON.stringify(response.error), { status: 500 });
    }

    return new Response(JSON.stringify(response.data), { status: 200 });
  } catch (error) {
    console.error(error);
    return new Response("Internal Server Error", { status: 500 });
  }
}

Add a config variable to the route:

//app/routes/register.jsx
import Auth from "../components/Auth";
import { authenticator } from "../../services/auth.server";
import { redirect } from "@remix-run/node";
import { register } from "../../services/authService.server";
import { useActionData } from "@remix-run/react";

export const meta = () => {
  return [
    {
      title: "",
    },
  ];
};

export const config = {
  maxDuration: 60,
};

export const loader = async ({ request }) => {
  const user_id = await authenticator.isAuthenticated(request);
  if (user_id) return redirect("/dashboard");
  return null;
};

export let action = async ({ request }) => {
  return await register(request);
};

export default function Register() {
  const toast = useActionData();
  return <Auth />;
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.