filemail-sdk 9.4.10 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/dist/src/client/downloader/downloaderCore.js +1 -1
  2. package/dist/src/client/downloader/downloaderCore.js.map +1 -1
  3. package/dist/src/client/uploader/node/nodeTransferUploader.d.ts.map +1 -1
  4. package/dist/src/client/uploader/node/nodeTransferUploader.js +6 -5
  5. package/dist/src/client/uploader/node/nodeTransferUploader.js.map +1 -1
  6. package/dist/src/client/uploader/transferUploaderBase.d.ts +1 -0
  7. package/dist/src/client/uploader/transferUploaderBase.d.ts.map +1 -1
  8. package/dist/src/client/uploader/transferUploaderBase.js +23 -28
  9. package/dist/src/client/uploader/transferUploaderBase.js.map +1 -1
  10. package/dist/src/client/uploader/transferUploaderConfig.d.ts +3 -4
  11. package/dist/src/client/uploader/transferUploaderConfig.d.ts.map +1 -1
  12. package/dist/src/client/uploader/transferUploaderConfig.js.map +1 -1
  13. package/dist/src/client/uploader/utils/uploaderUtils.d.ts.map +1 -1
  14. package/dist/src/client/uploader/utils/uploaderUtils.js +1 -2
  15. package/dist/src/client/uploader/utils/uploaderUtils.js.map +1 -1
  16. package/dist/src/client/uploader/web/webTransferUploader.d.ts.map +1 -1
  17. package/dist/src/client/uploader/web/webTransferUploader.js +5 -4
  18. package/dist/src/client/uploader/web/webTransferUploader.js.map +1 -1
  19. package/dist/src/downloader/chunkDownloader.js +2 -2
  20. package/dist/src/downloader/chunkDownloader.js.map +1 -1
  21. package/dist/src/index.d.ts +2 -1
  22. package/dist/src/index.d.ts.map +1 -1
  23. package/dist/src/index.js.map +1 -1
  24. package/dist/src/uploader/api/node/nodeFileServerUploadClient.d.ts +1 -1
  25. package/dist/src/uploader/api/node/nodeFileServerUploadClient.d.ts.map +1 -1
  26. package/dist/src/uploader/api/node/nodeFileServerUploadClient.js +5 -4
  27. package/dist/src/uploader/api/node/nodeFileServerUploadClient.js.map +1 -1
  28. package/dist/src/uploader/api/web/webFileServerUploadClient.d.ts +1 -1
  29. package/dist/src/uploader/api/web/webFileServerUploadClient.d.ts.map +1 -1
  30. package/dist/src/uploader/api/web/webFileServerUploadClient.js +5 -4
  31. package/dist/src/uploader/api/web/webFileServerUploadClient.js.map +1 -1
  32. package/dist/src/uploader/chunksIterator/chunksIterator.d.ts +1 -3
  33. package/dist/src/uploader/chunksIterator/chunksIterator.d.ts.map +1 -1
  34. package/dist/src/uploader/chunksIterator/chunksIterator.js +4 -4
  35. package/dist/src/uploader/chunksIterator/chunksIterator.js.map +1 -1
  36. package/dist/src/uploader/eventArgs/fileAckFailedEventArgs.d.ts +8 -0
  37. package/dist/src/uploader/eventArgs/fileAckFailedEventArgs.d.ts.map +1 -0
  38. package/dist/src/uploader/eventArgs/fileAckFailedEventArgs.js +2 -0
  39. package/dist/src/uploader/eventArgs/fileAckFailedEventArgs.js.map +1 -0
  40. package/dist/src/uploader/eventArgs/fileChunkUploadCompletedEventArgs.d.ts +1 -1
  41. package/dist/src/uploader/eventArgs/fileChunkUploadCompletedEventArgs.d.ts.map +1 -1
  42. package/dist/src/uploader/eventArgs/fileChunkUploadCompletedEventArgs.js.map +1 -1
  43. package/dist/src/uploader/eventArgs/fileChunkUploadEventArgs.d.ts +1 -0
  44. package/dist/src/uploader/eventArgs/fileChunkUploadEventArgs.d.ts.map +1 -1
  45. package/dist/src/uploader/eventArgs/fileChunkUploadEventArgs.js.map +1 -1
  46. package/dist/src/uploader/eventArgs/fileChunkUploadProgressedEventArgs.d.ts +1 -0
  47. package/dist/src/uploader/eventArgs/fileChunkUploadProgressedEventArgs.d.ts.map +1 -1
  48. package/dist/src/uploader/eventArgs/fileChunkUploadProgressedEventArgs.js.map +1 -1
  49. package/dist/src/uploader/eventArgs/fileUploadEventArgs.d.ts +1 -0
  50. package/dist/src/uploader/eventArgs/fileUploadEventArgs.d.ts.map +1 -1
  51. package/dist/src/uploader/eventArgs/fileUploadEventArgs.js.map +1 -1
  52. package/dist/src/uploader/eventArgs/filesBatchAckFailedEventArgs.d.ts +6 -0
  53. package/dist/src/uploader/eventArgs/filesBatchAckFailedEventArgs.d.ts.map +1 -0
  54. package/dist/src/uploader/eventArgs/filesBatchAckFailedEventArgs.js +2 -0
  55. package/dist/src/uploader/eventArgs/filesBatchAckFailedEventArgs.js.map +1 -0
  56. package/dist/src/uploader/export/transferUploadExportData.d.ts +3 -1
  57. package/dist/src/uploader/export/transferUploadExportData.d.ts.map +1 -1
  58. package/dist/src/uploader/export/transferUploadExportData.js.map +1 -1
  59. package/dist/src/uploader/export/transferUploadExportState.d.ts +4 -1
  60. package/dist/src/uploader/export/transferUploadExportState.d.ts.map +1 -1
  61. package/dist/src/uploader/export/transferUploadExportState.js.map +1 -1
  62. package/dist/src/uploader/export/transferUploadMetadata.d.ts +2 -9
  63. package/dist/src/uploader/export/transferUploadMetadata.d.ts.map +1 -1
  64. package/dist/src/uploader/export/transferUploadMetadata.js.map +1 -1
  65. package/dist/src/uploader/options/transferUploadConfig.d.ts +1 -2
  66. package/dist/src/uploader/options/transferUploadConfig.d.ts.map +1 -1
  67. package/dist/src/uploader/options/transferUploadConfig.js.map +1 -1
  68. package/dist/src/uploader/pendingFileAck.d.ts +7 -0
  69. package/dist/src/uploader/pendingFileAck.d.ts.map +1 -0
  70. package/dist/src/uploader/pendingFileAck.js +2 -0
  71. package/dist/src/uploader/pendingFileAck.js.map +1 -0
  72. package/dist/src/uploader/registeredTransferFile.d.ts +6 -0
  73. package/dist/src/uploader/registeredTransferFile.d.ts.map +1 -0
  74. package/dist/src/uploader/registeredTransferFile.js +2 -0
  75. package/dist/src/uploader/registeredTransferFile.js.map +1 -0
  76. package/dist/src/uploader/state/transferUploadState.d.ts +11 -8
  77. package/dist/src/uploader/state/transferUploadState.d.ts.map +1 -1
  78. package/dist/src/uploader/state/transferUploadState.js +54 -26
  79. package/dist/src/uploader/state/transferUploadState.js.map +1 -1
  80. package/dist/src/uploader/state/transferUploadStateFile.d.ts +1 -0
  81. package/dist/src/uploader/state/transferUploadStateFile.d.ts.map +1 -1
  82. package/dist/src/uploader/state/transferUploadStateFile.js +1 -0
  83. package/dist/src/uploader/state/transferUploadStateFile.js.map +1 -1
  84. package/dist/src/uploader/transferUpload.d.ts +17 -14
  85. package/dist/src/uploader/transferUpload.d.ts.map +1 -1
  86. package/dist/src/uploader/transferUpload.js +109 -123
  87. package/dist/src/uploader/transferUpload.js.map +1 -1
  88. package/dist/src/uploader/transferUploadAcker.d.ts +19 -0
  89. package/dist/src/uploader/transferUploadAcker.d.ts.map +1 -0
  90. package/dist/src/uploader/transferUploadAcker.js +119 -0
  91. package/dist/src/uploader/transferUploadAcker.js.map +1 -0
  92. package/dist/src/uploader/transferUploadEvent.d.ts +3 -1
  93. package/dist/src/uploader/transferUploadEvent.d.ts.map +1 -1
  94. package/dist/src/uploader/transferUploadEvent.js +3 -1
  95. package/dist/src/uploader/transferUploadEvent.js.map +1 -1
  96. package/dist/src/utils/api/apiClient.d.ts +6 -0
  97. package/dist/src/utils/api/apiClient.d.ts.map +1 -1
  98. package/dist/src/utils/api/apiClient.js.map +1 -1
  99. package/dist/src/utils/api/apiClientBase.d.ts +0 -2
  100. package/dist/src/utils/api/apiClientBase.d.ts.map +1 -1
  101. package/dist/src/utils/api/apiClientBase.js +6 -13
  102. package/dist/src/utils/api/apiClientBase.js.map +1 -1
  103. package/dist/src/utils/api/dtos/ackTransferFilesRequest.d.ts +9 -0
  104. package/dist/src/utils/api/dtos/ackTransferFilesRequest.d.ts.map +1 -0
  105. package/dist/src/utils/api/dtos/ackTransferFilesRequest.js +2 -0
  106. package/dist/src/utils/api/dtos/ackTransferFilesRequest.js.map +1 -0
  107. package/dist/src/utils/api/dtos/ackTransferFilesResponse.d.ts +7 -0
  108. package/dist/src/utils/api/dtos/ackTransferFilesResponse.d.ts.map +1 -0
  109. package/dist/src/utils/api/dtos/ackTransferFilesResponse.js +2 -0
  110. package/dist/src/utils/api/dtos/ackTransferFilesResponse.js.map +1 -0
  111. package/dist/src/utils/api/dtos/finalizeTransferRequest.d.ts +1 -1
  112. package/dist/src/utils/api/dtos/finalizeTransferRequest.d.ts.map +1 -1
  113. package/dist/src/utils/api/dtos/finalizeTransferRequest.js.map +1 -1
  114. package/dist/src/utils/api/dtos/initializeTransferRequest.d.ts +1 -0
  115. package/dist/src/utils/api/dtos/initializeTransferRequest.d.ts.map +1 -1
  116. package/dist/src/utils/api/dtos/initializeTransferRequest.js.map +1 -1
  117. package/dist/src/utils/api/dtos/initializeTransferResponse.d.ts +0 -9
  118. package/dist/src/utils/api/dtos/initializeTransferResponse.d.ts.map +1 -1
  119. package/dist/src/utils/api/dtos/initializeTransferResponse.js.map +1 -1
  120. package/dist/src/utils/api/dtos/registerTransferFilesRequest.d.ts +18 -0
  121. package/dist/src/utils/api/dtos/registerTransferFilesRequest.d.ts.map +1 -0
  122. package/dist/src/utils/api/dtos/registerTransferFilesRequest.js +2 -0
  123. package/dist/src/utils/api/dtos/registerTransferFilesRequest.js.map +1 -0
  124. package/dist/src/utils/api/dtos/registerTransferFilesResponse.d.ts +9 -0
  125. package/dist/src/utils/api/dtos/registerTransferFilesResponse.d.ts.map +1 -0
  126. package/dist/src/utils/api/dtos/registerTransferFilesResponse.js +2 -0
  127. package/dist/src/utils/api/dtos/registerTransferFilesResponse.js.map +1 -0
  128. package/dist/src/utils/api/fileServerClientFactory.d.ts +2 -4
  129. package/dist/src/utils/api/fileServerClientFactory.d.ts.map +1 -1
  130. package/dist/src/utils/api/fileServerClientFactory.js.map +1 -1
  131. package/dist/src/utils/api/node/nodeApiClient.d.ts +6 -0
  132. package/dist/src/utils/api/node/nodeApiClient.d.ts.map +1 -1
  133. package/dist/src/utils/api/node/nodeApiClient.js +26 -2
  134. package/dist/src/utils/api/node/nodeApiClient.js.map +1 -1
  135. package/dist/src/utils/api/node/nodeFileServerClientFactory.d.ts +2 -4
  136. package/dist/src/utils/api/node/nodeFileServerClientFactory.d.ts.map +1 -1
  137. package/dist/src/utils/api/node/nodeFileServerClientFactory.js +3 -7
  138. package/dist/src/utils/api/node/nodeFileServerClientFactory.js.map +1 -1
  139. package/dist/src/utils/api/web/webApiClient.d.ts +6 -0
  140. package/dist/src/utils/api/web/webApiClient.d.ts.map +1 -1
  141. package/dist/src/utils/api/web/webApiClient.js +24 -2
  142. package/dist/src/utils/api/web/webApiClient.js.map +1 -1
  143. package/dist/src/utils/api/web/webFileServerClientFactory.d.ts +2 -4
  144. package/dist/src/utils/api/web/webFileServerClientFactory.d.ts.map +1 -1
  145. package/dist/src/utils/api/web/webFileServerClientFactory.js +3 -6
  146. package/dist/src/utils/api/web/webFileServerClientFactory.js.map +1 -1
  147. package/package.json +1 -2
  148. package/dist/src/uploader/api/dtos/handshakeRequest.d.ts +0 -6
  149. package/dist/src/uploader/api/dtos/handshakeRequest.d.ts.map +0 -1
  150. package/dist/src/uploader/api/dtos/handshakeRequest.js +0 -2
  151. package/dist/src/uploader/api/dtos/handshakeRequest.js.map +0 -1
  152. package/dist/src/uploader/api/dtos/handshakeResponse.d.ts +0 -6
  153. package/dist/src/uploader/api/dtos/handshakeResponse.d.ts.map +0 -1
  154. package/dist/src/uploader/api/dtos/handshakeResponse.js +0 -2
  155. package/dist/src/uploader/api/dtos/handshakeResponse.js.map +0 -1
  156. package/dist/src/uploader/api/dtos/pingResponse.d.ts +0 -5
  157. package/dist/src/uploader/api/dtos/pingResponse.d.ts.map +0 -1
  158. package/dist/src/uploader/api/dtos/pingResponse.js +0 -2
  159. package/dist/src/uploader/api/dtos/pingResponse.js.map +0 -1
  160. package/dist/src/uploader/api/dtos/sendChunkRequest.d.ts +0 -10
  161. package/dist/src/uploader/api/dtos/sendChunkRequest.d.ts.map +0 -1
  162. package/dist/src/uploader/api/dtos/sendChunkRequest.js +0 -2
  163. package/dist/src/uploader/api/dtos/sendChunkRequest.js.map +0 -1
  164. package/dist/src/uploader/api/fileServerUdpClient.d.ts +0 -19
  165. package/dist/src/uploader/api/fileServerUdpClient.d.ts.map +0 -1
  166. package/dist/src/uploader/api/fileServerUdpClient.js +0 -2
  167. package/dist/src/uploader/api/fileServerUdpClient.js.map +0 -1
  168. package/dist/src/uploader/api/node/nodeFileServerUdpClient.d.ts +0 -39
  169. package/dist/src/uploader/api/node/nodeFileServerUdpClient.d.ts.map +0 -1
  170. package/dist/src/uploader/api/node/nodeFileServerUdpClient.js +0 -264
  171. package/dist/src/uploader/api/node/nodeFileServerUdpClient.js.map +0 -1
  172. package/dist/src/uploader/eventArgs/transferUploadModeChosenEventArgs.d.ts +0 -7
  173. package/dist/src/uploader/eventArgs/transferUploadModeChosenEventArgs.d.ts.map +0 -1
  174. package/dist/src/uploader/eventArgs/transferUploadModeChosenEventArgs.js +0 -2
  175. package/dist/src/uploader/eventArgs/transferUploadModeChosenEventArgs.js.map +0 -1
  176. package/dist/src/uploader/optimizer/optimizationValues.d.ts +0 -9
  177. package/dist/src/uploader/optimizer/optimizationValues.d.ts.map +0 -1
  178. package/dist/src/uploader/optimizer/optimizationValues.js +0 -2
  179. package/dist/src/uploader/optimizer/optimizationValues.js.map +0 -1
  180. package/dist/src/uploader/optimizer/strategies/udpConcurrencyBasedOptimizationStrategy.d.ts +0 -33
  181. package/dist/src/uploader/optimizer/strategies/udpConcurrencyBasedOptimizationStrategy.d.ts.map +0 -1
  182. package/dist/src/uploader/optimizer/strategies/udpConcurrencyBasedOptimizationStrategy.js +0 -135
  183. package/dist/src/uploader/optimizer/strategies/udpConcurrencyBasedOptimizationStrategy.js.map +0 -1
  184. package/dist/src/uploader/optimizer/strategies/udpSleepBasedOptimizationStrategy.d.ts +0 -30
  185. package/dist/src/uploader/optimizer/strategies/udpSleepBasedOptimizationStrategy.d.ts.map +0 -1
  186. package/dist/src/uploader/optimizer/strategies/udpSleepBasedOptimizationStrategy.js +0 -106
  187. package/dist/src/uploader/optimizer/strategies/udpSleepBasedOptimizationStrategy.js.map +0 -1
  188. package/dist/src/uploader/optimizer/transferUploadOptimizationStrategy.d.ts +0 -20
  189. package/dist/src/uploader/optimizer/transferUploadOptimizationStrategy.d.ts.map +0 -1
  190. package/dist/src/uploader/optimizer/transferUploadOptimizationStrategy.js +0 -2
  191. package/dist/src/uploader/optimizer/transferUploadOptimizationStrategy.js.map +0 -1
  192. package/dist/src/uploader/optimizer/transferUploadOptimizer.d.ts +0 -27
  193. package/dist/src/uploader/optimizer/transferUploadOptimizer.d.ts.map +0 -1
  194. package/dist/src/uploader/optimizer/transferUploadOptimizer.js +0 -169
  195. package/dist/src/uploader/optimizer/transferUploadOptimizer.js.map +0 -1
  196. package/dist/src/uploader/optimizer/uploadOptimizer.d.ts +0 -11
  197. package/dist/src/uploader/optimizer/uploadOptimizer.d.ts.map +0 -1
  198. package/dist/src/uploader/optimizer/uploadOptimizer.js +0 -2
  199. package/dist/src/uploader/optimizer/uploadOptimizer.js.map +0 -1
