Переглянути джерело

restful api 代理接口返回数据优化;clientFetch函数返回数据优化;

fogwind 4 днів тому
батько
коміт
2b9163fa02

+ 1 - 1
src/app/(public)/customer/account/mycoupon/_components/GiftCardList.tsx

@@ -32,7 +32,7 @@ const GiftCardList: React.FC = () => {
   useEffect(() => {
     const load = async () => {
       const resp = await clientFetch("/api/gift/my-gift-cards");
-      const dataObj = resp.data.data;
+      const dataObj = resp.data;
       setGiftCards((prev) => [...prev, ...dataObj]);
       console.log("完整返回:", dataObj);
     };

+ 2 - 2
src/app/(public)/customer/account/pointsreceivelist/_components/RedeemGiftCard.tsx

@@ -19,10 +19,10 @@ const RedeemGiftCard: React.FC = () => {
   useEffect(() => {
     const load = async () => {
       const resp = await clientFetch("/api/gift/lists");
-      const dataObj = resp.data.data.lists;
+      const dataObj = resp.data.lists;
       const dataArray = Object.values(dataObj);
       setList(dataObj);
-      setmyPoints(resp.data.data.myPoints);
+      setmyPoints(resp.data.myPoints);
        console.log("完整返回:", dataArray,myPoints);
     };
 

+ 6 - 16
src/app/api/gift/add/route.ts

@@ -1,6 +1,5 @@
 import { NextRequest, NextResponse } from "next/server";
 import { restApiFetch } from "@/utils/bagisto";
-import { isBagistoError } from "@/utils/type-guards";
 import { getAuthToken } from "@/utils/helper";
 
 export async function POST(req: NextRequest) {
@@ -21,28 +20,19 @@ export async function POST(req: NextRequest) {
         });
         // 打印后端原始返回结构
         console.log('接口原始response.body =', JSON.stringify(response.body, null, 2));
-        return NextResponse.json({
+        return NextResponse.json(response.body,{
             status: response.status,
-            data: response.body,
         });
+
     } catch (error) {
         console.log('/gift/add --- ', error); // 调试用
-        if (isBagistoError(error)) {
-            return NextResponse.json(
-                {
-                    data: null,
-                    error: error.cause ?? error,
-                },
-                { status: 200 }
-            );
-        }
-
         return NextResponse.json(
             {
-                message: "Network error",
-                error: error instanceof Error ? error.message : error,
+                message: error instanceof Error ? error.message : "Network error",
+                success: false,
+                data: []
             },
-            { status: 500 }
+            { status:500 }
         );
     }
 }

+ 5 - 16
src/app/api/gift/lists/route.ts

@@ -1,6 +1,5 @@
 import { NextRequest, NextResponse } from "next/server";
 import { restApiFetch } from "@/utils/bagisto";
-import { isBagistoError } from "@/utils/type-guards";
 import { getAuthToken } from "@/utils/helper";
 import type { GiftListBody,FetchWrap  } from '@/types/api/gift/lists';
 export async function GET(req: NextRequest) {
@@ -12,27 +11,17 @@ export async function GET(req: NextRequest) {
             cache:'no-store',
             guestToken,
         });
-        return NextResponse.json({
+        return NextResponse.json(response.body,{
             status: response.status,
-            data: response.body,
         });
     } catch (error) {
-        if (isBagistoError(error)) {
-            return NextResponse.json(
-                {
-                    data: null,
-                    error: error.cause ?? error,
-                },
-                { status: 200 }
-            );
-        }
-
         return NextResponse.json(
             {
-                message: "Network error",
-                error: error instanceof Error ? error.message : error,
+                message: error instanceof Error ? error.message : "Network error",
+                success: false,
+                data: []
             },
-            { status: 500 }
+            { status:500 }
         );
     }
 }

+ 20 - 19
src/app/api/gift/my-gift-cards/route.ts

@@ -1,38 +1,39 @@
 import { NextRequest, NextResponse } from "next/server";
 import { restApiFetch } from "@/utils/bagisto";
-import { isBagistoError } from "@/utils/type-guards";
 import { getAuthToken } from "@/utils/helper";
-import type { GiftCardRespBody,FetchResult  } from '@/types/api/gift/my-gift-cards';
+import type { GiftCardRespBody } from '@/types/api/gift/my-gift-cards';
 export async function GET(req: NextRequest) {
     try {
         const guestToken = getAuthToken(req);
-        const response = await restApiFetch<FetchResult<GiftCardRespBody>>({
+
+        const searchParams = req.nextUrl.searchParams;
+        const page = searchParams.get('page') || '1';
+        const per_page = searchParams.get('per_page') || '10';
+
+        const response = await restApiFetch<{
+            data: GiftCardRespBody,
+            variables: {page: string;per_page: string;}
+        }>({
+            variables: {
+                page,
+                per_page
+            },
             api: `/gift/my-gift-cards`,
             method:'GET',
             cache:'no-store',
             guestToken,
         });
-        return NextResponse.json({
+        return NextResponse.json(response.body,{
             status: response.status,
-            data: response.body,
         });
     } catch (error) {
-        if (isBagistoError(error)) {
-            return NextResponse.json(
-                {
-                    data: null,
-                    error: error.cause ?? error,
-                },
-                { status: 200 }
-            );
-        }
-
-        return NextResponse.json(
+         return NextResponse.json(
             {
-                message: "Network error",
-                error: error instanceof Error ? error.message : error,
+                message: error instanceof Error ? error.message : "Network error",
+                success: false,
+                data: []
             },
-            { status: 500 }
+            { status:500 }
         );
     }
 }

+ 9 - 13
src/lib/restApiClient.ts

@@ -21,7 +21,7 @@ async function getCachedSession(): Promise<BagistoSession | null> {
   return session;
 }
 
-export async function clientFetch(apiUrl: string, options: RequestInit = {}) {
+export async function clientFetch<T = any>(apiUrl: string, options: RequestInit = {}): Promise<T> {
     // 请求的是nextjs的代理接口
 
     const session = await getCachedSession();
@@ -38,18 +38,14 @@ export async function clientFetch(apiUrl: string, options: RequestInit = {}) {
     } else {
         options.headers = headers;
     }
-    
+
+    // fetch 不会reject 非2xx http状态码的响应,而是resolve,所以不会走catch,如果要走catch,需要自己主动抛出异常
     const response = await fetch(apiUrl, options);
-    // console.log('response -- ', response);
-    if(response.ok) {
-        const result = await response.json();
-        return result;
-    } else {
-        return {
-            status: response.status,
-            statusText: response.statusText,
-            data: await response.text(),
-        }
-    }
+    const result = await response.json();
+    console.log('response -- ', response);
+    // if(!response.ok) { // 非2xx状态
+    //     // 
+    // }
+    return result;
     
 }

+ 7 - 0
src/types/api/gift/my-gift-cards.ts

@@ -15,6 +15,13 @@ export interface GiftCardRespBody {
   success: boolean;
   message: string;
   data: GiftCardItem[];
+  pagination: {
+    current_page: number;
+    has_more: boolean;
+    last_page: number;
+    per_page: number;
+    total: number;
+  };
 }
 
 // restApiFetch返回外层结构

+ 33 - 76
src/utils/bagisto/index.ts

@@ -50,7 +50,8 @@ import {FetchGraphqlResult} from "@/types/graphqlFetch/type";
 
 type ExtractVariables<T> = T extends { variables: object }
   ? T["variables"]
-  : never;
+  : any;
+type ExtractData<T> = T extends { data: infer D } ? D : any;
 
 interface PageByUrlKeyResponse {
   pageByUrlKeypages?: PageData[];
@@ -110,9 +111,11 @@ export async function restApiFetch<T>({
   isCookies?: boolean;
   guestToken?: string;
   revalidate?: number;
-}): Promise<{ status: number; body: T } | never> {
+}): Promise<{ status: number; body: ExtractData<T> } | never> {
   try {
     const apiUrl = api.startsWith("http") ? api : `${REST_API_URL}${api}`;
+    const url = new URL(apiUrl);
+
     let accessToken: string | undefined = undefined;
 
     if (isCookies) {
@@ -139,7 +142,7 @@ export async function restApiFetch<T>({
         Object.assign(baseHeaders, headers);
       }
     }
-console.log('restApiFetch --- baseHeaders:', baseHeaders)
+    console.log('restApiFetch --- baseHeaders:', baseHeaders)
     const param: RequestInit = {
       method: method,
       headers: baseHeaders,
@@ -149,16 +152,22 @@ console.log('restApiFetch --- baseHeaders:', baseHeaders)
         ...(tags && { tags }),
       },
     };
-    if(variables) {
+    if(variables && method === "POST") {
       param.body = JSON.stringify({...variables});
     }
+    if(variables && method === "GET") {
+      const entries = Object.entries(variables as Record<string, unknown>);
+      for (const [key, val] of entries) {
+        if (val !== undefined && val !== null) {
+          url.searchParams.set(key, String(val));
+        }
+      }
+    }
 
-    const result = await fetch(apiUrl, param);
-    console.log('restApiFetch --- result:', result)
-    const body = await result.json();
-
-    if (body.errors) throw body.errors[0];
+    const result = await fetch(url, param);
 
+    const body = await result.json();
+    console.log('restApiFetch --- body:', body)
     return { status: result.status, body };
   } catch (e) {
     throw e;
@@ -176,7 +185,7 @@ export async function serverGraphqlFetch<
   tags,
   variables,
   revalidate = 0,
-  operationName = ''
+  // operationName = ''
 }: {
   cache?: RequestCache;
   headers?: HeadersInit | Record<string, string>;
@@ -184,7 +193,7 @@ export async function serverGraphqlFetch<
   tags?: string[];
   variables?: TVariables;
   revalidate?: number;
-  operationName?: string;
+  // operationName?: string;
 }): Promise<FetchGraphqlResult<TData>> {
   try {
     const queryString = typeof query === "string" ? query : print(query);
@@ -245,15 +254,21 @@ export async function serverGraphqlFetch<
 
     const body = await result.json();
     console.log('serverGraphqlFetch --- body:',body);
-    if (body.errors) {
-      if(operationName === 'GetCartItem' && body.errors[0].message === 'Cart not found') {
-        return { status: result.status, data: body.data, error: null };
-      } else {
-        return { status: result.status, data: body.data, error: body.errors[0] };
-      }
+    return {
+      status:result.status,
+      data:body.data ?? null,
+      error:body.errors?.[0] ?? null
     }
-    return { status: result.status, data: body.data,error: null };
+    // if (body.errors) {
+    //   if(operationName === 'GetCartItem' && body.errors[0].message === 'Cart not found') {
+    //     return { status: result.status, data: body.data, error: null };
+    //   } else {
+    //     return { status: result.status, data: body.data, error: body.errors[0] };
+    //   }
+    // }
+    // return { status: result.status, data: body.data,error: null };
   } catch (e) {
+    console.error( "GraphQL request failed", e );
     throw e;
   }
 }
@@ -335,70 +350,12 @@ export async function bagistoFetch<T>({
 
     const body = await result.json();
     console.log('bagistoFetch --- body:',body);
-    if (body.errors) {
-      if(operationName === 'GetCartItem' && body.errors[0].message === 'Cart not found') {
-        return { status: result.status, body };
-      }
-      throw body.errors[0]
-    }
     return { status: result.status, body };
   } catch (e) {
     throw e;
   }
 }
-/*
-export async function bagistoFetchNoSession<T>({
-  query,
-  tags,
-  variables,
-  headers,
-  cache = "force-cache",
-  revalidate = 60,
-}: {
-  query: string;
-  tags?: string[];
-  variables?: ExtractVariables<T>;
-  headers?: HeadersInit | Record<string, string>;
-  cache?: RequestCache;
-  isCookies?: boolean;
-  revalidate?: number;
-}): Promise<{ status: number; body: T } | never> {
-  try {
-    const result = await fetch(GRAPHQL_URL, {
-      method: "POST",
-      headers: {
-        "Content-Type": "application/json",
-        "X-STOREFRONT-KEY": STOREFRONT_KEY,
-        "x-locale": "en",
-        "x-currency": "USD",
-        ...headers,
-      },
-      body: JSON.stringify({
-        ...(query && { query }),
-        ...(variables && { variables }),
-      }),
-      cache,
-      next: {
-        revalidate: cache === "no-store" ? 0 : revalidate || 60,
-        ...(tags && { tags }),
-      },
-    });
-
-    const body = await result.json();
-
-    if (body.errors) {
-      throw body.errors[0];
-    }
 
-    return {
-      status: result.status,
-      body,
-    };
-  } catch (e) {
-    throw { error: e, query };
-  }
-}
-*/
 export const removeEdgesAndNodes = <T>(array: Array<T>) => {
   return array?.map((edge) => edge);
 };