@@ -4,6 +4,7 @@ import { aiService } from "@/server/service/ai";
44import { chatService } from "@/server/service/chat" ;
55import { type RequestContext , localUserId } from "@/server/service/context" ;
66import { settingsService } from "@/server/service/settings" ;
7+ import { useMemo } from "react" ;
78import useSWR from "swr" ;
89import type { SWRResponse } from "swr" ;
910import useSWRMutation from "swr/mutation" ;
@@ -17,7 +18,7 @@ type ExtractPromiseType<T> = T extends Promise<infer U> ? U : T;
1718// Remove the last parameter (userId) from function parameters
1819type RemoveLastParam < T extends readonly unknown [ ] > = T extends readonly [ ...infer Rest , any ] ? Rest : T ;
1920
20- // Transform function type to remove last parameter
21+ // Transform function type to remove last parameter and preserve exact return type
2122type TransformFunction < T > = T extends ( ...args : infer P ) => infer R ? ( ...args : RemoveLastParam < P > ) => R : T ;
2223
2324// Helper type to determine the correct argument type for SWR mutation
@@ -77,6 +78,7 @@ function createEnhancedService<T>(baseService: T): EnhancedService<T> {
7778 // Add SWR method - create a fetcher that calls the original method
7879 enhancedMethod . swr = ( key : string | null , ...args : any [ ] ) => {
7980 const fetcher = async ( ) => {
81+ console . log ( "SWR fetcher called with args:" , args ) ;
8082 // Add localUserId as the last parameter
8183 return await originalMethod . call ( target , ...args , requestContext ) ;
8284 } ;
@@ -126,10 +128,16 @@ function createEnhancedService<T>(baseService: T): EnhancedService<T> {
126128 */
127129function useService < T extends Record < string , any > > ( defaultService : T , apiService : T ) : EnhancedService < T > {
128130 const { isLogin } = useAuth ( ) ;
129- const service = isLogin ? apiService : defaultService ;
130131
131- // Return enhanced service (auth loading is guaranteed to be complete at root level)
132- return createEnhancedService ( service ) ;
132+ // Memoize service selection to prevent unnecessary re-computations
133+ const service = useMemo ( ( ) => {
134+ return isLogin ? apiService : defaultService ;
135+ } , [ isLogin , apiService , defaultService ] ) ;
136+
137+ // Memoize enhanced service creation
138+ return useMemo ( ( ) => {
139+ return createEnhancedService ( service ) ;
140+ } , [ service ] ) ;
133141}
134142
135143/**
@@ -158,12 +166,16 @@ async function doRequest<T>(apiCall: (...args: any[]) => Promise<Response>, ...a
158166 }
159167}
160168
161- /**
162- * Generic service proxy that automatically maps interface methods to API calls
163- * Dynamically resolves endpoints based on method names
164- */
165- function createApiServiceProxy < T extends object > ( apiEndpoints : Record < string , any > ) : T {
166- return new Proxy ( { } as T , {
169+ // Service proxy cache to avoid recreating proxies
170+ const apiServiceCache = new WeakMap < Record < string , any > , any > ( ) ;
171+
172+ function createApiServiceProxy < T extends Record < string , any > > ( apiEndpoints : Record < string , any > ) : T {
173+ // Check cache first
174+ if ( apiServiceCache . has ( apiEndpoints ) ) {
175+ return apiServiceCache . get ( apiEndpoints ) ;
176+ }
177+
178+ const proxy = new Proxy ( { } as T , {
167179 get ( target , prop : string | symbol ) {
168180 if ( typeof prop === "string" ) {
169181 // Look for a property with $post method
@@ -179,16 +191,23 @@ function createApiServiceProxy<T extends object>(apiEndpoints: Record<string, an
179191 return undefined ;
180192 } ,
181193 } ) ;
194+
195+ // Cache the proxy
196+ apiServiceCache . set ( apiEndpoints , proxy ) ;
197+ return proxy ;
182198}
183199
184200export function useChatService ( ) {
185- return useService ( chatService , createApiServiceProxy ( apiClient . api . chats ) ) ;
201+ const apiService = useMemo ( ( ) => createApiServiceProxy < typeof chatService > ( apiClient . api . chats ) , [ ] ) ;
202+ return useService ( chatService , apiService ) ;
186203}
187204
188205export function useSettingsService ( ) {
189- return useService ( settingsService , createApiServiceProxy ( apiClient . api . settings ) ) ;
206+ const apiService = useMemo ( ( ) => createApiServiceProxy < typeof settingsService > ( apiClient . api . settings ) , [ ] ) ;
207+ return useService ( settingsService , apiService ) ;
190208}
191209
192210export function useAiService ( ) {
193- return useService ( aiService , createApiServiceProxy ( apiClient . api . ai ) ) ;
211+ const apiService = useMemo ( ( ) => createApiServiceProxy < typeof aiService > ( apiClient . api . ai ) , [ ] ) ;
212+ return useService ( aiService , apiService ) ;
194213}
0 commit comments