@@ -1,16 +1,16 @@
1
- import sleep from 'abortable-sleep';
2
- import ApiError from '../utils/api/apiError.js';
3
- import FsError from '../utils/fileSystem/fsError.js';
4
1
  import TransferUploadState from "./state/transferUploadState.js";
5
2
  import TransferUploadError from "./transferUploadError.js";
6
3
  import TransferStatus from "../utils/types/transferStatus.js";
7
4
  import TransferUploadEvent from './transferUploadEvent.js';
8
5
  import ChunksIterator from './chunksIterator/chunksIterator.js';
9
6
  import mergeAbortAndPauseSignals from '../utils/mergeAbortAndPauseSignals.js';
7
+ import ApiError from '../utils/api/apiError.js';
8
+ import FsError from '../utils/fileSystem/fsError.js';
10
9
  import ApiFilemail449Error from '../utils/api/apiFilemail449Error.js';
11
10
  import { promiseAllSettled } from '../utils/promiseAll.js';
12
11
  import { isTransferFailureAbortReason } from './transferFailureAbortReason.js';
13
12
  import { concatUint8Arrays, hexToUint8Array, uint8ArrayToHex } from '../utils/uint8ArrayUtils.js';
13
+ const REGISTER_ITEMS_BATCH_SIZE = 250;
14
14
  export default class TransferUpload {
15
15
  #totalSizeInBytes;
16
16
  #chunkStreamProviderFactory;
@@ -19,8 +19,9 @@ export default class TransferUpload {
19
19
  #eventsEngine;
20
20
  #info;
21
21
  #config;
22
- #optimizer;
22
+ #concurrencyController;
23
23
  #cryptography;
24
+ #acker;
24
25
  #transferState;
25
26
  #transferMetadata;
26
27
  #transferDownloadUrl;
@@ -31,8 +32,6 @@ export default class TransferUpload {
31
32
  #mergedPauseAndAbortSignal;
32
33
  pauseEventListener;
33
34
  abortEventListener;
34
- #isUdpUploadMode;
35
- #serverLatencyInMs;
36
35
  #isRunMethodRunning = false;
37
36
  get status() {
38
37
  return this.#transferState?.status ?? TransferStatus.Initialized;
@@ -63,21 +62,19 @@ export default class TransferUpload {
63
62
  get transferId() {
64
63
  return this.#transferMetadata?.transferId;
65
64
  }
66
- constructor(chunkStreamProviderFactory, apiClient, fileServerClientFactory, eventsEngine, info, config, optimizer, cryptography) {
65
+ constructor(chunkStreamProviderFactory, apiClient, fileServerClientFactory, eventsEngine, info, config, concurrencyController, cryptography, acker) {
67
66
  if (info.files.length === 0)
68
67
  throw new TransferUploadError(`Files can't be empty`);
69
68
  this.#totalSizeInBytes = info.files.reduce((partialSum, file) => partialSum + file.fileSizeInBytes, 0);
70
- this.#isUdpUploadMode = false;
71
69
  this.#chunkStreamProviderFactory = chunkStreamProviderFactory;
72
70
  this.#apiClient = apiClient;
73
71
  this.#fileServerClientFactory = fileServerClientFactory;
74
72
  this.#eventsEngine = eventsEngine;
75
73
  this.#info = info;
76
74
  this.#config = config;
77
- this.#optimizer = optimizer;
75
+ this.#concurrencyController = concurrencyController;
78
76
  this.#cryptography = cryptography;
79
- if (this.isUploadAppendInfo(this.#info))
80
- this.createTransferMetadataFromInfo(this.#info);
77
+ this.#acker = acker;
81
78
  }
82
79
  isUploadAppend() {
83
80
  return this.isUploadAppendInfo(this.#info);
@@ -85,14 +82,20 @@ export default class TransferUpload {
85
82
  isUploadAppendInfo(info) {
86
83
  return info.transferKey !== undefined;
87
84
  }
88
- createTransferMetadataFromInfo(info) {
89
- if (!this.isUploadAppendInfo(info))
85
+ async registerFilesAndCreateTransferMetadataFromInfo() {
86
+ if (!this.isUploadAppendInfo(this.#info))
90
87
  throw new TransferUploadError(`Options are not TransferUploadAppendOptions`);
88
+ const registeredFiles = await this.registerTransferFilesWithValidation(this.#info.transferId, this.#info.transferKey);
89
+ this.createTransferMetadataFromInfo(this.#info, registeredFiles);
90
+ this.#eventsEngine.emit(TransferUploadEvent.RecreateDataUpdated);
91
+ }
92
+ createTransferMetadataFromInfo(info, registeredFiles) {
91
93
  this.#transferDownloadUrl = info.transferDownloadUrl;
92
94
  this.#transferMetadata = {
93
95
  transferId: info.transferId,
94
96
  transferKey: info.transferKey,
95
97
  transferFileServerUrl: info.transferFileServerUrl,
98
+ registeredFiles,
96
99
  transferRegion: info.transferRegion,
97
100
  encryptionData: info.e2eeData,
98
101
  };
@@ -110,27 +113,27 @@ export default class TransferUpload {
110
113
  this.#transferState.recover();
111
114
  this.#transferState.transferRun();
112
115
  this.addPauseAndStopListeners();
113
- if (!this.#transferMetadata)
116
+ if (this.isUploadAppend() && !this.#transferMetadata)
117
+ await this.registerFilesAndCreateTransferMetadataFromInfo();
118
+ else if (!this.#transferMetadata)
114
119
  await this.startApiTransferAndCreateMetadata();
115
120
  this.notifyMetadataDetermined();
116
- await this.pingServerAndChooseUploadMode();
117
- if (this.#isUdpUploadMode && !this.#transferMetadata.udpData.handshakeData)
118
- await this.serverUdpHandshake();
119
- this.#optimizer.start(this.#isUdpUploadMode, this.#serverLatencyInMs);
121
+ this.#acker.start(this.#transferMetadata.transferId, this.#transferMetadata.transferKey, this.#transferState, transferPauseSignal, transferAbortSignal);
120
122
  const ongoingChunkUploads = new Set();
121
123
  for (const file of this.files) {
122
124
  const fileStatus = this.#transferState.getFile(file.externalId);
123
125
  if (fileStatus.isCompleted)
124
126
  continue;
127
+ if (fileStatus.isUploadCompleted) {
128
+ this.enqueueFileAck(file);
129
+ continue;
130
+ }
125
131
  const alreadySentChunks = this.#transferState.getChunksForFile(file.externalId);
126
- const chunksIterator = new ChunksIterator(alreadySentChunks, file.fileSizeInBytes, this.#optimizer);
132
+ const chunksIterator = new ChunksIterator(alreadySentChunks, file.fileSizeInBytes, this.#config.chunkSizeInBytes);
127
133
  for (const chunk of chunksIterator.getChunksIterator()) {
128
134
  // eslint-disable-next-line no-await-in-loop
129
- const releaseSemaphore = await this.#optimizer.semaphoreAcquire();
130
- if (this.#optimizer.currentSleepTimeInMs >= 1)
131
- // eslint-disable-next-line no-await-in-loop
132
- await sleep(this.#optimizer.currentSleepTimeInMs, this.#mergedPauseAndAbortSignal);
133
- if (this.shouldStopSchedulingChunks()) {
135
+ const releaseSemaphore = await this.#concurrencyController.acquire();
136
+ if (this.shouldStopProcessing()) {
134
137
  releaseSemaphore();
135
138
  break;
136
139
  }
@@ -139,21 +142,21 @@ export default class TransferUpload {
139
142
  ongoingChunkUploads.delete(trackedChunkUploadPromise);
140
143
  });
141
144
  ongoingChunkUploads.add(trackedChunkUploadPromise);
142
- if (this.shouldStopSchedulingChunks())
145
+ if (this.shouldStopProcessing())
143
146
  break;
144
147
  }
145
- if (this.shouldStopSchedulingChunks())
148
+ if (this.shouldStopProcessing())
146
149
  break;
147
150
  }
148
151
  await promiseAllSettled(Array.from(ongoingChunkUploads));
149
- this.#optimizer.stop();
152
+ await this.#acker.flush();
150
153
  if (this.#transferState.status === TransferStatus.Pausing)
151
154
  this.#transferState.transferPaused();
152
155
  else if (this.#transferState.status === TransferStatus.Aborting)
153
156
  this.#transferState.transferAborted();
154
157
  // else if (this.isFailureAbortRequested())
155
158
  // this.#transferState.transferFailed();
156
- else if (this.uploadedBytesCount !== this.totalSizeInBytes)
159
+ else if (this.uploadedBytesCount !== this.totalSizeInBytes || this.hasUnackedFiles())
157
160
  this.#transferState.transferFailed();
158
161
  else {
159
162
  await this.finalizeTransfer();
@@ -184,8 +187,8 @@ export default class TransferUpload {
184
187
  throw new TransferUploadError(`Unhandled error occured. See 'cause' for more details`, { cause: error });
185
188
  }
186
189
  finally {
190
+ await this.#acker.stop();
187
191
  this.removePauseAndStopListeners();
188
- this.#optimizer.stop();
189
192
  this.#isRunMethodRunning = false;
190
193
  }
191
194
  }
@@ -199,65 +202,24 @@ export default class TransferUpload {
199
202
  };
200
203
  this.#eventsEngine.emit(TransferUploadEvent.TransferMetadataDetermined, eventArgs);
201
204
  }
202
- async pingServerAndChooseUploadMode() {
203
- try {
204
- if (this.#config.turnOffUdp)
205
- throw new Error(`UDP is turned off`);
206
- const udpData = this.#transferMetadata?.udpData;
207
- if (!udpData)
208
- throw new Error(`No UDP data is available`);
209
- const requestTimeout = this.#config.forceUdp ? 3 * 1000 : this.getPingTimeout(udpData.threshold);
210
- const retryDelay = 1000;
211
- const udpClient = this.#fileServerClientFactory.createFileServerUdpUploadClient(udpData.ip, udpData.port, requestTimeout, this.#mergedPauseAndAbortSignal, undefined, retryDelay);
212
- await udpClient.connect();
213
- const pingResult = await udpClient.ping();
214
- udpClient.close().catch(() => { });
215
- this.#serverLatencyInMs = pingResult.latencyInMs;
216
- this.#isUdpUploadMode = pingResult.latencyInMs >= udpData.threshold;
217
- const eventArgs = { isUdpMode: this.#isUdpUploadMode, latency: pingResult.latencyInMs };
218
- this.#eventsEngine.emit(TransferUploadEvent.TransferUploadModeChosen, eventArgs);
219
- }
220
- catch (error) {
221
- this.#isUdpUploadMode = false;
222
- const eventArgs = { isUdpMode: this.#isUdpUploadMode, error: error };
223
- this.#eventsEngine.emit(TransferUploadEvent.TransferUploadModeChosen, eventArgs);
224
- }
225
- }
226
- getPingTimeout(udpPingThreshold) {
227
- const pingTimeout = Math.min(3 * 1000, udpPingThreshold * 20);
228
- return Math.max(500, pingTimeout);
229
- }
230
- async serverUdpHandshake() {
231
- const transferMetadata = this.#transferMetadata;
232
- const udpData = transferMetadata.udpData;
233
- const requestTimeout = this.getHandshakeTimeout();
234
- const retryDelay = 1000;
235
- const udpClient = this.#fileServerClientFactory.createFileServerUdpUploadClient(udpData.ip, udpData.port, requestTimeout, this.#mergedPauseAndAbortSignal, undefined, retryDelay);
236
- await udpClient.connect();
237
- const handshakeRequest = { transferId: transferMetadata.transferId, transferKey: transferMetadata.transferKey };
238
- const handshakeResponse = await udpClient.handshake(handshakeRequest);
239
- udpClient.close().catch(() => { });
240
- this.#transferMetadata.udpData.handshakeData = handshakeResponse;
241
- }
242
- getHandshakeTimeout() {
243
- const timeout = Math.min(this.#serverLatencyInMs * 30, 30 * 1000);
244
- return Math.max(2000, timeout);
245
- }
246
205
  async sendChunkAndKeepUpdatingState(file, chunkStartPosition, chunkSizeInBytes, releaseSemaphore) {
247
206
  let uploadedBytesCount = 0;
207
+ const registeredFile = this.getRegisteredFile(file.externalId);
208
+ const uploadItemId = registeredFile?.uploadItemId;
248
209
  try {
249
- this.#transferState.chunkUploadStarted(file.externalId, chunkStartPosition, chunkSizeInBytes);
210
+ this.#transferState.chunkUploadStarted(file.externalId, uploadItemId, chunkStartPosition, chunkSizeInBytes);
250
211
  const chunkStreamProvider = this.#chunkStreamProviderFactory.createChunkStreamProvider(file, chunkStartPosition, chunkSizeInBytes, this.#transferMetadata?.encryptionData);
251
212
  const progressEventHandler = (eventArgs) => {
252
213
  uploadedBytesCount += eventArgs.transferredBytesSinceLastEvent;
253
- this.#transferState.chunkUploadProgressed(file.externalId, chunkStartPosition, chunkSizeInBytes, eventArgs);
214
+ this.#transferState.chunkUploadProgressed(file.externalId, uploadItemId, chunkStartPosition, chunkSizeInBytes, eventArgs);
254
215
  };
255
- const response = await this.sendChunk(file, chunkStreamProvider, progressEventHandler);
256
- const latencyInMsIfUdp = this.#isUdpUploadMode ? response.latencyInMs : undefined;
216
+ await this.sendChunk(file, registeredFile?.fileId, chunkStreamProvider, progressEventHandler);
257
217
  if (uploadedBytesCount === chunkSizeInBytes)
258
- this.#transferState.chunkUploadCompleted(file.externalId, chunkStartPosition, chunkSizeInBytes, latencyInMsIfUdp);
218
+ this.#transferState.chunkUploadCompleted(file.externalId, uploadItemId, chunkStartPosition, chunkSizeInBytes);
259
219
  else
260
- this.#transferState.chunkUploadCompletedPartially(file.externalId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, this.#pauseSignal.paused, latencyInMsIfUdp);
220
+ this.#transferState.chunkUploadCompletedPartially(file.externalId, uploadItemId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, this.#pauseSignal.paused);
221
+ if (this.#transferState.getFile(file.externalId).isUploadCompleted)
222
+ this.enqueueFileAck(file);
261
223
  }
262
224
  catch (error) {
263
225
  const chunkError = error;
@@ -266,46 +228,22 @@ export default class TransferUpload {
266
228
  && chunkError.cause.message === `Wrong md5 hash`
267
229
  && this.#pauseSignal?.paused === true;
268
230
  if (isTcpPausingError)
269
- this.#transferState.chunkUploadCompletedPartially(file.externalId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, this.#pauseSignal.paused);
231
+ this.#transferState.chunkUploadCompletedPartially(file.externalId, uploadItemId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, this.#pauseSignal.paused);
270
232
  else {
271
233
  const failedReason = this.getChunkFailedReason(error);
272
- this.#transferState.chunkUploadFailed(file.externalId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, failedReason, error);
234
+ this.#transferState.chunkUploadFailed(file.externalId, uploadItemId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, failedReason, error);
273
235
  }
274
236
  }
275
237
  finally {
276
238
  releaseSemaphore();
277
239
  }
278
240
  }
279
- async sendChunk(file, chunkStreamProvider, progressEventHandler) {
280
- if (this.#isUdpUploadMode)
281
- return await this.sendChunkUsingUdp(file, chunkStreamProvider, progressEventHandler);
282
- return await this.sendChunkUsingTcp(file, chunkStreamProvider, progressEventHandler);
283
- }
284
- async sendChunkUsingUdp(file, chunkStreamProvider, progressEventHandler) {
285
- const transferMetadata = this.#transferMetadata;
286
- const udpData = transferMetadata.udpData;
287
- const udpClient = this.#fileServerClientFactory.createFileServerUdpUploadClient(udpData.ip, udpData.port, this.#optimizer.currentRequestTimeoutInMs, this.#mergedPauseAndAbortSignal, 0);
288
- const sendChunkRequest = {
289
- sessionGuid: this.#transferMetadata.udpData.handshakeData.sessionGuid,
290
- aesKey: this.#transferMetadata.udpData.handshakeData.aesKey,
291
- chunkStartPosition: chunkStreamProvider.chunkStartPosition,
292
- fileSizeInBytes: file.fileSizeInBytes,
293
- fileDestinationPathInTransfer: file.fileDestinationPathInTransfer,
294
- fileName: file.fileName,
295
- };
296
- await udpClient.connect();
297
- const result = await udpClient.sendChunk(sendChunkRequest, chunkStreamProvider);
298
- udpClient.close().catch(() => { });
299
- const chunkProgressEventArgs = { transferredBytesTotal: chunkStreamProvider.chunkLengthInBytes, transferredBytesSinceLastEvent: chunkStreamProvider.chunkLengthInBytes };
300
- progressEventHandler(chunkProgressEventArgs);
301
- return result;
302
- }
303
- async sendChunkUsingTcp(file, chunkStreamProvider, progressEventHandler) {
241
+ async sendChunk(file, fileId, chunkStreamProvider, progressEventHandler) {
304
242
  const request = {
305
243
  chunkLengthInBytes: chunkStreamProvider.chunkLengthInBytes,
306
244
  chunkStartPosition: chunkStreamProvider.chunkStartPosition,
307
245
  };
308
- const fileServerClient = this.#fileServerClientFactory.createFileServerTcpUploadClient(this.#transferMetadata.transferFileServerUrl, this.#transferMetadata.transferId, this.#transferMetadata.transferKey, file.fileName, file.fileDestinationPathInTransfer, file.fileSizeInBytes);
246
+ const fileServerClient = this.#fileServerClientFactory.createFileServerUploadClient(this.#transferMetadata.transferFileServerUrl, this.#transferMetadata.transferId, this.#transferMetadata.transferKey, file.fileName, file.fileDestinationPathInTransfer, file.fileSizeInBytes, fileId);
309
247
  const ongoingRequestPromise = fileServerClient.sendFileChunk(request, chunkStreamProvider, this.#pauseSignal, this.#abortSignal);
310
248
  fileServerClient.addEventListener(`progress`, progressEventHandler);
311
249
  await ongoingRequestPromise;
@@ -355,7 +293,7 @@ export default class TransferUpload {
355
293
  this.#pauseSignal.removeEventListener(`pause`, this.pauseEventListener);
356
294
  this.#abortSignal.removeEventListener(`abort`, this.abortEventListener);
357
295
  }
358
- shouldStopSchedulingChunks() {
296
+ shouldStopProcessing() {
359
297
  return this.#transferState.status !== TransferStatus.Running || this.#abortSignal?.aborted === true || this.#pauseSignal?.paused === true;
360
298
  }
361
299
  isFailureAbortRequested() {
@@ -386,19 +324,73 @@ export default class TransferUpload {
386
324
  customfields: this.#info.customFields,
387
325
  };
388
326
  const response = await this.#apiClient.initializeTransfer(request, this.#mergedPauseAndAbortSignal);
327
+ const registeredFiles = await this.registerTransferFilesWithValidation(response.transferId, response.transferKey);
389
328
  this.#transferMetadata = {
390
329
  transferId: response.transferId,
391
330
  transferKey: response.transferKey,
392
331
  transferFileServerUrl: response.transferUrl,
332
+ registeredFiles,
393
333
  transferRegion: response.transferRegion,
394
334
  encryptionData: encryptionDataAndIvSaltHex?.encryptionData,
395
- udpData: this.getResponseOrForcedUdpData(response),
396
335
  };
336
+ this.#eventsEngine.emit(TransferUploadEvent.RecreateDataUpdated);
397
337
  }
398
338
  catch (error) {
399
339
  throw new TransferUploadError(`Error initializing transfer through the API`, { cause: error });
400
340
  }
401
341
  }
342
+ async registerTransferFilesWithValidation(transferId, transferKey) {
343
+ const registeredFiles = new Map();
344
+ for (let start = 0; start < this.files.length; start += REGISTER_ITEMS_BATCH_SIZE) {
345
+ const filesBatch = this.files.slice(start, start + REGISTER_ITEMS_BATCH_SIZE);
346
+ // eslint-disable-next-line no-await-in-loop
347
+ const response = await this.#apiClient.registerTransferFiles(transferId, {
348
+ transferkey: transferKey,
349
+ items: filesBatch.map(file => ({
350
+ path: this.joinTransferPath(file.fileDestinationPathInTransfer, file.fileName),
351
+ type: `File`,
352
+ size: file.fileSizeInBytes,
353
+ })),
354
+ }, this.#mergedPauseAndAbortSignal);
355
+ if (response.items.length !== filesBatch.length)
356
+ throw new TransferUploadError(`Invalid register transfer files response`);
357
+ response.items.forEach((item, index) => {
358
+ const file = filesBatch[index];
359
+ if (!file || !item.uploadItemId || !item.fileId)
360
+ throw new TransferUploadError(`Invalid register transfer files response`);
361
+ registeredFiles.set(file.externalId, { uploadItemId: item.uploadItemId, fileId: item.fileId });
362
+ });
363
+ }
364
+ return registeredFiles;
365
+ }
366
+ joinTransferPath(directoryPath, fileName) {
367
+ const normalizedDirectoryPath = directoryPath.replace(/^\/+|\/+$/g, ``);
368
+ const normalizedFileName = fileName.replace(/^\/+/g, ``);
369
+ if (!normalizedDirectoryPath)
370
+ return normalizedFileName;
371
+ return `${normalizedDirectoryPath}/${normalizedFileName}`;
372
+ }
373
+ getRegisteredFile(externalFileId) {
374
+ return this.#transferMetadata?.registeredFiles?.get(externalFileId);
375
+ }
376
+ enqueueFileAck(file) {
377
+ if (this.isLegacyTransfer()) { // Remove legacy mode after all our clients migrated to app version >= 4.22
378
+ this.#transferState.fileCompleted(file.externalId, undefined);
379
+ return;
380
+ }
381
+ const registeredFile = this.getRegisteredFile(file.externalId);
382
+ if (!registeredFile)
383
+ throw new TransferUploadError(`Can't ack file with external id = ${file.externalId} - no registered file found. The transfer state is malformed.`);
384
+ this.#acker.enqueue({ externalFileId: file.externalId, uploadItemId: registeredFile.uploadItemId, sizeInBytes: file.fileSizeInBytes });
385
+ }
386
+ hasUnackedFiles() {
387
+ if (this.isLegacyTransfer())
388
+ return false;
389
+ return this.files.some(file => !this.#transferState.getFile(file.externalId).isCompleted);
390
+ }
391
+ isLegacyTransfer() {
392
+ return this.#transferMetadata !== undefined && this.#transferMetadata.registeredFiles === undefined;
393
+ }
402
394
  async generateEncryptionDataAndIvSaltHmacHex(e2eeKey) {
403
395
  if (!e2eeKey)
404
396
  return undefined;
@@ -415,14 +407,6 @@ export default class TransferUpload {
415
407
  ivSaltHmacHex,
416
408
  };
417
409
  }
418
- getResponseOrForcedUdpData(response) {
419
- if (!this.#config.forceUdp || !response.udp)
420
- return response.udp;
421
- return {
422
- ...response.udp,
423
- threshold: 0,
424
- };
425
- }
426
410
  async finalizeTransfer() {
427
411
  this.#eventsEngine.emit(TransferUploadEvent.TransferFinalizing);
428
412
  if (this.isUploadAppend())
@@ -446,7 +430,7 @@ export default class TransferUpload {
446
430
  const request = {
447
431
  transferid: this.#transferMetadata.transferId,
448
432
  transferkey: this.#transferMetadata.transferKey,
449
- protocol: this.#isUdpUploadMode ? `udp` : `tcp`,
433
+ protocol: `tcp`,
450
434
  };
451
435
  const response = await this.#apiClient.finalizeTransfer(request, this.#mergedPauseAndAbortSignal);
452
436
  this.#transferDownloadUrl = response.downloadUrl;
@@ -459,7 +443,7 @@ export default class TransferUpload {
459
443
  }
460
444
  async cancel(abortSignal) {
461
445
  try {
462
- const isTransferApiInitialized = Boolean(this.#transferState) && Boolean(this.#transferMetadata);
446
+ const isTransferApiInitialized = Boolean(this.#transferState) && (Boolean(this.#transferMetadata) || this.isUploadAppend());
463
447
  if (!isTransferApiInitialized) {
464
448
  this.emitCancelEvents();
465
449
  return;
@@ -530,19 +514,20 @@ export default class TransferUpload {
530
514
  getTransferMetadataExportValue() {
531
515
  if (!this.#transferMetadata)
532
516
  return undefined;
533
- const { encryptionData, ...rest } = this.#transferMetadata;
517
+ const { encryptionData, registeredFiles, ...rest } = this.#transferMetadata;
534
518
  return {
535
519
  ...rest,
536
520
  encryptionData: !encryptionData ? undefined : {
537
521
  ivHex: uint8ArrayToHex(encryptionData.iv),
538
522
  keyHex: uint8ArrayToHex(encryptionData.key),
539
523
  },
524
+ registeredFiles: this.isLegacyTransfer() ? undefined : Array.from(registeredFiles.entries()),
540
525
  };
541
526
  }
542
- static recreate(transferExportData, config, chunkStreamProviderFactory, apiClient, fileServerClientFactory, eventsEngine, optimizer, cryptography) {
527
+ static recreate(transferExportData, config, chunkStreamProviderFactory, apiClient, fileServerClientFactory, eventsEngine, concurrencyController, cryptography, acker) {
543
528
  try {
544
529
  TransferUpload.validateRecreateParams(transferExportData);
545
- const transfer = new TransferUpload(chunkStreamProviderFactory, apiClient, fileServerClientFactory, eventsEngine, transferExportData.info, config, optimizer, cryptography);
530
+ const transfer = new TransferUpload(chunkStreamProviderFactory, apiClient, fileServerClientFactory, eventsEngine, transferExportData.info, config, concurrencyController, cryptography, acker);
546
531
  transfer.#transferMetadata = this.recreateTransferMetadata(transferExportData.transferMetadata);
547
532
  transfer.#transferState = new TransferUploadState(transferExportData.info.files, eventsEngine, config.currentRatesTimespanInMs, config.progressEventThrottlingInMs, transferExportData.state);
548
533
  return transfer;
@@ -557,13 +542,14 @@ export default class TransferUpload {
557
542
  static recreateTransferMetadata(transferMetadata) {
558
543
  if (!transferMetadata)
559
544
  return undefined;
560
- const { encryptionData, ...rest } = transferMetadata;
545
+ const { encryptionData, registeredFiles, ...rest } = transferMetadata;
561
546
  return {
562
547
  ...rest,
563
548
  encryptionData: !encryptionData ? undefined : {
564
549
  iv: hexToUint8Array(encryptionData.ivHex),
565
550
  key: hexToUint8Array(encryptionData.keyHex),
566
551
  },
552
+ registeredFiles: registeredFiles ? new Map(registeredFiles) : undefined,
567
553
  };
568
554
  }
569
555
  static validateRecreateParams(transferExportData) {