@@ -64,54 +64,105 @@ type V6CompatibleVersion = '6' | '7';
64
64
const allRoutes = new Set < RouteObject > ( ) ;
65
65
66
66
/**
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 .
68
68
*/
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 ) ;
111
91
}
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 ) ;
112
154
}
113
155
}
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
115
166
if ( Array . isArray ( route . children ) ) {
116
167
for ( const child of route . children ) {
117
168
checkRouteForAsyncHandler ( child ) ;
0 commit comments