typescript - ParamCheck ტიპის შეცდომა NextJS როუტ ჰენდლერზე
- მე მაქვს NextJS 13.4 აპლიკაცია, რომელიც იყენებს App Router-ს.
- მე მაქვს მარშრუტის დამმუშავებელი (
/api/me), რომელიც იღებს პროფილის ინფორმაციას. - როუტის დამამუშავებელი დაცულია Auth0-ის
withApiAuthRequired()ფუნქციით. - ანდფოინტი მუშაობს როგორც მოსალოდნელი, როცა აპლიკაციას ვმართავ Dev რეჟიმში (
yarn dev), თუმცა: - პროდუქციის შექმნა იცვლება (
yarn build) შემდეგი შეცდომით.
შეცდომა წაშენების დროს
.next/types/app/api/me/route.ts:32:7
Type error: Type '{ __tag__: "GET"; __param_position__: "first"; __param_type__: NextApiRequest; }' does not satisfy the constraint 'ParamCheck<NextRequest | Request>'.
Types of property '__param_type__' are incompatible.
Type 'NextApiRequest' is not assignable to type 'NextRequest | Request'.
Type 'NextApiRequest' is missing the following properties from type 'NextRequest': geo, ip, nextUrl, page, and 19 more.
30 | Diff<
31 | ParamCheck<Request | NextRequest>,
> 32 | {
| ^
33 | __tag__: 'GET'
34 | __param_position__: 'first'
35 | __param_type__: FirstArg<MaybeField<TEntry, 'GET'>>
error Command failed with exit code 1.
მარშრუტის დამკვირვებელი
// ~/src/app/api/me/route.ts
import { getSession, withApiAuthRequired } from '@auth0/nextjs-auth0';
import { firebaseApp } from '@muze/lib/firebase';
import { getFirestore } from 'firebase-admin/firestore';
import { getDownloadURL, getStorage } from 'firebase-admin/storage';
import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next';
const GET: NextApiHandler = withApiAuthRequired(
async (req: NextApiRequest, res: NextApiResponse) => {
const session = await getSession();
if (!!session && !!firebaseApp) {
// Auth0
const auth0User = session.user;
// Firebase Firestore
const db = getFirestore(firebaseApp);
const firebaseUser = await db
.collection('users')
.where('email', '==', auth0User.email)
.get();
const firebaseUserData = firebaseUser.docs.map((user) => user.data());
// Firebase Storage
const storage = getStorage();
const fileRef = storage
.bucket()
.file(`users/${auth0User.email}/kitmasked.png`);
const fileUrl = await getDownloadURL(fileRef);
// return res.end();
return res.status(200).json({
idNickname: auth0User.nickname,
idName: auth0User.name,
idPicture: auth0User.picture,
idUpdatedAt: auth0User.updated_at,
idEmail: auth0User.email,
idEmailVerified: auth0User.email_verified,
profileJoined: firebaseUserData[0].joined,
profileEmail: firebaseUserData[0].email,
profileUsername: firebaseUserData[0].username,
profileImageUrl: fileUrl,
});
}
}
);
export { GET };
მე ვიყენებ:
"next": "^13.4.6""@auth0/nextjs-auth0": "^3.0.1""@auth0/auth0-react": "^2.2.0"
კრისტალურად ჩანს, რომ რუტის დამმუშავებლის პარამეტრები არიან NextApiRequest და NextApiResponse NextRequest და NextResponse-ის ნაცვლად, შესაბამისად, მაგრამ მე არ მაქვს იდეა, რატომ არის რუტი შედგენილი ისე, რომ შეიცავდეს ამ ParamCheck-ს NextRequest | Request როგორც ტიპის პარამეტრს.
ხრიკები: ასე რატომ ხდება ეს? სწორად ვაშენებ ხომ ანაზუღლებელს?
რას ვცდილობდი
მოსინჯე პარამეტრის ტიპების ცვლილება, მაგრამ withApiAuthRequired() არასდროს მიიღებს სხვა ტიპის ჰენდლერს.
მე არ მინდა API-ის გადატანა pages საქაღალდეში და როგორც Pages Router-ის, ისე App Router-ის გამოყენება.
უკვე მაქვს ნანახი რამდენიმე გამუშვების გზა, რომელიც მოიცავს "სუპერტაიპის" შექმნას, რომელიც მოიცავს როგორც NextApiRequest-ს, ისე NextRequest-ს, მაგრამ ეს ძალიან ჰაკის მსგავსად გამოიყურება. მინდა გავიგო, რატომ ხდება ეს და გამოვიყენო ხელსაწყოები ისე, როგორც ისინი იყო გათვალისწინებული. არ მინდა უბრალოდ მუშაობდეს.
პასუხი #1
ჯერაც ვერ გამიგია როგორ შეცვალო ParamCheck, მაგრამ მეტი კვლევის შემდეგ, ჩემი გაგებით, ზედმეტია withApiAuthRequired()-ის გამოყენება, თუ თან იყენებ getSession() hook-ს და სთხოვ ვალიდურ სესიას. ამიტომ უბრალოდ მოვხსენი withApiAuthRequired() და ვიღებ NextRequest და NextResponse-ს ნაცვლად NextApiRequest და NextApiResponse შესაბამისად:
import { getSession } from '@auth0/nextjs-auth0';
import { firebaseApp } from '@muze/lib/firebase';
import { getFirestore } from 'firebase-admin/firestore';
import { getDownloadURL, getStorage } from 'firebase-admin/storage';
import { NextRequest, NextResponse } from 'next/server';
const GET = async (req: NextRequest, res: NextResponse) => {
const session = await getSession();
if (!!session && !!firebaseApp) {
// Auth0
const auth0User = session.user;
// Firebase Firestore
const db = getFirestore(firebaseApp);
const firebaseUser = await db
.collection('users')
.where('email', '==', auth0User.email)
.get();
const firebaseUserData = firebaseUser.docs.map((user) => user.data());
// Firebase Storage
const storage = getStorage();
const fileRef = storage
.bucket()
.file(`users/${auth0User.email}/profile.png`);
const fileUrl = await getDownloadURL(fileRef);
// return res.end();
return NextResponse.json({
idNickname: auth0User.nickname,
idName: auth0User.name,
idPicture: auth0User.picture,
idUpdatedAt: auth0User.updated_at,
idEmail: auth0User.email,
idEmailVerified: auth0User.email_verified,
profileJoined: firebaseUserData[0].joined,
profileEmail: firebaseUserData[0].email,
profileUsername: firebaseUserData[0].username,
profileImageUrl: fileUrl,
});
}
};
export { GET };
