NEXTJS google trend API - javascript

Having trouble using the npm google trends api in NEXTJS
Not sure if this is the right way to go about it.
I made a new API route.
http://localhost:3000/api/trends
http://localhost:3000/api/trends
import googleTrendsApi from "google-trends-api";
const handler = async (res, req) => {
const data = await googleTrendsApi
.interestOverTime({ keyword: ["Women's march", "Trump Inauguration"] })
.then(function (results) {
console.log("These results are awesome", results);
});
res.status(200).json({ data: data });
};
I get an error saying
TypeError: res.status is not a function

Try this. Here I am using TypeScript, if you are using Javascript, please edit code as needed.
import type { NextApiRequest, NextApiResponse } from 'next'
import googleTrendsApi from "google-trends-api";
type Data = {
name: string
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
const data = googleTrendsApi
.interestOverTime({ keyword: ["Women's march", "Trump Inauguration"] })
.then(function (results: any) {
res.status(200).json(results)
});
}

Related

How to extends express request interface

I'm using express with typescript. I want to extend my express request interface for that I have done something like this:-
Middleware.ts
import { NextFunction, Request, Response } from 'express';
// eslint-disable-next-line #typescript-eslint/no-var-requires
const configureI18n = require('../helpers/i18n');
const [_, i18nObj] = configureI18n(false);
export interface CRequest extends Request {
i18nObj: any;
}
const langHeadersMiddleware = (
request: CRequest,
response: Response,
next: NextFunction
): void => {
try {
const language = request.headers['accept-language'];
i18nObj.setLocale(language ? language : 'en');
request.i18nObj = i18nObj;
next();
} catch (error) {
i18nObj.setLocale('en');
}
};
export default langHeadersMiddleware;
route.ts
getUserProfile.get(
'/:id',
async (request: CRequest, response: express.Response) => {
try {
const id = request.params.id;
response.json({
err: 0,
message: request.i18nObj.__('MESSAGES.USER_FETCH'),
data
});
} catch (error: any) {
response.json({ err: 1, message: error.message, error });
}
}
);
In this route I'm getting an error:-
No overload matches this call.
The last overload gave the following error.
Argument of type '(request: CRequest, response: express.Response) => Promise' is not assignable to parameter of type 'Application<Record<string, any>>'.
Type '(request: CRequest, response: Response<any, Record<string, any>>) => Promise' is missing the following properties from type 'Application<Record<string, any>>': init, defaultConfiguration, engine, set, and 61 more.
I went through so many blogs, article but everyone is using the same as I did.
you would have to fork and rework the whole express package, which would definitely not recommend :)
But You can:
add your i18n to the request in the middleware as you're doing and just use it with //#ts-ignore above it
add your i18n to the request body in the middleware and just use it

Axios & Typescript: Return array object with only the props specified

