filemail-sdk 9.4.9 → 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 (205) 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/eventArgs/transferUploadCompletedEventArgs.d.ts +1 -0
  57. package/dist/src/uploader/eventArgs/transferUploadCompletedEventArgs.d.ts.map +1 -1
  58. package/dist/src/uploader/eventArgs/transferUploadCompletedEventArgs.js.map +1 -1
  59. package/dist/src/uploader/export/transferUploadExportData.d.ts +3 -1
  60. package/dist/src/uploader/export/transferUploadExportData.d.ts.map +1 -1
  61. package/dist/src/uploader/export/transferUploadExportData.js.map +1 -1
  62. package/dist/src/uploader/export/transferUploadExportState.d.ts +4 -1
  63. package/dist/src/uploader/export/transferUploadExportState.d.ts.map +1 -1
  64. package/dist/src/uploader/export/transferUploadExportState.js.map +1 -1
  65. package/dist/src/uploader/export/transferUploadMetadata.d.ts +2 -9
  66. package/dist/src/uploader/export/transferUploadMetadata.d.ts.map +1 -1
  67. package/dist/src/uploader/export/transferUploadMetadata.js.map +1 -1
  68. package/dist/src/uploader/options/transferUploadConfig.d.ts +1 -2
  69. package/dist/src/uploader/options/transferUploadConfig.d.ts.map +1 -1
  70. package/dist/src/uploader/options/transferUploadConfig.js.map +1 -1
  71. package/dist/src/uploader/pendingFileAck.d.ts +7 -0
  72. package/dist/src/uploader/pendingFileAck.d.ts.map +1 -0
  73. package/dist/src/uploader/pendingFileAck.js +2 -0
  74. package/dist/src/uploader/pendingFileAck.js.map +1 -0
  75. package/dist/src/uploader/registeredTransferFile.d.ts +6 -0
  76. package/dist/src/uploader/registeredTransferFile.d.ts.map +1 -0
  77. package/dist/src/uploader/registeredTransferFile.js +2 -0
  78. package/dist/src/uploader/registeredTransferFile.js.map +1 -0
  79. package/dist/src/uploader/state/transferUploadState.d.ts +12 -9
  80. package/dist/src/uploader/state/transferUploadState.d.ts.map +1 -1
  81. package/dist/src/uploader/state/transferUploadState.js +56 -27
  82. package/dist/src/uploader/state/transferUploadState.js.map +1 -1
  83. package/dist/src/uploader/state/transferUploadStateFile.d.ts +1 -0
  84. package/dist/src/uploader/state/transferUploadStateFile.d.ts.map +1 -1
  85. package/dist/src/uploader/state/transferUploadStateFile.js +1 -0
  86. package/dist/src/uploader/state/transferUploadStateFile.js.map +1 -1
  87. package/dist/src/uploader/transferUpload.d.ts +17 -14
  88. package/dist/src/uploader/transferUpload.d.ts.map +1 -1
  89. package/dist/src/uploader/transferUpload.js +112 -124
  90. package/dist/src/uploader/transferUpload.js.map +1 -1
  91. package/dist/src/uploader/transferUploadAcker.d.ts +19 -0
  92. package/dist/src/uploader/transferUploadAcker.d.ts.map +1 -0
  93. package/dist/src/uploader/transferUploadAcker.js +119 -0
  94. package/dist/src/uploader/transferUploadAcker.js.map +1 -0
  95. package/dist/src/uploader/transferUploadEvent.d.ts +3 -1
  96. package/dist/src/uploader/transferUploadEvent.d.ts.map +1 -1
  97. package/dist/src/uploader/transferUploadEvent.js +3 -1
  98. package/dist/src/uploader/transferUploadEvent.js.map +1 -1
  99. package/dist/src/utils/api/apiClient.d.ts +6 -0
  100. package/dist/src/utils/api/apiClient.d.ts.map +1 -1
  101. package/dist/src/utils/api/apiClient.js.map +1 -1
  102. package/dist/src/utils/api/apiClientBase.d.ts +0 -2
  103. package/dist/src/utils/api/apiClientBase.d.ts.map +1 -1
  104. package/dist/src/utils/api/apiClientBase.js +6 -13
  105. package/dist/src/utils/api/apiClientBase.js.map +1 -1
  106. package/dist/src/utils/api/dtos/ackTransferFilesRequest.d.ts +9 -0
  107. package/dist/src/utils/api/dtos/ackTransferFilesRequest.d.ts.map +1 -0
  108. package/dist/src/utils/api/dtos/ackTransferFilesRequest.js +2 -0
  109. package/dist/src/utils/api/dtos/ackTransferFilesRequest.js.map +1 -0
  110. package/dist/src/utils/api/dtos/ackTransferFilesResponse.d.ts +7 -0
  111. package/dist/src/utils/api/dtos/ackTransferFilesResponse.d.ts.map +1 -0
  112. package/dist/src/utils/api/dtos/ackTransferFilesResponse.js +2 -0
  113. package/dist/src/utils/api/dtos/ackTransferFilesResponse.js.map +1 -0
  114. package/dist/src/utils/api/dtos/finalizeTransferRequest.d.ts +1 -1
  115. package/dist/src/utils/api/dtos/finalizeTransferRequest.d.ts.map +1 -1
  116. package/dist/src/utils/api/dtos/finalizeTransferRequest.js.map +1 -1
  117. package/dist/src/utils/api/dtos/finalizeTransferResponse.d.ts +2 -0
  118. package/dist/src/utils/api/dtos/finalizeTransferResponse.d.ts.map +1 -1
  119. package/dist/src/utils/api/dtos/finalizeTransferResponse.js.map +1 -1
  120. package/dist/src/utils/api/dtos/initializeTransferRequest.d.ts +1 -0
  121. package/dist/src/utils/api/dtos/initializeTransferRequest.d.ts.map +1 -1
  122. package/dist/src/utils/api/dtos/initializeTransferRequest.js.map +1 -1
  123. package/dist/src/utils/api/dtos/initializeTransferResponse.d.ts +0 -9
  124. package/dist/src/utils/api/dtos/initializeTransferResponse.d.ts.map +1 -1
  125. package/dist/src/utils/api/dtos/initializeTransferResponse.js.map +1 -1
  126. package/dist/src/utils/api/dtos/registerTransferFilesRequest.d.ts +18 -0
  127. package/dist/src/utils/api/dtos/registerTransferFilesRequest.d.ts.map +1 -0
  128. package/dist/src/utils/api/dtos/registerTransferFilesRequest.js +2 -0
  129. package/dist/src/utils/api/dtos/registerTransferFilesRequest.js.map +1 -0
  130. package/dist/src/utils/api/dtos/registerTransferFilesResponse.d.ts +9 -0
  131. package/dist/src/utils/api/dtos/registerTransferFilesResponse.d.ts.map +1 -0
  132. package/dist/src/utils/api/dtos/registerTransferFilesResponse.js +2 -0
  133. package/dist/src/utils/api/dtos/registerTransferFilesResponse.js.map +1 -0
  134. package/dist/src/utils/api/fileServerClientFactory.d.ts +2 -4
  135. package/dist/src/utils/api/fileServerClientFactory.d.ts.map +1 -1
  136. package/dist/src/utils/api/fileServerClientFactory.js.map +1 -1
  137. package/dist/src/utils/api/node/nodeApiClient.d.ts +6 -0
  138. package/dist/src/utils/api/node/nodeApiClient.d.ts.map +1 -1
  139. package/dist/src/utils/api/node/nodeApiClient.js +27 -2
  140. package/dist/src/utils/api/node/nodeApiClient.js.map +1 -1
  141. package/dist/src/utils/api/node/nodeFileServerClientFactory.d.ts +2 -4
  142. package/dist/src/utils/api/node/nodeFileServerClientFactory.d.ts.map +1 -1
  143. package/dist/src/utils/api/node/nodeFileServerClientFactory.js +3 -7
  144. package/dist/src/utils/api/node/nodeFileServerClientFactory.js.map +1 -1
  145. package/dist/src/utils/api/web/webApiClient.d.ts +6 -0
  146. package/dist/src/utils/api/web/webApiClient.d.ts.map +1 -1
  147. package/dist/src/utils/api/web/webApiClient.js +25 -2
  148. package/dist/src/utils/api/web/webApiClient.js.map +1 -1
  149. package/dist/src/utils/api/web/webFileServerClientFactory.d.ts +2 -4
  150. package/dist/src/utils/api/web/webFileServerClientFactory.d.ts.map +1 -1
  151. package/dist/src/utils/api/web/webFileServerClientFactory.js +3 -6
  152. package/dist/src/utils/api/web/webFileServerClientFactory.js.map +1 -1
  153. package/package.json +1 -2
  154. package/dist/src/uploader/api/dtos/handshakeRequest.d.ts +0 -6
  155. package/dist/src/uploader/api/dtos/handshakeRequest.d.ts.map +0 -1
  156. package/dist/src/uploader/api/dtos/handshakeRequest.js +0 -2
  157. package/dist/src/uploader/api/dtos/handshakeRequest.js.map +0 -1
  158. package/dist/src/uploader/api/dtos/handshakeResponse.d.ts +0 -6
  159. package/dist/src/uploader/api/dtos/handshakeResponse.d.ts.map +0 -1
  160. package/dist/src/uploader/api/dtos/handshakeResponse.js +0 -2
  161. package/dist/src/uploader/api/dtos/handshakeResponse.js.map +0 -1
  162. package/dist/src/uploader/api/dtos/pingResponse.d.ts +0 -5
  163. package/dist/src/uploader/api/dtos/pingResponse.d.ts.map +0 -1
  164. package/dist/src/uploader/api/dtos/pingResponse.js +0 -2
  165. package/dist/src/uploader/api/dtos/pingResponse.js.map +0 -1
  166. package/dist/src/uploader/api/dtos/sendChunkRequest.d.ts +0 -10
  167. package/dist/src/uploader/api/dtos/sendChunkRequest.d.ts.map +0 -1
  168. package/dist/src/uploader/api/dtos/sendChunkRequest.js +0 -2
  169. package/dist/src/uploader/api/dtos/sendChunkRequest.js.map +0 -1
  170. package/dist/src/uploader/api/fileServerUdpClient.d.ts +0 -19
  171. package/dist/src/uploader/api/fileServerUdpClient.d.ts.map +0 -1
  172. package/dist/src/uploader/api/fileServerUdpClient.js +0 -2
  173. package/dist/src/uploader/api/fileServerUdpClient.js.map +0 -1
  174. package/dist/src/uploader/api/node/nodeFileServerUdpClient.d.ts +0 -39
  175. package/dist/src/uploader/api/node/nodeFileServerUdpClient.d.ts.map +0 -1
  176. package/dist/src/uploader/api/node/nodeFileServerUdpClient.js +0 -264
  177. package/dist/src/uploader/api/node/nodeFileServerUdpClient.js.map +0 -1
  178. package/dist/src/uploader/eventArgs/transferUploadModeChosenEventArgs.d.ts +0 -7
  179. package/dist/src/uploader/eventArgs/transferUploadModeChosenEventArgs.d.ts.map +0 -1
  180. package/dist/src/uploader/eventArgs/transferUploadModeChosenEventArgs.js +0 -2
  181. package/dist/src/uploader/eventArgs/transferUploadModeChosenEventArgs.js.map +0 -1
  182. package/dist/src/uploader/optimizer/optimizationValues.d.ts +0 -9
  183. package/dist/src/uploader/optimizer/optimizationValues.d.ts.map +0 -1
  184. package/dist/src/uploader/optimizer/optimizationValues.js +0 -2
  185. package/dist/src/uploader/optimizer/optimizationValues.js.map +0 -1
  186. package/dist/src/uploader/optimizer/strategies/udpConcurrencyBasedOptimizationStrategy.d.ts +0 -33
  187. package/dist/src/uploader/optimizer/strategies/udpConcurrencyBasedOptimizationStrategy.d.ts.map +0 -1
  188. package/dist/src/uploader/optimizer/strategies/udpConcurrencyBasedOptimizationStrategy.js +0 -135
  189. package/dist/src/uploader/optimizer/strategies/udpConcurrencyBasedOptimizationStrategy.js.map +0 -1
  190. package/dist/src/uploader/optimizer/strategies/udpSleepBasedOptimizationStrategy.d.ts +0 -30
  191. package/dist/src/uploader/optimizer/strategies/udpSleepBasedOptimizationStrategy.d.ts.map +0 -1
  192. package/dist/src/uploader/optimizer/strategies/udpSleepBasedOptimizationStrategy.js +0 -106
  193. package/dist/src/uploader/optimizer/strategies/udpSleepBasedOptimizationStrategy.js.map +0 -1
  194. package/dist/src/uploader/optimizer/transferUploadOptimizationStrategy.d.ts +0 -20
  195. package/dist/src/uploader/optimizer/transferUploadOptimizationStrategy.d.ts.map +0 -1
  196. package/dist/src/uploader/optimizer/transferUploadOptimizationStrategy.js +0 -2
  197. package/dist/src/uploader/optimizer/transferUploadOptimizationStrategy.js.map +0 -1
  198. package/dist/src/uploader/optimizer/transferUploadOptimizer.d.ts +0 -27
  199. package/dist/src/uploader/optimizer/transferUploadOptimizer.d.ts.map +0 -1
  200. package/dist/src/uploader/optimizer/transferUploadOptimizer.js +0 -169
  201. package/dist/src/uploader/optimizer/transferUploadOptimizer.js.map +0 -1
  202. package/dist/src/uploader/optimizer/uploadOptimizer.d.ts +0 -11
  203. package/dist/src/uploader/optimizer/uploadOptimizer.d.ts.map +0 -1
  204. package/dist/src/uploader/optimizer/uploadOptimizer.js +0 -2
  205. 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,19 +19,19 @@ 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;
