@@ -3,11 +3,17 @@ import { client as authClient } from "./generated/auth/client.gen.js";
33import { client as pathClient } from "./generated/path/client.gen.js" ;
44
55let interceptorsRegistered = false ;
6+ let refreshFn : ( ( ) => Promise < boolean > ) | undefined ;
7+ let authFn : ( ( ) => Promise < string | undefined > ) | undefined ;
68
79export function configureClients ( options : {
810 baseUrl : string ;
911 auth : ( ) => Promise < string | undefined > ;
12+ onRefreshToken ?: ( ) => Promise < boolean > ;
1013} ) : void {
14+ authFn = options . auth ;
15+ refreshFn = options . onRefreshToken ;
16+
1117 for ( const client of [ authClient , pathClient ] ) {
1218 client . setConfig ( {
1319 baseUrl : options . baseUrl ,
@@ -19,7 +25,23 @@ export function configureClients(options: {
1925 interceptorsRegistered = true ;
2026
2127 for ( const client of [ authClient , pathClient ] ) {
22- client . interceptors . response . use ( async ( response ) => {
28+ // Interceptor signature: (response, request, opts) => response
29+ client . interceptors . response . use ( async ( response : Response , request : Request ) => {
30+ // 401 retry with token refresh
31+ if ( response . status === 401 && refreshFn ) {
32+ const refreshed = await refreshFn ( ) ;
33+ if ( refreshed && authFn ) {
34+ const newToken = await authFn ( ) ;
35+ if ( newToken ) {
36+ const retryRequest = new Request ( request , {
37+ headers : new Headers ( request . headers ) ,
38+ } ) ;
39+ retryRequest . headers . set ( "Authorization" , `Bearer ${ newToken } ` ) ;
40+ return fetch ( retryRequest ) ;
41+ }
42+ }
43+ }
44+
2345 if ( ! response . ok ) {
2446 const contentType = response . headers . get ( "content-type" ) ;
2547 if ( contentType ?. includes ( "application/json" ) ) {
0 commit comments