@@ -400,64 +400,64 @@ export default class Transloadit<
400
400
return newFile
401
401
}
402
402
403
- #createAssembly(
403
+ async #createAssembly(
404
404
fileIDs : string [ ] ,
405
405
assemblyOptions : OptionsWithRestructuredFields ,
406
406
) {
407
407
this . uppy . log ( '[Transloadit] Create Assembly' )
408
408
409
- return this . client
410
- . createAssembly ( {
409
+ try {
410
+ const newAssembly = await this . client . createAssembly ( {
411
411
...assemblyOptions ,
412
412
expectedFiles : fileIDs . length ,
413
413
} )
414
- . then ( async ( newAssembly ) => {
415
- const files = this . uppy
416
- . getFiles ( )
417
- . filter ( ( { id } ) => fileIDs . includes ( id ) )
418
- if ( files . length === 0 ) {
419
- // All files have been removed, cancelling.
420
- await this . client . cancelAssembly ( newAssembly )
421
- return null
422
- }
423
-
424
- const assembly = new Assembly ( newAssembly , this . #rateLimitedQueue)
425
- const { status } = assembly
426
- const assemblyID = status . assembly_id
427
414
428
- const updatedFiles : Record < string , UppyFile < M , B > > = { }
429
- files . forEach ( ( file ) => {
430
- updatedFiles [ file . id ] = this . #attachAssemblyMetadata( file , status )
431
- } )
415
+ const files = this . uppy
416
+ . getFiles ( )
417
+ . filter ( ( { id } ) => fileIDs . includes ( id ) )
432
418
433
- this . uppy . setState ( {
434
- files : {
435
- ...this . uppy . getState ( ) . files ,
436
- ...updatedFiles ,
437
- } ,
438
- } )
419
+ if ( files . length === 0 ) {
420
+ // All files have been removed, cancelling.
421
+ await this . client . cancelAssembly ( newAssembly )
422
+ return null
423
+ }
439
424
440
- this . uppy . emit ( 'transloadit:assembly-created' , status , fileIDs )
425
+ const assembly = new Assembly ( newAssembly , this . #rateLimitedQueue)
426
+ const { status } = assembly
427
+ const assemblyID = status . assembly_id
441
428
442
- this . uppy . log ( `[Transloadit] Created Assembly ${ assemblyID } ` )
443
- return assembly
429
+ const updatedFiles : Record < string , UppyFile < M , B > > = { }
430
+ files . forEach ( ( file ) => {
431
+ updatedFiles [ file . id ] = this . #attachAssemblyMetadata( file , status )
444
432
} )
445
- . catch ( ( err ) => {
446
- // TODO: use AssemblyError?
447
- const wrapped = new ErrorWithCause (
448
- `${ this . i18n ( 'creatingAssemblyFailed' ) } : ${ err . message } ` ,
449
- { cause : err } ,
450
- )
451
- if ( 'details' in err ) {
452
- // @ts -expect-error details is not in the Error type
453
- wrapped . details = err . details
454
- }
455
- if ( 'assembly' in err ) {
456
- // @ts -expect-error assembly is not in the Error type
457
- wrapped . assembly = err . assembly
458
- }
459
- throw wrapped
433
+
434
+ this . uppy . setState ( {
435
+ files : {
436
+ ...this . uppy . getState ( ) . files ,
437
+ ...updatedFiles ,
438
+ } ,
460
439
} )
440
+
441
+ this . uppy . emit ( 'transloadit:assembly-created' , status , fileIDs )
442
+
443
+ this . uppy . log ( `[Transloadit] Created Assembly ${ assemblyID } ` )
444
+ return assembly
445
+ } catch ( err ) {
446
+ // TODO: use AssemblyError?
447
+ const wrapped = new ErrorWithCause (
448
+ `${ this . i18n ( 'creatingAssemblyFailed' ) } : ${ err . message } ` ,
449
+ { cause : err } ,
450
+ )
451
+ if ( 'details' in err ) {
452
+ // @ts -expect-error details is not in the Error type
453
+ wrapped . details = err . details
454
+ }
455
+ if ( 'assembly' in err ) {
456
+ // @ts -expect-error assembly is not in the Error type
457
+ wrapped . assembly = err . assembly
458
+ }
459
+ throw wrapped
460
+ }
461
461
}
462
462
463
463
#createAssemblyWatcher( idOrArrayOfIds : string | string [ ] ) {
@@ -616,6 +616,7 @@ export default class Transloadit<
616
616
await this . client . cancelAssembly ( assembly )
617
617
// TODO bubble this through AssemblyWatcher so its event handlers can clean up correctly
618
618
this . uppy . emit ( 'transloadit:assembly-cancelled' , assembly )
619
+ this . assembly = undefined
619
620
}
620
621
621
622
/**
@@ -702,20 +703,21 @@ export default class Transloadit<
702
703
this . #connectAssembly( this . assembly ! )
703
704
}
704
705
705
- // Force-update all Assemblies to check for missed events.
706
- const updateAssemblies = ( ) => {
706
+ // Force-update Assembly to check for missed events.
707
+ const updateAssembly = ( ) => {
707
708
return this . assembly ?. update ( )
708
709
}
709
710
710
711
// Restore all Assembly state.
711
- this . restored = Promise . resolve ( ) . then ( ( ) => {
712
+ this . restored = ( async ( ) => {
712
713
restoreState ( )
713
714
restoreAssemblies ( )
714
- updateAssemblies ( )
715
- } )
716
-
717
- this . restored . then ( ( ) => {
715
+ await updateAssembly ( )
718
716
this . restored = null
717
+ } ) ( )
718
+
719
+ this . restored . catch ( ( err ) => {
720
+ this . uppy . log ( 'Failed to restore' , err )
719
721
} )
720
722
}
721
723
@@ -800,8 +802,11 @@ export default class Transloadit<
800
802
try {
801
803
const assembly =
802
804
// this.assembly can already be defined if we recovered files with Golden Retriever (this.#onRestored)
803
- ( this . assembly ??
804
- ( await this . #createAssembly( fileIDs , assemblyOptions ) ) ) !
805
+ this . assembly ?? ( await this . #createAssembly( fileIDs , assemblyOptions ) )
806
+
807
+ if ( assembly == null )
808
+ throw new Error ( 'All files were canceled after assembly was created' )
809
+
805
810
if ( this . opts . importFromUploadURLs ) {
806
811
await this . #reserveFiles( assembly , fileIDs )
807
812
}
@@ -823,65 +828,67 @@ export default class Transloadit<
823
828
}
824
829
}
825
830
826
- #afterUpload = ( fileIDs : string [ ] , uploadID : string ) : Promise < void > => {
827
- const files = fileIDs . map ( ( fileID ) => this . uppy . getFile ( fileID ) )
828
- // Only use files without errors
829
- const filteredFileIDs = files
830
- . filter ( ( file ) => ! file . error )
831
- . map ( ( file ) => file . id )
831
+ #afterUpload = async ( fileIDs : string [ ] , uploadID : string ) : Promise < void > => {
832
+ try {
833
+ // If we're still restoring state, wait for that to be done.
834
+ await this . restored
832
835
833
- // If we're still restoring state, wait for that to be done.
834
- if ( this . restored ) {
835
- return this . restored . then ( ( ) => {
836
- return this . #afterUpload( filteredFileIDs , uploadID )
837
- } )
838
- }
836
+ const files = fileIDs
837
+ . map ( ( fileID ) => this . uppy . getFile ( fileID ) )
838
+ // Only use files without errors
839
+ . filter ( ( file ) => ! file . error )
839
840
840
- const assemblyID = this . assembly ?. status . assembly_id
841
+ const assemblyID = this . assembly ?. status . assembly_id
841
842
842
- const closeSocketConnections = ( ) => {
843
- this . assembly ?. close ( )
844
- }
843
+ const closeSocketConnections = ( ) => {
844
+ this . assembly ?. close ( )
845
+ }
845
846
846
- // If we don't have to wait for encoding metadata or results, we can close
847
- // the socket immediately and finish the upload.
848
- if ( ! this . #shouldWaitAfterUpload( ) ) {
849
- closeSocketConnections ( )
850
- const status = this . assembly ?. status
851
- if ( status != null ) {
852
- this . uppy . addResultData ( uploadID , {
853
- transloadit : [ status ] ,
854
- } )
847
+ // If we don't have to wait for encoding metadata or results, we can close
848
+ // the socket immediately and finish the upload.
849
+ if ( ! this . #shouldWaitAfterUpload( ) ) {
850
+ closeSocketConnections ( )
851
+ const status = this . assembly ?. status
852
+ if ( status != null ) {
853
+ this . uppy . addResultData ( uploadID , {
854
+ transloadit : [ status ] ,
855
+ } )
856
+ }
857
+ return
855
858
}
856
- return Promise . resolve ( )
857
- }
858
859
859
- // If no Assemblies were created for this upload, we also do not have to wait.
860
- // There's also no sockets or anything to close, so just return immediately.
861
- if ( ! assemblyID ) {
862
- this . uppy . addResultData ( uploadID , { transloadit : [ ] } )
863
- return Promise . resolve ( )
864
- }
860
+ // If no Assemblies were created for this upload, we also do not have to wait.
861
+ // There's also no sockets or anything to close, so just return immediately.
862
+ if ( ! assemblyID ) {
863
+ this . uppy . addResultData ( uploadID , { transloadit : [ ] } )
864
+ return
865
+ }
865
866
866
- const incompleteFiles = files . filter (
867
- ( file ) => ! hasProperty ( this . completedFiles , file . id ) ,
868
- )
869
- incompleteFiles . forEach ( ( file ) => {
870
- this . uppy . emit ( 'postprocess-progress' , file , {
871
- mode : 'indeterminate' ,
872
- message : this . i18n ( 'encoding' ) ,
867
+ const incompleteFiles = files . filter (
868
+ ( file ) => ! hasProperty ( this . completedFiles , file . id ) ,
869
+ )
870
+ incompleteFiles . forEach ( ( file ) => {
871
+ this . uppy . emit ( 'postprocess-progress' , file , {
872
+ mode : 'indeterminate' ,
873
+ message : this . i18n ( 'encoding' ) ,
874
+ } )
873
875
} )
874
- } )
875
876
876
- return this . #watcher. promise . then ( ( ) => {
877
+ await this . #watcher. promise
878
+ // assembly is now done processing!
877
879
closeSocketConnections ( )
878
880
const status = this . assembly ?. status
879
881
if ( status != null ) {
880
882
this . uppy . addResultData ( uploadID , {
881
883
transloadit : [ status ] ,
882
884
} )
883
885
}
884
- } )
886
+ } finally {
887
+ // in case allowMultipleUploadBatches is true and the user wants to upload again,
888
+ // we need to allow a new assembly to be created.
889
+ // see https://github.com/transloadit/uppy/issues/5397
890
+ this . assembly = undefined
891
+ }
885
892
}
886
893
887
894
#closeAssemblyIfExists = ( ) => {
0 commit comments