@@ -64,54 +64,105 @@ type V6CompatibleVersion = '6' | '7';
6464const allRoutes = new Set < RouteObject > ( ) ;
6565
6666/**
67- * Recursively checks a route for async handlers and sets up Proxies to add discovered child routes to allRoutes when called .
67+ * Handles the result of an async handler function call .
6868 */
69- export function checkRouteForAsyncHandler ( route : RouteObject ) : void {
70- // If the route has a handle, set up proxies for any functions on it
71- if ( route . handle && typeof route . handle === 'object' ) {
72- for ( const key of Object . keys ( route . handle ) ) {
73- const maybeFn = route . handle [ key ] ;
74- if ( typeof maybeFn === 'function' ) {
75- // Create a proxy that intercepts function calls
76- route . handle [ key ] = new Proxy ( maybeFn , {
77- apply ( target , thisArg , argArray ) {
78- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
79- const result = target . apply ( thisArg , argArray ) ;
80- // If the result is a promise, handle it when resolved
81- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
82- if ( result && typeof result . then === 'function' ) {
83- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
84- result
85- . then ( ( resolvedRoutes : unknown ) => {
86- if ( Array . isArray ( resolvedRoutes ) ) {
87- // Add resolved routes as children to maintain proper route tree structure
88- route . children = resolvedRoutes ;
89- // Add discovered children to allRoutes
90- resolvedRoutes . forEach ( child => {
91- allRoutes . add ( child ) ;
92- // Recursively check for async handlers in child routes
93- checkRouteForAsyncHandler ( child ) ;
94- } ) ;
95- }
96- } )
97- . catch ( ( e : unknown ) => {
98- DEBUG_BUILD && debug . warn ( `Error resolving async handler '${ key } ' for route` , route , e ) ;
99- } ) ;
100- } else if ( Array . isArray ( result ) ) {
101- // Handle synchronous array results - add as children to maintain route tree structure
102- route . children = result ;
103- result . forEach ( child => {
104- allRoutes . add ( child ) ;
105- checkRouteForAsyncHandler ( child ) ;
106- } ) ;
107- }
108- return result ;
109- } ,
110- } ) ;
69+ function handleAsyncHandlerResult ( result : unknown , route : RouteObject , handlerKey : string ) : void {
70+ if (
71+ result &&
72+ typeof result === 'object' &&
73+ 'then' in result &&
74+ typeof ( result as Promise < unknown > ) . then === 'function'
75+ ) {
76+ handlePromiseResult ( result as Promise < unknown > , route , handlerKey ) ;
77+ } else if ( Array . isArray ( result ) ) {
78+ handleSynchronousArrayResult ( result , route ) ;
79+ }
80+ }
81+
82+ /**
83+ * Handles promise results from async handlers.
84+ */
85+ function handlePromiseResult ( promise : Promise < unknown > , route : RouteObject , handlerKey : string ) : void {
86+ promise
87+ . then ( ( resolvedRoutes : unknown ) => {
88+ if ( Array . isArray ( resolvedRoutes ) ) {
89+ addResolvedRoutesToParent ( resolvedRoutes , route ) ;
90+ processResolvedRoutes ( resolvedRoutes ) ;
11191 }
92+ } )
93+ . catch ( ( e : unknown ) => {
94+ DEBUG_BUILD && debug . warn ( `Error resolving async handler '${ handlerKey } ' for route` , route , e ) ;
95+ } ) ;
96+ }
97+
98+ /**
99+ * Handles synchronous array results from handlers.
100+ */
101+ function handleSynchronousArrayResult ( result : RouteObject [ ] , route : RouteObject ) : void {
102+ addResolvedRoutesToParent ( result , route ) ;
103+ processResolvedRoutes ( result ) ;
104+ }
105+
106+ /**
107+ * Adds resolved routes as children to the parent route.
108+ */
109+ function addResolvedRoutesToParent ( resolvedRoutes : RouteObject [ ] , parentRoute : RouteObject ) : void {
110+ parentRoute . children = Array . isArray ( parentRoute . children )
111+ ? [ ...parentRoute . children , ...resolvedRoutes ]
112+ : resolvedRoutes ;
113+ }
114+
115+ /**
116+ * Processes resolved routes by adding them to allRoutes and checking for nested async handlers.
117+ */
118+ function processResolvedRoutes ( resolvedRoutes : RouteObject [ ] ) : void {
119+ resolvedRoutes . forEach ( child => {
120+ allRoutes . add ( child ) ;
121+ checkRouteForAsyncHandler ( child ) ;
122+ } ) ;
123+ }
124+
125+ /**
126+ * Creates a proxy wrapper for an async handler function.
127+ */
128+ function createAsyncHandlerProxy (
129+ originalFunction : ( ...args : unknown [ ] ) => unknown ,
130+ route : RouteObject ,
131+ handlerKey : string ,
132+ ) : ( ...args : unknown [ ] ) => unknown {
133+ return new Proxy ( originalFunction , {
134+ apply ( target : ( ...args : unknown [ ] ) => unknown , thisArg , argArray ) {
135+ const result = target . apply ( thisArg , argArray ) ;
136+ handleAsyncHandlerResult ( result , route , handlerKey ) ;
137+ return result ;
138+ } ,
139+ } ) ;
140+ }
141+
142+ /**
143+ * Sets up proxies for all function properties in a route's handle object.
144+ */
145+ function setupHandleProxies ( route : RouteObject ) : void {
146+ if ( ! route . handle || typeof route . handle !== 'object' ) {
147+ return ;
148+ }
149+
150+ for ( const key of Object . keys ( route . handle ) ) {
151+ const maybeFn = route . handle [ key ] ;
152+ if ( typeof maybeFn === 'function' ) {
153+ route . handle [ key ] = createAsyncHandlerProxy ( maybeFn , route , key ) ;
112154 }
113155 }
114- // If the route has children, check them recursively
156+ }
157+
158+ /**
159+ * Recursively checks a route for async handlers and sets up Proxies to add discovered child routes to allRoutes when called.
160+ */
161+ export function checkRouteForAsyncHandler ( route : RouteObject ) : void {
162+ // Set up proxies for any functions in the route's handle
163+ setupHandleProxies ( route ) ;
164+
165+ // Recursively check child routes
115166 if ( Array . isArray ( route . children ) ) {
116167 for ( const child of route . children ) {
117168 checkRouteForAsyncHandler ( child ) ;
0 commit comments