NextJS API route error "TypeError: res.status is not a function" - api

I created a simple api endpoint named getFeed which is supposed to get feed content from Sanity CMS. But unexpectedly the endpoint is throwing an error "res.status is not a function". I know there is a similar question asked here , but in my case the api endpoint file is stored in the supposed pages/api directory. Here is the code snippet below.
import { NextApiResponse } from 'next'
import { client } from '../../lib/sanity/sanity'
export default async function getFeed(res: NextApiResponse) {
try {
const feeds = await client.fetch(
`*[_type == "post"]
{
_createdAt,
title,
description,
picture,
postDocId,
postedByUserId,
postedByUserName,
postedByUserImage
}`
)
return res.status(200).json({ feeds })
} catch (error) {
return res.status(500).json({ message: "Couldn't get post feed:\n", error })
}
}
Here is my folder structure
What am I doing wrong??

Try to specify also the req parameter and add a type to the response:
import { NextApiRequest, NextApiResponse } from 'next'
interface Data {
message?: string;
feeds?: <type-of-feeds>[];
}
export default async function getFeed(req: NextApiRequest, res: NextApiResponse<Data>) { ... }

Related

Vercel: This Serverless Function (FUNCTION_INVOCATION_FAILED)

I have an error that appears when I try to access my link
This Serverless Function has crashed.
Your connection is working correctly.
Vercel is working correctly.
500: INTERNAL_SERVER_ERROR
Code: FUNCTION_INVOCATION_FAILED
ID: cdg1:cdg1::bgdnz-1676557396498-149041f4043b
[GET] /6OzxT
15:07:51:26
2023-02-16T14:07:51.324Z 020abb04-a238-441a-8a1d-5a4fb96d66c3 ERROR Unhandled Promise Rejection {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"TypeError: fetch failed","reason":{"errorType":"TypeError","errorMessage":"fetch failed","cause":{"errorType":"ConnectTimeoutError","errorMessage":"Connect Timeout Error","code":"UND_ERR_CONNECT_TIMEOUT","name":"ConnectTimeoutError","message":"Connect Timeout Error","stack":["ConnectTimeoutError: Connect Timeout Error"," at onConnectTimeout (/var/task/vercel/path0/node_modules/undici/lib/core/connect.js:182:24)"," at /var/task/vercel/path0/node_modules/undici/lib/core/connect.js:129:46"," at Immediate._onImmediate (/var/task/vercel/path0/node_modules/undici/lib/core/connect.js:170:9)"," at process.processImmediate (node:internal/timers:471:21)"]},"stack":["TypeError: fetch failed"," at fetch (/var/task/vercel/path0/node_modules/undici/index.js:113:13)"," at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: TypeError: fetch failed"," at process.<anonymous> (file:///var/runtime/index.mjs:1194:17)"," at process.emit (node:events:525:35)"," at emit (node:internal/process/promises:149:20)"," at processPromiseRejections (node:internal/process/promises:283:27)"," at process.processTicksAndRejections (node:internal/process/task_queues:96:32)"]}
Unknown application error occurred
Runtime.Unknown
I tried to add a try/catch, and normally it should be redirected to the URL (here steellgold.fr)
+page.server.ts (Redirect page) (https://preview.linkfy.fr/6OzxT)
import { PUBLIC_URL, PUBLIC_API_URL } from "$env/static/public";
import type { Link } from "$lib/types/link.type";
import { restRequest } from "$lib/utils/request/request";
import { error, redirect } from "#sveltejs/kit";
import type { PageServerLoad } from "./$types";
// eslint-disable-next-line
export const load = (async({ params }) => {
if (!params.slug) throw redirect(303, PUBLIC_URL);
const data = await restRequest<Link>("get", PUBLIC_URL + "api/link", {
query: {
slug: params.slug
}
}, [], true);
if (!data.success) {
throw error(404, { message: "This link not exist or has been disabled", code: 404 });
}
try {
fetch(PUBLIC_API_URL + "link/" + params.slug);
} catch (e) {
console.error(e);
}
if (!data.data.status) throw error(423, { message: "This link has been disabled", code: 423 });
throw redirect(303, data.data.url);
}) satisfies PageServerLoad;
increment.ts (Fastify route fort increment links)
import { FastifyReply, FastifyRequest } from "fastify";
import { app } from "../..";
import { Link } from "../../types/link";
import { error, success, warn } from "../../utils/logger";
import prisma from "../../utils/prisma";
app.get("/link/:slug", {
handler: async(request: FastifyRequest<{ Params: Link }>, reply: FastifyReply) => {
reply.status(200).send({ message: "Correctly routed received request." });
warn(`[GET] incrementing link with slug /${request.params.slug}.`);
const link = await prisma.link.findUnique({
where: { slug: request.params.slug }
});
if (!link) {
reply.status(404).send({ error: "Link not found" });
error(`[404] Link with slug /${request.params.slug} not found.`);
return;
}
await prisma.link.update({
where: { slug: request.params.slug },
data: { clicks: link.clicks + 1 }
});
success(`[200] Link with slug /${request.params.slug} incremented by 1.`);
return reply.status(200).send({
message: "Link incremented successfully."
});
}
});```
All codes is open-source: https://github.com/Steellgold/Linkfy or https://github.com/Steellgold/LinkfyAPI if you want

Nuxt 3 - Server not ready on mount, Volar engine confused

I have two issues that may or may not be related.
Overview
Folder Structure
pages
|---user.vue
server
|---api
|---profile.get.ts
|---profile.post.ts
The tech is Nuxt3 using the server and Supabase.
profile.get.ts
import { serverSupabaseClient, serverSupabaseUser } from "#supabase/server"
import { Database } from "~~/types/supabase"
export default defineEventHandler(async (event) => {
try {
const supabase = serverSupabaseClient<Database>(event)
const user = await serverSupabaseUser(event)
const query = getQuery(event)
const { data, error } = await supabase.from('profiles').select('*').eq('email', query.email).single()
if (error) throw { status: error.code, message: error.message }
return { displayName: data.display_name, avatarUrl: data.avatar_url }
} catch (err) {
console.error('Handled Error:', err)
}
})
profile.post.ts
import { serverSupabaseClient } from "#supabase/server"
import { Database } from "~~/types/supabase"
export default defineEventHandler(async (event) => {
const supabase = serverSupabaseClient<Database>(event)
const { displayName, avatarUrl, email }: { displayName: string, avatarUrl: string, email: string } = await readBody(event)
const { error } = await supabase.from('profiles').update({ display_name: displayName, avatar_url: avatarUrl }).match({ email })
if (error) throw new Error(error.message)
return { status: 200 }
})
user.vue Snippet
onMounted(() => {
setTimeout(() => {
getProfile()
}, 100) // Fails when around 50 or less
})
async function getProfile() {
const { data, error } = await useFetch('/api/profile', { method: 'GET', params: { email: user.value?.email } })
console.log(data.value)
console.log(error.value)
displayName.value = data.value!.displayName || ''
avatarUrl.value = data.value!.avatarUrl || ''
}
Problem 1
When user.vue mounts, I want to call my Nuxt API (profile.get.ts) and fetch user data (display name, avatar url) from the Supabase database. However, I receive this error when fetching on mount: FetchError: 404 Cannot find any route matching /api/profile. (/api/profile). However, if I use setTimeout to 100ms, it fetches fine. That makes me think the API server is simply not ready, but the documentation doesn't mention that and encourages fetching during lifecycle.
Problem 2
Volar seems to be confused about the typing of data from getProfile().
Property 'displayName' does not exist on type '{ status: number; } | { displayName: string | null; avatarUrl: string | null; }'.
Property 'displayName' does not exist on type '{ status: number; }'.ts(2339)
However, this is the typing from profile.post.ts even though I'm using profile.get.ts.
Current Behavior
Without setTimeout at 100ms or greater, it will fail with the 404 message
With setTimeout at 100ms or greater, or with getProfile() called from a button, there is no issue, even with the TypeScript errors, etc.
Desired Behavior
TypeScript correctly recognizes the proper endpoint (profiles.get.ts since I'm calling it with get)
Data can be fetched on mount from the API without the use of setTimeout

Front end Mutation call won't resolve

I have a react-native mobile app making a call to a graphql backend. Queries are working without issue. I just coded a mutation however, and everytime I try to make a call, the client is raising this issue:
Error: Could not find a default resolver for travelPassPasswordResetEmail. Please supply a resolver for this mutation.: {"response":{"errors":[{"message":"Could not find a default resolver for travelPassPasswordResetEmail. Please supply a resolver for this mutation.","locations":[{"line":2,"column":3}],"path":["travelPassPasswordResetEmail"]}],"data":null,"status":201,"headers":{"map":{"content-type":"application/json"}}},"request":{"query":"mutation travelPassPasswordResetEmail($email: String) {\n travelPassPasswordResetEmail(email: $email) {\n message\n status\n }\n}","variables":{"email":"test#test.com"}}}
We are using graphql-codegen.
The mutation in the schema:
type Mutation {
travelPassPasswordResetEmail(email: String): SetResetPasswordMutation!
}
The operations graphql file:
mutation travelPassPasswordResetEmail($email: String) {
travelPassPasswordResetEmail(email: $email) {
message
status
}
}
In the types files we get the following generated for the mutation:
export const TravelPassPasswordResetEmail = gql`
mutation travelPassPasswordResetEmail($email: String) {
travelPassPasswordResetEmail(email: $email) {
message
status
}
}
`;
export const TravelPassPasswordResetEmailDocument = gql`
mutation travelPassPasswordResetEmail($email: String) {
travelPassPasswordResetEmail(email: $email) {
message
status
}
}
`;
export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = defaultWrapper) {
return {
travelPassPasswordResetEmail(variables?: TravelPassPasswordResetEmailMutationVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise<TravelPassPasswordResetEmailMutation> {
return withWrapper((wrappedRequestHeaders) => client.request<TravelPassPasswordResetEmailMutation>(TravelPassPasswordResetEmailDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'travelPassPasswordResetEmail');
}
};
}
Does anyone know why this is asking for a resolver and it cannot be found? I have tested the graphql on the backend with postman and everything is ok.

Cannot read property 'context' of undefined - GraphQL

I am using Typescript, Express, TypeORM, GraphQL and TypeGraphQL to build a small app that allows the user to login.
However, when I hit my test query bye on the GraphQL playground, I get:
Cannot read property 'context' of undefined
"TypeError: Cannot read property 'context' of undefined",
" at new exports.isAuth // isAuth is a JS file I wrote
MyContext.js
import { Request, Response } from "express";
export interface MyContext {
req: Request;
res: Response;
payload?: { userId: string };
}
isAuth.js
import { MiddlewareFn } from "type-graphql";
import { verify } from "jsonwebtoken";
import { MyContext } from "./MyContext";
export const isAuth: MiddlewareFn<MyContext> = ({ context }, next) => {
const authorization = context.req.headers["authorization"];
if (!authorization) {
throw new Error("not authorized");
}
...
UserResolver
#Query(() => String)
#UseMiddleware(isAuth)
bye(#Ctx() { payload }: MyContext) {
console.log(payload);
return `your user id is: ${payload!.userId}`;
}
I am not sure why the context is undefinied in the file isAuth.js
SOLVED thanks to: https://github.com/MichalLytek/type-graphql/issues/433
1) Go into ./tsconfig.json
2) Change "target": "es5" to "target": "es6"

ReferenceError: data is not defined in angular 6

Im calling a service from one of my component, via the assignGirdle function. While this service is being executed, I get the above error, but when I check in the network tab and click on the API call, in response in can see the data.
Note girdleNew is of type any. Also this function I'm calling on ngOnInit()
assignGirdle() {
this.diamondSearchService.getDistinctValues()
.subscribe((data) => {
this.girdleNew = data;
}, error => {
this.alertify.error(error);
});
}
The service:
getDistinctValues() {
return this.authHttp
.get(this.baseUrl + 'distinct/girdle')
.map(response => response.json())
.catch(this.handleError);
}
Check if you have imported service in your component. Below is my data service import.
import { DataService } from '../data.service';
Create object of the same in your component:
constructor(public data: DataService) { }
In my component I have called this getUser() method which is defined in DataService.
this.data.getUser(email).subscribe( data => {
if(data.length > 0){
console.log(data);
}
});
Below is my service:
getUser(email){
// definition
}
This works for me.