@@ -27,50 +27,57 @@ export abstract class XHRUploadClient extends AbstractModrinthClient {
2727
2828 const url = this . buildUrl ( path , baseUrl , options . version )
2929
30- // For FormData uploads, don't set Content-Type (let browser set multipart boundary)
31- // For file uploads, use application/octet-stream
32- const isFormData = 'formData' in options && options . formData instanceof FormData
33- const baseHeaders = this . buildDefaultHeaders ( )
34- // Remove Content-Type for FormData so browser can set multipart/form-data with boundary
35- if ( isFormData ) {
36- delete baseHeaders [ 'Content-Type' ]
37- } else {
38- baseHeaders [ 'Content-Type' ] = 'application/octet-stream'
39- }
40-
41- const mergedOptions : UploadRequestOptions = {
42- retry : false , // default: don't retry uploads
43- ...options ,
44- headers : {
45- ...baseHeaders ,
46- ...options . headers ,
47- } ,
48- }
49- this . attachArchonSentryCaptureHeader ( mergedOptions )
50-
51- const context = this . buildUploadContext ( url , path , mergedOptions )
52-
5330 const progressCallbacks : Array < ( p : UploadProgress ) => void > = [ ]
54- if ( mergedOptions . onProgress ) {
55- progressCallbacks . push ( mergedOptions . onProgress )
31+ if ( options . onProgress ) {
32+ progressCallbacks . push ( options . onProgress )
5633 }
5734 const abortController = new AbortController ( )
5835
59- if ( mergedOptions . signal ) {
60- mergedOptions . signal . addEventListener ( 'abort' , ( ) => abortController . abort ( ) )
36+ if ( options . signal ) {
37+ options . signal . addEventListener ( 'abort' , ( ) => abortController . abort ( ) )
6138 }
6239
40+ let context : RequestContext | undefined
6341 const handle : UploadHandle < T > = {
64- promise : this . executeUploadFeatureChain < T > ( context , progressCallbacks , abortController )
65- . then ( async ( result ) => {
66- await this . config . hooks ?. onResponse ?.( result , context )
67- return result
68- } )
69- . catch ( async ( error ) => {
70- const apiError = this . normalizeError ( error , context )
42+ promise : ( async ( ) => {
43+ const isFormData = 'formData' in options && options . formData instanceof FormData
44+ const baseHeaders = await this . buildDefaultHeaders ( )
45+ if ( isFormData ) {
46+ delete baseHeaders [ 'Content-Type' ]
47+ } else {
48+ baseHeaders [ 'Content-Type' ] = 'application/octet-stream'
49+ }
50+
51+ const mergedOptions : UploadRequestOptions = {
52+ retry : false ,
53+ ...options ,
54+ headers : {
55+ ...baseHeaders ,
56+ ...options . headers ,
57+ } ,
58+ }
59+ this . attachArchonSentryCaptureHeader ( mergedOptions )
60+
61+ const uploadContext = this . buildUploadContext ( url , path , mergedOptions )
62+ context = uploadContext
63+ if ( abortController . signal . aborted ) {
64+ throw new ModrinthApiError ( 'Upload cancelled' )
65+ }
66+
67+ const result = await this . executeUploadFeatureChain < T > (
68+ uploadContext ,
69+ progressCallbacks ,
70+ abortController ,
71+ )
72+ await this . config . hooks ?. onResponse ?.( result , uploadContext )
73+ return result
74+ } ) ( ) . catch ( async ( error ) => {
75+ const apiError = this . normalizeError ( error , context )
76+ if ( context ) {
7177 await this . config . hooks ?. onError ?.( apiError , context )
72- throw apiError
73- } ) ,
78+ }
79+ throw apiError
80+ } ) ,
7481 onProgress : ( callback ) => {
7582 progressCallbacks . push ( callback )
7683 return handle
0 commit comments