@@ -13,6 +13,8 @@ import {
1313 Request ,
1414 _TypedFetch ,
1515 TypedFetch ,
16+ ContentTypeDiscriminator ,
17+ BlobTypeSelector ,
1618} from './types'
1719
1820const sendBody = ( method : Method ) =>
@@ -134,13 +136,18 @@ function getFetchParams(request: Request) {
134136 return { url, init }
135137}
136138
137- async function getResponseData ( response : Response ) {
139+ async function getResponseData ( response : Response , isBlob : BlobTypeSelector ) {
138140 const contentType = response . headers . get ( 'content-type' )
139141 if ( response . status === 204 /* no content */ ) {
140142 return undefined
141143 }
142- if ( contentType && contentType . indexOf ( 'application/json' ) !== - 1 ) {
143- return response . json ( )
144+ if ( contentType ) {
145+ if ( isBlob ( contentType ) ) {
146+ return response . blob ( )
147+ }
148+ if ( contentType . includes ( 'application/json' ) ) {
149+ return response . json ( )
150+ }
144151 }
145152 const text = await response . text ( )
146153 try {
@@ -150,25 +157,32 @@ async function getResponseData(response: Response) {
150157 }
151158}
152159
153- async function fetchJson ( url : string , init : RequestInit ) : Promise < ApiResponse > {
154- const response = await fetch ( url , init )
155-
156- const data = await getResponseData ( response )
160+ function getFetchResponse ( blobTypeSelector : BlobTypeSelector ) {
161+ async function fetchResponse (
162+ url : string ,
163+ init : RequestInit ,
164+ ) : Promise < ApiResponse > {
165+ const response = await fetch ( url , init )
166+
167+ const data = await getResponseData ( response , blobTypeSelector )
168+
169+ const result = {
170+ headers : response . headers ,
171+ url : response . url ,
172+ ok : response . ok ,
173+ status : response . status ,
174+ statusText : response . statusText ,
175+ data,
176+ }
157177
158- const result = {
159- headers : response . headers ,
160- url : response . url ,
161- ok : response . ok ,
162- status : response . status ,
163- statusText : response . statusText ,
164- data,
165- }
178+ if ( result . ok ) {
179+ return result
180+ }
166181
167- if ( result . ok ) {
168- return result
182+ throw new ApiError ( result )
169183 }
170184
171- throw new ApiError ( result )
185+ return fetchResponse
172186}
173187
174188function wrapMiddlewares ( middlewares : Middleware [ ] , fetch : Fetch ) : Fetch {
@@ -227,24 +241,47 @@ function createFetch<OP>(fetch: _TypedFetch<OP>): TypedFetch<OP> {
227241 return fun
228242}
229243
244+ function getBlobTypeSelector ( discriminator ?: ContentTypeDiscriminator ) {
245+ if ( ! discriminator ) {
246+ return ( ) => false
247+ }
248+ if ( typeof discriminator === 'function' ) {
249+ return discriminator
250+ }
251+ let arrayDiscriminator = discriminator
252+ if ( ! Array . isArray ( discriminator ) ) {
253+ arrayDiscriminator = [ discriminator ]
254+ }
255+ const arrayOfRegExp = ( arrayDiscriminator as Array < string | RegExp > ) . map (
256+ ( expr ) => ( expr instanceof RegExp ? expr : new RegExp ( `^.*${ expr } .*$` ) ) ,
257+ )
258+ return ( contentType : string ) =>
259+ Boolean ( arrayOfRegExp . find ( ( expr ) => expr . test ( contentType ) ) )
260+ }
261+
230262function fetcher < Paths > ( ) {
231263 let baseUrl = ''
232264 let defaultInit : RequestInit = { }
233265 const middlewares : Middleware [ ] = [ ]
234- const fetch = wrapMiddlewares ( middlewares , fetchJson )
266+ let blobTypeSelector : BlobTypeSelector = ( ) => false
235267
236268 return {
237269 configure : ( config : FetchConfig ) => {
238270 baseUrl = config . baseUrl || ''
239271 defaultInit = config . init || { }
240272 middlewares . splice ( 0 )
241273 middlewares . push ( ...( config . use || [ ] ) )
274+ blobTypeSelector = getBlobTypeSelector ( config . asBlob )
242275 } ,
243276 use : ( mw : Middleware ) => middlewares . push ( mw ) ,
244277 path : < P extends keyof Paths > ( path : P ) => ( {
245278 method : < M extends keyof Paths [ P ] > ( method : M ) => ( {
246- create : ( ( queryParams ?: Record < string , true | 1 > ) =>
247- createFetch ( ( payload , init ) =>
279+ create : ( ( queryParams ?: Record < string , true | 1 > ) => {
280+ const fetch = wrapMiddlewares (
281+ middlewares ,
282+ getFetchResponse ( blobTypeSelector ) ,
283+ )
284+ return createFetch ( ( payload , init ) =>
248285 fetchUrl ( {
249286 baseUrl : baseUrl || '' ,
250287 path : path as string ,
@@ -254,7 +291,8 @@ function fetcher<Paths>() {
254291 init : mergeRequestInit ( defaultInit , init ) ,
255292 fetch,
256293 } ) ,
257- ) ) as CreateFetch < M , Paths [ P ] [ M ] > ,
294+ )
295+ } ) as CreateFetch < M , Paths [ P ] [ M ] > ,
258296 } ) ,
259297 } ) ,
260298 }
0 commit comments