@@ -228,25 +228,39 @@ const encodePath = (item: string): string => {
228228 * @param options - Optional fetch options, automatically extended with common headers and credentials.
229229 * @returns The fetch Response promise.
230230 */
231- const request = ( url : string , options : RequestInit = { } ) : Promise < Response > => {
232- options . method = options . method || 'GET'
233- options . headers = options . headers || { } ; ( options as any ) . withCredentials = true
231+ const request = ( url : string , options : RequestInit & { timeout ?: number } = { } ) : Promise < Response > => {
232+ const { timeout, ...fetchOptions } = options
234233
235- if ( undefined === ( options . headers as Record < string , any > ) [ 'Content-Type' ] ) {
234+ fetchOptions . method = fetchOptions . method || 'GET'
235+ fetchOptions . headers = fetchOptions . headers || { } ;
236+ ( fetchOptions as any ) . withCredentials = true
237+
238+ if ( undefined === ( fetchOptions . headers as Record < string , any > ) [ 'Content-Type' ] ) {
236239 if ( ! ( options ?. body instanceof FormData ) ) {
237- ; ( options . headers as Record < string , any > ) [ 'Content-Type' ] = 'application/json'
240+ ; ( fetchOptions . headers as Record < string , any > ) [ 'Content-Type' ] = 'application/json'
238241 }
239242 }
240243
241- if ( undefined === ( options . headers as Record < string , any > ) [ 'Accept' ] ) {
242- ; ( options . headers as Record < string , any > ) [ 'Accept' ] = 'application/json'
244+ if ( undefined === ( fetchOptions . headers as Record < string , any > ) [ 'Accept' ] ) {
245+ ; ( fetchOptions . headers as Record < string , any > ) [ 'Accept' ] = 'application/json'
243246 }
244247
245248 if ( url . startsWith ( '/' ) ) {
246- options . credentials = 'same-origin'
249+ fetchOptions . credentials = 'same-origin'
247250 }
248251
249- return fetch ( url . startsWith ( '/' ) ? uri ( url ) : url , options )
252+ let controller : AbortController | undefined
253+ let timer : ReturnType < typeof setTimeout > | undefined
254+
255+ if ( typeof timeout === 'number' && timeout > 0 ) {
256+ controller = new AbortController ( )
257+ fetchOptions . signal = controller . signal
258+ timer = setTimeout ( ( ) => controller ! . abort ( `Request timed out.` ) , timeout * 1000 )
259+ }
260+
261+ return fetch ( url . startsWith ( '/' ) ? uri ( url ) : url , fetchOptions ) . finally ( ( ) => {
262+ if ( timer ) { clearTimeout ( timer ) }
263+ } )
250264}
251265
252266/**
@@ -879,10 +893,10 @@ const parse_api_error = async (json: unknown): Promise<string> => {
879893 }
880894
881895 if ( payload . error ) {
882- return String ( payload . error + ( extra_detail ? ` - ${ extra_detail } ` : '' ) )
896+ return String ( payload . error + ( extra_detail ? ` - ${ extra_detail } ` : '' ) )
883897 }
884898 if ( payload . message ) {
885- return String ( payload . message + ( extra_detail ? ` - ${ extra_detail } ` : '' ) )
899+ return String ( payload . message + ( extra_detail ? ` - ${ extra_detail } ` : '' ) )
886900 }
887901
888902 if ( extra_detail ) {
0 commit comments