How is this anonymous function being called - javascript

I came across this code:
export default async function (req, res) {
...
}
This appears to be an anonymous function and it does get called when the app is run, but but I don't know how it can get called.
NOTE: This is part of a Nodejs app.
The entire code that it is part of is located in a single file:
import { Configuration, OpenAIApi } from "openai";
const configuration = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);
export default async function (req, res) {
if (!configuration.apiKey) {
res.status(500).json({
error: {
message: "OpenAI API key not configured, please follow instructions in README.md",
}
});
return;
}
const animal = req.body.animal || '';
if (animal.trim().length === 0) {
res.status(400).json({
error: {
message: "Please enter a valid animal",
}
});
return;
}
try {
const completion = await openai.createCompletion({
model: "text-davinci-003",
prompt: generatePrompt(animal),
temperature: 0.6,
});
res.status(200).json({ result: completion.data.choices[0].text });
} catch(error) {
// Consider adjusting the error handling logic for your use case
if (error.response) {
console.error(error.response.status, error.response.data);
res.status(error.response.status).json(error.response.data);
} else {
console.error(`Error with OpenAI API request: ${error.message}`);
res.status(500).json({
error: {
message: 'An error occurred during your request.',
}
});
}
}
}
function generatePrompt(animal) {
const capitalizedAnimal =
animal[0].toUpperCase() + animal.slice(1).toLowerCase();
return `Suggest three names for an animal that is a superhero.
Animal: Cat
Names: Captain Sharpclaw, Agent Fluffball, The Incredible Feline
Animal: Dog
Names: Ruff the Protector, Wonder Canine, Sir Barks-a-Lot
Animal: ${capitalizedAnimal}
Names:`;
}

It's the default export of a file. So when it is imported in another file, the whole default export can be placed into a variable.
// file1.js
export default async function (req, res) {
...
}
// file2.js
import myDefault from "file1.js";
// do something with myDefault
Or using the alternative syntax, useful when there are other exports from the file:
// file3.js
import { default as alias } from "file1.js";
// do something with alias

Function in question is an default export of the file, so when this file will be imported you will be able to give this default export any name, e.g. import defaultExportAlias from "module-name";

Like this:
import func from './file';
func();
However keep in mind that unnamed exports are a violation of this eslint rule.

Related

Create T3 App Redirect inside a TRPC middleware if user is not signed