28
+ #transferConfirmationUrl;
27
29
  #transferRecipientTrackingLinks;
28
30
  #pauseSignal;
29
31
  #abortSignal;
30
32
  #mergedPauseAndAbortSignal;
31
33
  pauseEventListener;
32
34
  abortEventListener;
33
- #isUdpUploadMode;
34
- #serverLatencyInMs;
35
35
  #isRunMethodRunning = false;
36
36
  get status() {
37
37
  return this.#transferState?.status ?? TransferStatus.Initialized;
@@ -62,21 +62,19 @@ export default class TransferUpload {
62
62
  get transferId() {
63
63
  return this.#transferMetadata?.transferId;
64
64
  }
65
- constructor(chunkStreamProviderFactory, apiClient, fileServerClientFactory, eventsEngine, info, config, optimizer, cryptography) {
65
+ constructor(chunkStreamProviderFactory, apiClient, fileServerClientFactory, eventsEngine, info, config, concurrencyController, cryptography, acker) {
66
66
  if (info.files.length === 0)
67
67
  throw new TransferUploadError(`Files can't be empty`);
68
68
  this.#totalSizeInBytes = info.files.reduce((partialSum, file) => partialSum + file.fileSizeInBytes, 0);
69
- this.#isUdpUploadMode = false;
70
69
  this.#chunkStreamProviderFactory = chunkStreamProviderFactory;
71
70
  this.#apiClient = apiClient;
72
71
  this.#fileServerClientFactory = fileServerClientFactory;
73
72
  this.#eventsEngine = eventsEngine;
74
73
  this.#info = info;
75
74
  this.#config = config;
76
- this.#optimizer = optimizer;
75
+ this.#concurrencyController = concurrencyController;
77
76
  this.#cryptography = cryptography;
78
- if (this.isUploadAppendInfo(this.#info))
79
- this.createTransferMetadataFromInfo(this.#info);
77
+ this.#acker = acker;
80
78
  }
81
79
  isUploadAppend() {
82
80
  return this.isUploadAppendInfo(this.#info);
@@ -84,14 +82,20 @@ export default class TransferUpload {
84
82
  isUploadAppendInfo(info) {
85
83
  return info.transferKey !== undefined;
86
84
  }
87
- createTransferMetadataFromInfo(info) {
88
- if (!this.isUploadAppendInfo(info))
85
+ async registerFilesAndCreateTransferMetadataFromInfo() {
86
+ if (!this.isUploadAppendInfo(this.#info))
89
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) {
90
93
  this.#transferDownloadUrl = info.transferDownloadUrl;
91
94
  this.#transferMetadata = {
92
95
  transferId: info.transferId,
93
96
  transferKey: info.transferKey,
94
97
  transferFileServerUrl: info.transferFileServerUrl,
98
+ registeredFiles,
95
99
  transferRegion: info.transferRegion,
96
100
  encryptionData: info.e2eeData,
97
101
  };
@@ -109,27 +113,27 @@ export default class TransferUpload {
109
113
  this.#transferState.recover();
110
114
  this.#transferState.transferRun();
111
115
  this.addPauseAndStopListeners();
112
- if (!this.#transferMetadata)
116
+ if (this.isUploadAppend() && !this.#transferMetadata)
117
+ await this.registerFilesAndCreateTransferMetadataFromInfo();
118
+ else if (!this.#transferMetadata)
113
119
  await this.startApiTransferAndCreateMetadata();
114
120
  this.notifyMetadataDetermined();
115
- await this.pingServerAndChooseUploadMode();
116
- if (this.#isUdpUploadMode && !this.#transferMetadata.udpData.handshakeData)
117
- await this.serverUdpHandshake();
118
- this.#optimizer.start(this.#isUdpUploadMode, this.#serverLatencyInMs);
121
+ this.#acker.start(this.#transferMetadata.transferId, this.#transferMetadata.transferKey, this.#transferState, transferPauseSignal, transferAbortSignal);
119
122
  const ongoingChunkUploads = new Set();
120
123
  for (const file of this.files) {
121
124
  const fileStatus = this.#transferState.getFile(file.externalId);
122
125
  if (fileStatus.isCompleted)
123
126
  continue;
127
+ if (fileStatus.isUploadCompleted) {
128
+ this.enqueueFileAck(file);
129
+ continue;
130
+ }
124
131
  const alreadySentChunks = this.#transferState.getChunksForFile(file.externalId);
125
- const chunksIterator = new ChunksIterator(alreadySentChunks, file.fileSizeInBytes, this.#optimizer);
132
+ const chunksIterator = new ChunksIterator(alreadySentChunks, file.fileSizeInBytes, this.#config.chunkSizeInBytes);
126
133
  for (const chunk of chunksIterator.getChunksIterator()) {
127
134
  // eslint-disable-next-line no-await-in-loop
128
- const releaseSemaphore = await this.#optimizer.semaphoreAcquire();
129
- if (this.#optimizer.currentSleepTimeInMs >= 1)
130
- // eslint-disable-next-line no-await-in-loop
131
- await sleep(this.#optimizer.currentSleepTimeInMs, this.#mergedPauseAndAbortSignal);
132
- if (this.shouldStopSchedulingChunks()) {
135
+ const releaseSemaphore = await this.#concurrencyController.acquire();
136
+ if (this.shouldStopProcessing()) {
133
137
  releaseSemaphore();
134
138
  break;
135
139
  }
@@ -138,25 +142,25 @@ export default class TransferUpload {
138
142
  ongoingChunkUploads.delete(trackedChunkUploadPromise);
139
143
  });
140
144
  ongoingChunkUploads.add(trackedChunkUploadPromise);
141
- if (this.shouldStopSchedulingChunks())
145
+ if (this.shouldStopProcessing())
142
146
  break;
143
147
  }
144
- if (this.shouldStopSchedulingChunks())
148
+ if (this.shouldStopProcessing())
145
149
  break;
146
150
  }
147
151
  await promiseAllSettled(Array.from(ongoingChunkUploads));
148
- this.#optimizer.stop();
152
+ await this.#acker.flush();
149
153
  if (this.#transferState.status === TransferStatus.Pausing)
150
154
  this.#transferState.transferPaused();
151
155
  else if (this.#transferState.status === TransferStatus.Aborting)
152
156
  this.#transferState.transferAborted();
153
157
  // else if (this.isFailureAbortRequested())
154
158
  // this.#transferState.transferFailed();
155
- else if (this.uploadedBytesCount !== this.totalSizeInBytes)
159
+ else if (this.uploadedBytesCount !== this.totalSizeInBytes || this.hasUnackedFiles())
156
160
  this.#transferState.transferFailed();
157
161
  else {
158
162
  await this.finalizeTransfer();
159
- this.#transferState.transferCompleted(this.#transferMetadata, this.#transferDownloadUrl, this.#transferRecipientTrackingLinks);
163
+ this.#transferState.transferCompleted(this.#transferMetadata, this.#transferDownloadUrl, this.#transferConfirmationUrl, this.#transferRecipientTrackingLinks);
160
164
  }
161
165
  }
162
166
  catch (error) {
@@ -183,8 +187,8 @@ export default class TransferUpload {
183
187
  throw new TransferUploadError(`Unhandled error occured. See 'cause' for more details`, { cause: error });
184
188
  }
185
189
  finally {
190
+ await this.#acker.stop();
186
191
  this.removePauseAndStopListeners();
187
- this.#optimizer.stop();
188
192
  this.#isRunMethodRunning = false;
189
193
  }
190
194
  }
@@ -198,65 +202,24 @@ export default class TransferUpload {
198
202
  };
199
203
  this.#eventsEngine.emit(TransferUploadEvent.TransferMetadataDetermined, eventArgs);
200
204
  }
201
- async pingServerAndChooseUploadMode() {
202
- try {
203
- if (this.#config.turnOffUdp)
204
- throw new Error(`UDP is turned off`);
205
- const udpData = this.#transferMetadata?.udpData;
206
- if (!udpData)
207
- throw new Error(`No UDP data is available`);
208
- const requestTimeout = this.#config.forceUdp ? 3 * 1000 : this.getPingTimeout(udpData.threshold);
209
- const retryDelay = 1000;
210
- const udpClient = this.#fileServerClientFactory.createFileServerUdpUploadClient(udpData.ip, udpData.port, requestTimeout, this.#mergedPauseAndAbortSignal, undefined, retryDelay);
211
- await udpClient.connect();
212
- const pingResult = await udpClient.ping();
213
- udpClient.close().catch(() => { });
214
- this.#serverLatencyInMs = pingResult.latencyInMs;
215
- this.#isUdpUploadMode = pingResult.latencyInMs >= udpData.threshold;
216
- const eventArgs = { isUdpMode: this.#isUdpUploadMode, latency: pingResult.latencyInMs };
217
- this.#eventsEngine.emit(TransferUploadEvent.TransferUploadModeChosen, eventArgs);
218
- }
219
- catch (error) {
220
- this.#isUdpUploadMode = false;
221
- const eventArgs = { isUdpMode: this.#isUdpUploadMode, error: error };
222
- this.#eventsEngine.emit(TransferUploadEvent.TransferUploadModeChosen, eventArgs);
223
- }
224
- }
225
- getPingTimeout(udpPingThreshold) {
226
- const pingTimeout = Math.min(3 * 1000, udpPingThreshold * 20);
227
- return Math.max(500, pingTimeout);
228
- }
229
- async serverUdpHandshake() {
230
- const transferMetadata = this.#transferMetadata;
231
- const udpData = transferMetadata.udpData;
232
- const requestTimeout = this.getHandshakeTimeout();
233
- const retryDelay = 1000;
234
- const udpClient = this.#fileServerClientFactory.createFileServerUdpUploadClient(udpData.ip, udpData.port, requestTimeout, this.#mergedPauseAndAbortSignal, undefined, retryDelay);
235
- await udpClient.connect();
236
- const handshakeRequest = { transferId: transferMetadata.transferId, transferKey: transferMetadata.transferKey };
237
- const handshakeResponse = await udpClient.handshake(handshakeRequest);
238
- udpClient.close().catch(() => { });
239
- this.#transferMetadata.udpData.handshakeData = handshakeResponse;
240
- }
241
- getHandshakeTimeout() {
242
- const timeout = Math.min(this.#serverLatencyInMs * 30, 30 * 1000);
243
- return Math.max(2000, timeout);
244
- }
245
205
  async sendChunkAndKeepUpdatingState(file, chunkStartPosition, chunkSizeInBytes, releaseSemaphore) {
246
206
  let uploadedBytesCount = 0;
207
+ const registeredFile = this.getRegisteredFile(file.externalId);
208
+ const uploadItemId = registeredFile?.uploadItemId;
247
209
  try {
248
- this.#transferState.chunkUploadStarted(file.externalId, chunkStartPosition, chunkSizeInBytes);
210
+ this.#transferState.chunkUploadStarted(file.externalId, uploadItemId, chunkStartPosition, chunkSizeInBytes);
249
211
  const chunkStreamProvider = this.#chunkStreamProviderFactory.createChunkStreamProvider(file, chunkStartPosition, chunkSizeInBytes, this.#transferMetadata?.encryptionData);
250
212
  const progressEventHandler = (eventArgs) => {
251
213
  uploadedBytesCount += eventArgs.transferredBytesSinceLastEvent;
252
- this.#transferState.chunkUploadProgressed(file.externalId, chunkStartPosition, chunkSizeInBytes, eventArgs);
214
+ this.#transferState.chunkUploadProgressed(file.externalId, uploadItemId, chunkStartPosition, chunkSizeInBytes, eventArgs);
253
215
  };
254
- const response = await this.sendChunk(file, chunkStreamProvider, progressEventHandler);
255
- const latencyInMsIfUdp = this.#isUdpUploadMode ? response.latencyInMs : undefined;
216
+ await this.sendChunk(file, registeredFile?.fileId, chunkStreamProvider, progressEventHandler);
256
217
  if (uploadedBytesCount === chunkSizeInBytes)
257
- this.#transferState.chunkUploadCompleted(file.externalId, chunkStartPosition, chunkSizeInBytes, latencyInMsIfUdp);
218
+ this.#transferState.chunkUploadCompleted(file.externalId, uploadItemId, chunkStartPosition, chunkSizeInBytes);
258
219
  else
259
- 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);
260
223
  }
261
224
  catch (error) {
262
225
  const chunkError = error;
@@ -265,46 +228,22 @@ export default class TransferUpload {
265
228
  && chunkError.cause.message === `Wrong md5 hash`
266
229
  && this.#pauseSignal?.paused === true;
267
230
  if (isTcpPausingError)
268
- this.#transferState.chunkUploadCompletedPartially(file.externalId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, this.#pauseSignal.paused);
231
+ this.#transferState.chunkUploadCompletedPartially(file.externalId, uploadItemId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, this.#pauseSignal.paused);
269
232
  else {
270
233
  const failedReason = this.getChunkFailedReason(error);
271
- this.#transferState.chunkUploadFailed(file.externalId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, failedReason, error);
234
+ this.#transferState.chunkUploadFailed(file.externalId, uploadItemId, chunkStartPosition, chunkSizeInBytes, uploadedBytesCount, failedReason, error);
272
235
  }
273
236
  }
274
237
  finally {
275
238
  releaseSemaphore();
276
239
  }
277
240
  }
278
- async sendChunk(file, chunkStreamProvider, progressEventHandler) {
279
- if (this.#isUdpUploadMode)
280
- return await this.sendChunkUsingUdp(file, chunkStreamProvider, progressEventHandler);
281
- return await this.sendChunkUsingTcp(file, chunkStreamProvider, progressEventHandler);
282
- }
283
- async sendChunkUsingUdp(file, chunkStreamProvider, progressEventHandler) {
284
- const transferMetadata = this.#transferMetadata;
285
- const udpData = transferMetadata.udpData;
286
- const udpClient = this.#fileServerClientFactory.createFileServerUdpUploadClient(udpData.ip, udpData.port, this.#optimizer.currentRequestTimeoutInMs, this.#mergedPauseAndAbortSignal, 0);
287
- const sendChunkRequest = {
288
- sessionGuid: this.#transferMetadata.udpData.handshakeData.sessionGuid,
289
- aesKey: this.#transferMetadata.udpData.handshakeData.aesKey,
290
- chunkStartPosition: chunkStreamProvider.chunkStartPosition,
291
- fileSizeInBytes: file.fileSizeInBytes,
292
- fileDestinationPathInTransfer: file.fileDestinationPathInTransfer,
293
- fileName: file.fileName,
294
- };
295
- await udpClient.connect();
296
- const result = await udpClient.sendChunk(sendChunkRequest, chunkStreamProvider);
297
- udpClient.close().catch(() => { });
298
- const chunkProgressEventArgs = { transferredBytesTotal: chunkStreamProvider.chunkLengthInBytes, transferredBytesSinceLastEvent: chunkStreamProvider.chunkLengthInBytes };
299
- progressEventHandler(chunkProgressEventArgs);
300
- return result;
301
- }
302
- async sendChunkUsingTcp(file, chunkStreamProvider, progressEventHandler) {
241
+ async sendChunk(file, fileId, chunkStreamProvider, progressEventHandler) {
303
242
  const request = {
304
243
  chunkLengthInBytes: chunkStreamProvider.chunkLengthInBytes,
305
244
  chunkStartPosition: chunkStreamProvider.chunkStartPosition,
306
245
  };
307
- 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);
308
247
  const ongoingRequestPromise = fileServerClient.sendFileChunk(request, chunkStreamProvider, this.#pauseSignal, this.#abortSignal);
309
248
  fileServerClient.addEventListener(`progress`, progressEventHandler);
310
249
  await ongoingRequestPromise;
@@ -354,7 +293,7 @@ export default class TransferUpload {
354
293
  this.#pauseSignal.removeEventListener(`pause`, this.pauseEventListener);
355
294
  this.#abortSignal.removeEventListener(`abort`, this.abortEventListener);
356
295
  }
357
- shouldStopSchedulingChunks() {
296
+ shouldStopProcessing() {
358
297
  return this.#transferState.status !== TransferStatus.Running || this.#abortSignal?.aborted === true || this.#pauseSignal?.paused === true;
359
298
  }
360
299
  isFailureAbortRequested() {
@@ -385,19 +324,73 @@ export default class TransferUpload {
385
324
  customfields: this.#info.customFields,
386
325
  };
387
326
  const response = await this.#apiClient.initializeTransfer(request, this.#mergedPauseAndAbortSignal);
327
+ const registeredFiles = await this.registerTransferFilesWithValidation(response.transferId, response.transferKey);
388
328
  this.#transferMetadata = {
389
329
  transferId: response.transferId,
390
330
  transferKey: response.transferKey,
391
331
  transferFileServerUrl: response.transferUrl,
332
+ registeredFiles,
392
333
  transferRegion: response.transferRegion,
393
334
  encryptionData: encryptionDataAndIvSaltHex?.encryptionData,
394
- udpData: this.getResponseOrForcedUdpData(response),
395
335
  };
336
+ this.#eventsEngine.emit(TransferUploadEvent.RecreateDataUpdated);
396
337
  }
397
338
  catch (error) {
398
339
  throw new TransferUploadError(`Error initializing transfer through the API`, { cause: error });
399
340
  }
400
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
+ }
401
394
  async generateEncryptionDataAndIvSaltHmacHex(e2eeKey) {
402
395
  if (!e2eeKey)
403
396
  return undefined;
@@ -414,14 +407,6 @@ export default class TransferUpload {
414
407
  ivSaltHmacHex,
415
408
  };
416
409
  }
417
- getResponseOrForcedUdpData(response) {
418
- if (!this.#config.forceUdp || !response.udp)
419
- return response.udp;
420
- return {
421
- ...response.udp,
422
- threshold: 0,
423
- };
424
- }
425
410
  async finalizeTransfer() {
426
411
  this.#eventsEngine.emit(TransferUploadEvent.TransferFinalizing);
427
412
  if (this.isUploadAppend())
@@ -445,10 +430,11 @@ export default class TransferUpload {
445
430
  const request = {
446
431
  transferid: this.#transferMetadata.transferId,
447
432
  transferkey: this.#transferMetadata.transferKey,
448
- protocol: this.#isUdpUploadMode ? `udp` : `tcp`,
433
+ protocol: `tcp`,
449
434
  };
450
435
  const response = await this.#apiClient.finalizeTransfer(request, this.#mergedPauseAndAbortSignal);
451
436
  this.#transferDownloadUrl = response.downloadUrl;
437
+ this.#transferConfirmationUrl = response.confirmationUrl;
452
438
  this.#transferRecipientTrackingLinks = response.recipientTrackingLinks;
453
439
  }
454
440
  catch (error) {
@@ -457,7 +443,7 @@ export default class TransferUpload {
457
443
  }
458
444
  async cancel(abortSignal) {
459
445
  try {
460
- const isTransferApiInitialized = Boolean(this.#transferState) && Boolean(this.#transferMetadata);
446
+ const isTransferApiInitialized = Boolean(this.#transferState) && (Boolean(this.#transferMetadata) || this.isUploadAppend());
461
447
  if (!isTransferApiInitialized) {
462
448
  this.emitCancelEvents();
463
449
  return;
@@ -528,19 +514,20 @@ export default class TransferUpload {
528
514
  getTransferMetadataExportValue() {
529
515
  if (!this.#transferMetadata)
530
516
  return undefined;
531
- const { encryptionData, ...rest } = this.#transferMetadata;
517
+ const { encryptionData, registeredFiles, ...rest } = this.#transferMetadata;
532
518
  return {
533
519
  ...rest,
534
520
  encryptionData: !encryptionData ? undefined : {
535
521
  ivHex: uint8ArrayToHex(encryptionData.iv),
536
522
  keyHex: uint8ArrayToHex(encryptionData.key),
537
523
  },
524
+ registeredFiles: this.isLegacyTransfer() ? undefined : Array.from(registeredFiles.entries()),
538
525
  };
539
526
  }
540
- static recreate(transferExportData, config, chunkStreamProviderFactory, apiClient, fileServerClientFactory, eventsEngine, optimizer, cryptography) {
527
+ static recreate(transferExportData, config, chunkStreamProviderFactory, apiClient, fileServerClientFactory, eventsEngine, concurrencyController, cryptography, acker) {
541
528
  try {
542
529
  TransferUpload.validateRecreateParams(transferExportData);
543
- 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);
544
531
  transfer.#transferMetadata = this.recreateTransferMetadata(transferExportData.transferMetadata);
545
532
  transfer.#transferState = new TransferUploadState(transferExportData.info.files, eventsEngine, config.currentRatesTimespanInMs, config.progressEventThrottlingInMs, transferExportData.state);
546
533
  return transfer;
@@ -555,13 +542,14 @@ export default class TransferUpload {
555
542
  static recreateTransferMetadata(transferMetadata) {
556
543
  if (!transferMetadata)
557
544
  return undefined;
558
- const { encryptionData, ...rest } = transferMetadata;
545
+ const { encryptionData, registeredFiles, ...rest } = transferMetadata;
559
546
  return {
560
547
  ...rest,
561
548
  encryptionData: !encryptionData ? undefined : {
562
549
  iv: hexToUint8Array(encryptionData.ivHex),
563
550
  key: hexToUint8Array(encryptionData.keyHex),
564
551
  },
552
+ registeredFiles: registeredFiles ? new Map(registeredFiles) : undefined,
565
553
  };
566
554
  }
567
555
  static validateRecreateParams(transferExportData) {