typescript - ParamCheck ტიპის შეცდომა NextJS როუტ ჰენდლერზე


  1. მე მაქვს NextJS 13.4 აპლიკაცია, რომელიც იყენებს App Router-ს.
  2. მე მაქვს მარშრუტის დამმუშავებელი (/api/me), რომელიც იღებს პროფილის ინფორმაციას.
  3. როუტის დამამუშავებელი დაცულია Auth0-ის withApiAuthRequired() ფუნქციით.
  4. ანდფოინტი მუშაობს როგორც მოსალოდნელი, როცა აპლიკაციას ვმართავ Dev რეჟიმში (yarn dev), თუმცა:
  5. პროდუქციის შექმნა იცვლება (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 };

მე ვიყენებ:

  1. "next": "^13.4.6"
  2. "@auth0/nextjs-auth0": "^3.0.1"
  3. "@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 };