How can I trigger a redirect on the server side if a signed in user has not completed their profile page
const enforceUserIsAuthed = t.middleware(({ ctx, next }) => {
if (!ctx.session || !ctx.session.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
// redirect to profile page if user has not completed profile
return next({
ctx: {
// infers the `session` as non-nullable
session: { ...ctx.session, user: ctx.session.user },
},
});
});
This is not currently possible in the way you are describing to the best of my knowledge.
Here are some alternatives that might be helpful:
In getServerSideProps
this only works if you want to redirect before the initial page load. You could also create a wrapper around gSSP to make this more DRY if you're going to use it on a lot of pages.
import { type GetServerSidePropsContext } from "next";
import { getServerAuthSession } from "../server/auth";
export async function getServerSideProps(ctx: GetServerSidePropsContext) {
const session = await getServerAuthSession(ctx);
if (!session) {
return {
redirect: {
destination: "/",
permanent: false,
},
};
}
return {
props: {},
};
}
export default function AuthedPage() {
return <div>Authed</div>;
}
As part of a query or mutation clientside
this is useful for a query or mutation that is only fired after the page has loaded. Again this is a very simple example and could be DRYed, probably the easiest way would be to extract into a custom hook.
import { useRouter } from "next/router";
import { api } from "../utils/api";
export default function AuthedPage() {
const router = useRouter();
// `authedHello` is the example Create T3 App "hello" procedure
// but as a protectedProcedure, ie throws "UNAUTHORIZED" if no session.
// Replace this with a middleware that throws on whatever condition you need it to.
const authedHello = api.example.protectedHello.useQuery(
{ text: "world" },
{
retry: (_count, err) => {
// `onError` only runs once React Query stops retrying
if (err.data?.code === "UNAUTHORIZED") {
return false;
}
return true;
},
onError: (err) => {
if (err.data?.code === "UNAUTHORIZED") {
void router.push("/");
}
},
}
);
return (
<div>
<h1>Authed Page</h1>
<p>{authedHello.data?.greeting}</p>
</div>
);
}
Using Next.js middleware
This is easy to apply to a bunch of routes using the matcher, but it falls a bit outside of T3 conventions.
// pages/middleware.ts
import { NextResponse } from "next/server";
import { getServerSession } from "next-auth";
import { authOptions } from "../server/auth";
import type { NextApiRequest, NextApiResponse } from "next";
export async function middleware(req: NextApiRequest, res: NextApiResponse) {
const session = await getServerSession(req, res, authOptions);
if (!session?.user) {
return NextResponse.redirect(new URL("/", req.url));
}
}
export const config = {
matcher: ["/protectedPage", "/anotherProtectedPage"],
};
Using require in next-auth's useSession
this is useful if you want to guard a page but can't use getServerSideProps. It doesn't quite solve your specific problem, but might be useful to other people who find this. See: https://next-auth.js.org/getting-started/client#require-session

Auth0 Endpoint "api/auth/me" returns a 404 Error in Next.js App

I have gone through the following tutorial to get my Next.js App integrated with Auth0.
I am able to log in and log out just fine but when trying to display user information on the page after login, the user object is unable to be returned. I have ensured that there is nothing wrong with the Profile.js page that is rendering the user object or the env.local file with my app's secret keys.
After further inspection I noticed that I get an error in the browser console that reads: Failed to Load Resource ... 404 Not Found: http://localhost:3000/api/auth/me.
This error gives me a gut feeling that there is a discrepancy in the mapping between my next.js app and Auth0 since I have modified the basepath in next.config.js:
module.exports = {
basePath: '/my_path',
webpack: (config) => {
return config
},
env: {
},
publicRuntimeConfig: {
BACKEND_API_URL: process.env.BACKEND_API_URL,
CONSENT_COOKIE_NAME: 'ConsentCookie'
},
}
Is there a way to add my basepath into the endpoint that the user object is being returned from? The end result would look something like: https://localhost:3000/my_path/api/auth/me
I am not 100% certain that this will fix my issue with getting the user object returned properly, so I am open to any other suggestions and willing to add more context surrounding specific files in my app.
Edit:
After bringing this issue up on the Auth0 forums (link), I was pointed towards this link, which is another example Next.js Auth0 sample app, except they have written their frontend with TypeScript (which I am not familiar with). They are manipulating the UserContext object and resetting the ProfileURL, which is what I am after; so what would be the JavaScript equivalent to this?
The same repsonse to the Auth0 forum post I mentioned also included another link to an example function that creates a custom URL for the login. This is very close to what I am after since again, I am trying to create a custom auth URL to retrieve the User object and get rid of the 404 ... /api/auth/me not found error.
Due to my inexperience with JS, my attempts at trying to create a similar function to the example stated previously have failed, so what would this look like?
I am feeling intense bittersweet emotions after finding an insultingly simple solution to this issue.
Found in the readme.md of the NextJS-Auth0 repository...
This small snippet of code fixed all of my issues after hours of searching for a solution -
// _app.js
function App({ Component, pageProps }) {
return (
<UserProvider loginUrl="/foo/api/auth/login" profileUrl="/foo/api/auth/me">
<Component {...pageProps} />
</UserProvider>
);
}
Now to get back to wiping the tears off my desk..
I have been having this issue too. What was happening for my Next app deployed on Vercel is that all the api/auth/* routes were not working in production but everything worked locally.
I'm using the Auth0 Universal Login Experience
// package.json
...
"dependencies": {
"#auth0/nextjs-auth0": "^1.9.2",
}
...
All I had before was the function
// api/auth/[...auth0].ts
import { handleAuth } from "#auth0/nextjs-auth0";
export default handleAuth();
So what I did is create all the paths I'd need in my application in their respective files. I think Next.js was not creating the dynamic files at [...auth0].ts
// api/auth/callback.ts
import { handleCallback } from "#auth0/nextjs-auth0";
import { NextApiRequest, NextApiResponse } from "next";
const callbackHandler = async (req: NextApiRequest, res: NextApiResponse) => {
try {
await handleCallback(req, res);
} catch (error) {
res.status(error.status || 400).end(error.message);
}
};
export default callbackHandler;
// api/auth/login.ts
import { handleLogin } from "#auth0/nextjs-auth0";
import { NextApiRequest, NextApiResponse } from "next";
const loginHandler = async (req: NextApiRequest, res: NextApiResponse) => {
try {
await handleLogin(req, res, {
authorizationParams: {
screen_hint: "login",
},
});
} catch (error) {
res.status(error.status || 400).end(error.message);
}
};
export default loginHandler;
// api/auth/logout.ts
import { handleLogout } from "#auth0/nextjs-auth0";
import { NextApiRequest, NextApiResponse } from "next";
const logoutHandler = async (req: NextApiRequest, res: NextApiResponse) => {
try {
await handleLogout(req, res);
} catch (error) {
res.status(error.status || 400).end(error.message);
}
};
export default logoutHandler;
// api/auth/me.ts
// not api/auth/profile.ts
import { handleProfile } from "#auth0/nextjs-auth0";
import { NextApiRequest, NextApiResponse } from "next";
const profileHandler = async (req: NextApiRequest, res: NextApiResponse) => {
try {
await handleProfile(req, res);
} catch (error) {
res.status(error.status || 400).end(error.message);
}
};
export default profileHandler;
// api/auth/signup.ts
import { handleLogin } from "#auth0/nextjs-auth0";
import { NextApiRequest, NextApiResponse } from "next";
const signupHandler = async (req: NextApiRequest, res: NextApiResponse) => {
try {
await handleLogin(req, res, {
authorizationParams: {
screen_hint: "signup",
},
});
} catch (error) {
res.status(error.status || 400).end(error.message);
}
};
export default signupHandler;

Not able to export function in nodejs

I have defined a function service in one of the file
import Category from '../models/Category.js';
export const AllCategories = () => {
console.log('hit');
const cursor = Category.find({});
console.log(cursor);
return cursor
}
export default {AllCategories}
I am importing this in the controller file
import express from 'express';
import categoryService from '../services/categories.js'
const router = express.Router();
export const getCategories = async(req,res) => {
try {
const categoriesInfo = categoryService.AllCategories
res.status(200).json(categoriesInfo)
} catch (error) {
res.status(404).json({ message: error.message });
}
}
export default router;
But the issue is that AllCategories is not getting run, what is wrong here
I also tried adding async/await
import Category from '../models/Category.js';
export const AllCategories = async () => {
try {
console.log("hit");
const cursor = await Category.find({});
console.log(cursor);
return cursor
} catch (error) {
return error
}
}
export default {AllCategories}
But still no luck
You're not calling the function, this saves it in the variable categoriesInfo:
const categoriesInfo = categoryService.AllCategories
To get its return value:
const categoriesInfo = await categoryService.AllCategories();
Note: I think you need to make it async if you're doing a db transaction so keep the second version and test it.
You can't use the ES module or ESM syntax by default in node.js. You either have to use CommonJS syntax or you have to do 1 of the following.
Change the file extension from .js to .mjs
Add to the nearest package.json file a field called type with a value of module

Node JS : Route.get() requires a callback function but got a [object Undefined] While using ES6 Modules

Route File
scoreboardroute.js
import { scoreRouteController } from '../controllers/scoreboardcontroller';
const SCOREROUTE = app => {
app.route('/getAllScores').get(scoreRouteController.getAllScores);
};
export { SCOREROUTE };
Controller File
scoreboardcontroller.js
import { scoreBoardModel } from '../model/scoreboardmodel';
class scoreRouteController {
getAllScores = (req, res) => {
scoreBoardModel.getAllScoresList((err, response) => {
if (err) {
res.send(err);
}
res.send(response);
});
};
}
export { scoreRouteController };
Model File:
scoreboardmodel.js
import { db } from './db';
class scoreBoardModel {
getAllScoresList = callback => {
db.query('Select * from users', (err,response) => {
callback(err, response);
});
}
};
export { scoreBoardModel };
I was trying to use ES6 features like class and arrow functions inside my application. While I'm trying to execute this code it hit the following error. I don't know what went wrong. And I'm really new for node JS server.
So, Can anyone please help me to get rid of this error.
Error:
node_modules/express/lib/router/route.js:202
throw new Error(msg);
^
Error: Route.get() requires a callback function but got a [object Undefined]
at Route.(anonymous function) [as get] (/node_modules/express/lib/router/route.js:202:15)
at SCOREROUTE (/app/routes/scoreboardroute.js:4:32)
at Object. (/server.js:26:1)
at Module._compile (internal/modules/cjs/loader.js:689:30)
I'm finding the answer.
While importing the class I'm using like Object import. So, changed it like
import scoreRouteController from '../controllers/scoreboardcontroller';
And I'm not going to use so many instances for my application. So, I assign static keyword for my every function inside my class.
static getAllScores = (req, res) => {.....
While exporting I was not exporting an Obj. I changed into default class export.
export default scoreRouteController;
And finally, it works.

Module has not default export after converting to Typescript

I have converted the JavaScript code to Typescript and getting the error
Module has no default export
I have tried importing using the curly braces and exporting using module.exports but none of them worked.
contactController.ts
const contacts: String[] = [];
// Handle index actions
exports.index = (req: any, res: any) => {
res.json({
data: contacts,
message: "Contacts retrieved successfully",
status: "success"
});
};
// Handle create contact actions
exports.new = (req: any, res: any) => {
// save the contact and check for errors
contacts.push("Pyramids");
res.json({
data: contact,
message: "New contact created!"
});
};
api-route.ts
import contactController from "./contactController";
In the api-routes.ts, when I am trying to import the contactController module it is throwing the error
Module has no default export
How can I import without the error? I have tried using "import {contactController} from "./contactController" but that did not work as well.
Documentation (see the "Export" and "Import" sections): Typescript Modules Documentation.
To complete Vasil's answer:
When you import a module this way:
// <some_file>.ts
import <whatever_name_I_want> from "<path_to_my_awesome_module>";
<my_awesome_module>.ts needs to have a default export. For example, this can be done this way:
// <my_awesome_module>.ts
export default foo = () => { // notice the 'default' keyword
// ...
};
export bar = () => {
// ...
};
With the code above, <whatever_name_I_want> will be the foo method (a module can only have 1 default export). In order to import the bar method as well, you will have to import it seperately:
// <some_file>.ts
import <whatever_name_I_want>, { bar } from "<path_to_my_awesome_module>";
But according to what you're trying to do, there is probably no need to use a default export. You could simply export all your methods with the export keyword, like this:
// contactController.ts
export index = (req: any, res: any) => { // no need for a default export
// ...
};
export create = (req: any, res: any) => {
// ...
};
and import them both either in brackets:
// api-routes.ts
import { index, create } from "./contactController";
// Usage
index(...);
create(...);
or in a global variable:
// api-routes.ts
import * as contactController from "./contactController";
// Usage
contactController.index(...);
contactController.create(...);
PS: I renamed your new method in create because "new" is already a JavaScript keyword.
You need to change the way you export to:
const contacts: String[] = [];
// Handle index actions
const index = (req: any, res: any) => {
res.json({
data: contacts,
message: "Contacts retrieved successfully",
status: "success"
});
};
// Handle create contact actions
const newContact = (req: any, res: any) => {
// save the contact and check for errors
contacts.push("Pyramids");
res.json({
data: contact,
message: "New contact created!"
});
};
export default {index, newContact};
Then you should be able to import then like so
import routes from './contactController';

Categories

Resources