I'm trying to build an API that fetches the ERC20 tokens in my balance. For this, I'm using nextjs & axios with TypeScript.
The issue I have is that the response outputed by my endpoint returns way too much data, rather than the only 3 props defined in my Token type. Here is how it goes:
util/api.ts
import axios from 'axios';
import console from 'console';
type Token = {
contractAddress: string;
tokenName: string;
tokenSymbol: string;
};
async function getTokens(walletAddress: string) {
const params = {
action: 'tokentx',
address: walletAddress,
offset: 5,
startblock: 0,
endblock: 999999999,
sort: 'asc',
apikey: 'XXXXX'
}
try {
const response = await axios.request<Token[]>({
url: 'https://api.etherscan.io/api?module=account',
params: params
}).then((response) => {
return response.data
});
return response
} catch (error) {
if (axios.isAxiosError(error)) {
console.log('error message: ', error.message);
return error.message;
} else {
console.log('unexpected error: ', error);
return 'An unexpected error occurred';
}
}
}
export async function getWalletBalance(walletAddress: string) {
let tokens = await getTokens(walletAddress)
return tokens
}
pages/api/balances/[network]/[wallet.ts]
import { NextApiRequest, NextApiResponse } from "next";
import NextCors from "nextjs-cors";
import { getWalletBalance } from "../../../../util/api";
export default async (req: NextApiRequest, res: NextApiResponse) => {
await NextCors(req, res, {
methods: ["GET"],
origin: "*",
optionsSuccessStatus: 200,
});
const { wallet } = req.query as { wallet: string };
try {
const balance = await getWalletBalance(wallet);
res.json({ balance });
} catch (e) {
res.status(400).json({ error: (e as Error).message });
}
};
How can I make it so that getTokens() only returns an array of Token with only the contractAddress, tokenName, tokenSymbol props, in order for the endpoint to output only the JSON I need?
If you're looking to reduce the data returned from the api.etherscan.io
in your own proxy api you'd need to filter out only the props you need. you can achieve it like so:
.then((response) => {
return response.data.map(x=>({
contractAddress:x.contractAddress
tokenName:x.tokenName
tokenSymbol:x.tokenSymbol
});
})
I don't know much about the 3rd party endpoint but I assuming its a REST endpoint so you couldn't take advantage of Graphql's ability to reduce overfetching by specifying the properties of the type you're interested in.

how to return Stripe's createToken tokenId and use it in another function in vuex

so I call Stripe.card.createToken in my api.js file and want to return the token this function generates so I can use it in my vuex, how can I do that?
// api.js
export const stripeToken = async ({ cardInfo }) => {
const { data } = await Stripe.card.createToken({
cardInfo,
});
return data;
};
So I want to use it in my actions in vuex like this. I did this and it doesn't work, it returns undefined:
//vuex
import { stripeToken } from '#src/store/api';
async stripeToken({ dispatch }, { cardInfo }) {
const { data } = await stripeToken({ cardInfo });
console.log('tokenId: ', data.tokenId);
},
I'm not familiar with vuex, but the Stripe.card.createToken method takes two parameters: a JavaScript object containing credit card data entered by the user, and a callback function to handle the response. You can learn more about it in the Stripe documentation here.
Here's how you could display the ID of a token with Stripe.card.createToken:
Stripe.card.createToken(cardInfo, (status, response) => {
if (response.error) {
console.log(response.error);
} else {
console.log(response.id);
}
});
Note that Stripe.card.createToken is an old method from Stripe.js v2 that is now deprecated, so I would recommend upgrading to Stripe.js v3 if possible.

Error occurred prerendering page in Next JS [duplicate]

This question already has an answer here:
Fetch error when building Next.js static website in production
(1 answer)
Closed last year.
I created an API in next JS (in the pages/api folder) and I used it on a page in the pages folder.
When I run on the localhost (development stage), the API can be called correctly. But when I deploy to Vercel there is an error during build.
This is my code when i call the API which is in the pages/api folder
export const getStaticProps = async () => {
const baseUrlDribble = 'https://api.dribbble.com/v2';
const baseUrl = process.env.NODE_ENV === 'production' ?
'https://jovanka-samudra.vercel.app/api' : 'http://localhost:3000/api';
const resShots = await fetch(`${baseUrlDribble}/user/shots?access_token=${process.env.TOKEN_DRIBBLE}&page=1&per_page=9`);
const shots = await resShots.json();
const resResult = await fetch(`${baseUrl}/projects`);
const result = await resResult.json();
const projects = result.data.projects;
return {
props: {
shots,
projects,
},
revalidate: 1,
}
}
This is the API code to retrieve data from database (pages/api/projects folder)
import ProjectService from "#services/ProjectService";
import connectDB from "#utils/connectDB";
import projectValidator from "#validators/project";
import ClientError from '#exceptions/ClientError';
const handler = async (req, res) => {
const projectService = new ProjectService();
if (req.method === 'GET') {
try {
const projects = await projectService.getProjects();
return res.status(200).json({
success: true,
length: projects.length,
data: {
projects
}
});
} catch (error) {
return res.status(500).json({
success: false,
message: error.message,
});
}
} else if (req.method === 'POST') {
...
}
return res.status(404).json({
success: false,
message: 'Method not alowed'
});
}
export default connectDB(handler);
services/ProjectService folder
import InvariantError from '#exceptions/InvariantError';
import NotFoundError from '#exceptions/NotFoundError';
import Project from '#models/Project';
class ProjectService {
async getProjects() {
const projects = await Project.find().sort({ 'createdAt': -1 });
return projects;
}
...
}
export default ProjectService;
You should not fetch an internal API route from getStaticProps — instead, you can write the fetch code in API route directly in getStaticProps.
https://nextjs.org/docs/basic-features/data-fetching/get-static-props#write-server-side-code-directly

TypeError: resolver is not a function

I am attempting to create a basic post on click in my NextJS app to a MongoDB database. The issue i am getting is TypeError: resolver is not a function. I understand it might be a syncronicity issue but for the life of me I cannot figure out where.
Stack used: NextJS, Axios, Mongoose.
Component code snippet calling axios:
i know the states are updating so i am putting only the snippet that handles the request
handleSubmit = async (e: any) => {
e.preventDefault();
await axios
.post('/api/roomSession', {
roomName: this.state.roomName,
teamName: this.state.teamName
})
.then((response: any) => console.log('axios call reached', response))
.catch((error: any) => console.log('---- error! ----', error));
};
[...]
<button onClick={this.handleSubmit}>Create</button>
[...]
NextJS API file:
import { newSession } from '../../packages/backend/mongo/connection';
const apiNewSession = async (roomName, teamName) => {
await newSession(teamName, roomName);
};
export default apiNewSession();
Mongoose file:
const mongoose = require('mongoose');
mongoose
.connect(
'mongodbconnection',
{ useNewUrlParser: true, useUnifiedTopology: true }
)
.then(() => {
console.log('connected to mongoDB');
})
.catch(err => console.error('Connection failed: ', err));
const sessionSchema = new mongoose.Schema({
teamName: String,
roomName: String
});
const Session = mongoose.model.tests || mongoose.model('tests', sessionSchema);
export const newSession = async (teamName, roomName) => {
const session = new Session({
teamName,
roomName
});
const result = await session.save();
mongoose.connection.close();
};
Some extra info on the strange behaviour: When first time called, the code throws the aformentioned error but manages to reach the mongoDB connection and creates an EMPTY entry inside the collection (only _id, and _v).
Upon second attempt, only the error is thrown.
I was exporting the function incorrectly from the NextJS API file.
Correct method:
export default apiNewSession;
Not sure why it still happened when when i was exporting the function by default.
My problem was that I was defining a middleware function incorrectly...
This is okay
/* pages/api/endpoint.js */
export default MiddleWare(handler)
But middleware functions shouldn't be async...
async function MiddleWare(handler) {
// ^ remove this!
return async function (req, res) {
// some async stuff
next(req, res);
}
}

Categories