filemail-sdk 4.5.1 → 4.6.1

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 (68) hide show
  1. package/dist/src/client/downloaderCore.js +16 -28
  2. package/dist/src/client/downloaderCore.js.map +1 -1
  3. package/dist/src/client/loggers/dummyLogger.d.ts +1 -0
  4. package/dist/src/client/loggers/dummyLogger.js +1 -0
  5. package/dist/src/client/loggers/dummyLogger.js.map +1 -1
  6. package/dist/src/client/loggers/logger.d.ts +7 -0
  7. package/dist/src/client/node/nodeTransferDownloader.d.ts +3 -1
  8. package/dist/src/client/node/nodeTransferDownloader.js +13 -4
  9. package/dist/src/client/node/nodeTransferDownloader.js.map +1 -1
  10. package/dist/src/client/node/nodeTransferUploader.d.ts +5 -0
  11. package/dist/src/client/node/nodeTransferUploader.js +46 -28
  12. package/dist/src/client/node/nodeTransferUploader.js.map +1 -1
  13. package/dist/src/client/transferDownloader.d.ts +1 -1
  14. package/dist/src/client/transferUploaderOptions.d.ts +1 -0
  15. package/dist/src/downloader/chunkDownloader.js +10 -8
  16. package/dist/src/downloader/chunkDownloader.js.map +1 -1
  17. package/dist/src/downloader/downloadOptions.d.ts +5 -16
  18. package/dist/src/downloader/downloadOptions.js +7 -18
  19. package/dist/src/downloader/downloadOptions.js.map +1 -1
  20. package/dist/src/downloader/downloadStatus/downloadFileProgress.d.ts +2 -1
  21. package/dist/src/downloader/downloadStatus/downloadFileProgress.js +2 -1
  22. package/dist/src/downloader/downloadStatus/downloadFileProgress.js.map +1 -1
  23. package/dist/src/downloader/downloadStatus/downloadFilePromise.d.ts +6 -0
  24. package/dist/src/downloader/downloadStatus/downloadFilePromise.js +32 -0
  25. package/dist/src/downloader/downloadStatus/downloadFilePromise.js.map +1 -0
  26. package/dist/src/downloader/downloadStatus/downloadState.d.ts +2 -1
  27. package/dist/src/downloader/downloadStatus/downloadState.js +40 -18
  28. package/dist/src/downloader/downloadStatus/downloadState.js.map +1 -1
  29. package/dist/src/downloader/downloadTracker.js +219 -130
  30. package/dist/src/downloader/downloadTracker.js.map +1 -1
  31. package/dist/src/downloader/dtos/downloadCommand.d.ts +2 -2
  32. package/dist/src/downloader/dtos/downloadErrorCode.d.ts +8 -1
  33. package/dist/src/downloader/dtos/downloadErrorCode.js +7 -0
  34. package/dist/src/downloader/dtos/downloadErrorCode.js.map +1 -1
  35. package/dist/src/downloader/dtos/downloadEvent.d.ts +3 -1
  36. package/dist/src/downloader/dtos/downloadEvent.js +2 -0
  37. package/dist/src/downloader/dtos/downloadEvent.js.map +1 -1
  38. package/dist/src/downloader/dtos/downloadFileChunkInfo.d.ts +13 -0
  39. package/dist/src/downloader/dtos/downloadFileChunkInfo.js.map +1 -1
  40. package/dist/src/downloader/dtos/downloadFileInfo.d.ts +11 -7
  41. package/dist/src/downloader/dtos/downloadFileInfo.js +14 -9
  42. package/dist/src/downloader/dtos/downloadFileInfo.js.map +1 -1
  43. package/dist/src/downloader/dtos/downloadTrackerFileInfo.d.ts +13 -9
  44. package/dist/src/downloader/dtos/downloadTrackerFileProgressInfo.d.ts +22 -0
  45. package/dist/src/downloader/dtos/downloadTrackerFileProgressInfo.js +2 -0
  46. package/dist/src/downloader/dtos/downloadTrackerFileProgressInfo.js.map +1 -0
  47. package/dist/src/downloader/dtos/downloadTrackerProgressInfo.d.ts +2 -2
  48. package/dist/src/downloader/eventArgs/downloadTrackingFailedEventArgs.d.ts +8 -0
  49. package/dist/src/downloader/eventArgs/downloadTrackingFailedEventArgs.js +2 -0
  50. package/dist/src/downloader/eventArgs/downloadTrackingFailedEventArgs.js.map +1 -0
  51. package/dist/src/downloader/filesDownloader.js +169 -80
  52. package/dist/src/downloader/filesDownloader.js.map +1 -1
  53. package/dist/src/downloader/filesPreparer.js +2 -6
  54. package/dist/src/downloader/filesPreparer.js.map +1 -1
  55. package/dist/src/utils/api/dtos/getTransferRequest.d.ts +2 -0
  56. package/dist/src/utils/api/node/nodeApiClient.js +11 -1
  57. package/dist/src/utils/api/node/nodeApiClient.js.map +1 -1
  58. package/dist/src/utils/fileSystem/fileSystemService.d.ts +6 -1
  59. package/dist/src/utils/fileSystem/node/nodeFileSystemService.d.ts +6 -1
  60. package/dist/src/utils/fileSystem/node/nodeFileSystemService.js +39 -7
  61. package/dist/src/utils/fileSystem/node/nodeFileSystemService.js.map +1 -1
  62. package/dist/src/utils/fileSystem/parsedPath.d.ts +8 -0
  63. package/dist/src/utils/fileSystem/parsedPath.js +2 -0
  64. package/dist/src/utils/fileSystem/parsedPath.js.map +1 -0
  65. package/dist/src/utils/pseudoRandom.d.ts +2 -1
  66. package/dist/src/utils/pseudoRandom.js +4 -1
  67. package/dist/src/utils/pseudoRandom.js.map +1 -1
  68. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"downloadEvent.js","sourceRoot":"","sources":["../../../../src/downloader/dtos/downloadEvent.ts"],"names":[],"mappings":"AAAA,IAAK,qBA0BJ;AA1BD,WAAK,qBAAqB;IACtB,4DAAmC,CAAA;IACnC,kEAAyC,CAAA;IACzC,gEAAuC,CAAA;IACvC,wFAA+D,CAAA;IAC/D,sDAA6B,CAAA;IAC7B,oDAA2B,CAAA;IAC3B,sEAA6C,CAAA;IAC7C,oEAA2C,CAAA;IAC3C,wEAA+C,CAAA;IAC/C,0EAAiD,CAAA;IACjD,kEAAyC,CAAA;IACzC,sEAA6C,CAAA;IAC7C,4EAAmD,CAAA;IACnD,0EAAiD,CAAA;IACjD,oEAA2C,CAAA;IAC3C,oEAA2C,CAAA;IAC3C,8CAAqB,CAAA;IACrB,4CAAmB,CAAA;IACnB,4CAAmB,CAAA;IACnB,4CAAmB,CAAA;IACnB,0CAAiB,CAAA;IACjB,0DAAiC,CAAA;IACjC,gDAAuB,CAAA;IACvB,0EAAiD,CAAA;IACjD,sFAA6D,CAAA;AACjE,CAAC,EA1BI,qBAAqB,KAArB,qBAAqB,QA0BzB;AAED,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"downloadEvent.js","sourceRoot":"","sources":["../../../../src/downloader/dtos/downloadEvent.ts"],"names":[],"mappings":"AAAA,IAAK,qBA4BJ;AA5BD,WAAK,qBAAqB;IACtB,4DAAmC,CAAA;IACnC,kEAAyC,CAAA;IACzC,gEAAuC,CAAA;IACvC,wFAA+D,CAAA;IAC/D,sDAA6B,CAAA;IAC7B,oDAA2B,CAAA;IAC3B,sEAA6C,CAAA;IAC7C,oEAA2C,CAAA;IAC3C,0EAAiD,CAAA;IACjD,wEAA+C,CAAA;IAC/C,0EAAiD,CAAA;IACjD,kEAAyC,CAAA;IACzC,sEAA6C,CAAA;IAC7C,4EAAmD,CAAA;IACnD,0EAAiD,CAAA;IACjD,oEAA2C,CAAA;IAC3C,oEAA2C,CAAA;IAC3C,8CAAqB,CAAA;IACrB,4CAAmB,CAAA;IACnB,4CAAmB,CAAA;IACnB,4CAAmB,CAAA;IACnB,0CAAiB,CAAA;IACjB,0DAAiC,CAAA;IACjC,gDAAuB,CAAA;IACvB,0EAAiD,CAAA;IACjD,sFAA6D,CAAA;IAC7D,0EAAiD,CAAA;AACrD,CAAC,EA5BI,qBAAqB,KAArB,qBAAqB,QA4BzB;AAED,eAAe,qBAAqB,CAAC"}
@@ -3,9 +3,22 @@ import type DownloadFileInfo from "./downloadFileInfo";
3
3
  export default class DownloadFileChunkInfo {
4
4
  readonly id: string;
5
5
  readonly file: DownloadFileInfo;
6
+ /**
7
+ * Zero-based index of first byte of this chunk within a file.
8
+ */
6
9
  readonly start: number | null;
10
+ /**
11
+ * Zero-based index of last byte of this chunk within a file.
12
+ */
7
13
  readonly end: number | null;
14
+ /**
15
+ * Zero-based index of the chunk within a file.
16
+ */
8
17
  readonly chunkNumber: number;
18
+ /**
19
+ * The real chunk size in bytes (no matter of downloader chunkSize setting). For unspecified downloader chunkSize
20
+ * this will equal to file size. Otherwise it is calculated as end-start+1
21
+ */
9
22
  readonly chunkSize: number;
10
23
  isCompleted: boolean;
11
24
  isFailed: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"downloadFileChunkInfo.js","sourceRoot":"","sources":["../../../../src/downloader/dtos/downloadFileChunkInfo.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,OAAO,OAAO,qBAAqB;IAatC,YAAY,IAAsB,EAAE,WAAmB,EAAE,YAA2B;QANpF,gBAAW,GAAG,KAAK,CAAC;QACpB,aAAQ,GAAG,KAAK,CAAC;QACjB,YAAO,GAAyB,IAAI,CAAC;QACrC,oBAAe,GAAG,CAAC,CAAC;QACpB,YAAO,GAAG,CAAC,CAAC;QAGR,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,WAAW,EAAE,CAAC;QAC9C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,YAAY,KAAK,IAAI,EAAE;YACvB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YAClB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;YAChB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC;SACrC;aACI;YACD,IAAI,CAAC,KAAK,GAAG,WAAW,GAAG,YAAa,CAAC;YACzC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,GAAG,YAAa,GAAG,CAAC,CAAC,CAAC;YAC1E,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;SAC9C;IACL,CAAC;IAED,IAAI,CAAC,MAAqB;QACtB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IAC1B,CAAC;IAED,QAAQ;QACJ,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,WAAW,CAAC,eAAuB;QAC/B,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC;YACpB,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;;YAEnB,IAAI,CAAC,OAAO,GAAG,CAAC,GAAG,GAAG,eAAe,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;IAChE,CAAC;CACJ"}
1
+ {"version":3,"file":"downloadFileChunkInfo.js","sourceRoot":"","sources":["../../../../src/downloader/dtos/downloadFileChunkInfo.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,OAAO,OAAO,qBAAqB;IA4BtC,YAAY,IAAsB,EAAE,WAAmB,EAAE,YAA2B;QANpF,gBAAW,GAAG,KAAK,CAAC;QACpB,aAAQ,GAAG,KAAK,CAAC;QACjB,YAAO,GAAyB,IAAI,CAAC;QACrC,oBAAe,GAAG,CAAC,CAAC;QACpB,YAAO,GAAG,CAAC,CAAC;QAGR,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,WAAW,EAAE,CAAC;QAC9C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,YAAY,KAAK,IAAI,EAAE;YACvB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YAClB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;YAChB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC;SACrC;aACI;YACD,IAAI,CAAC,KAAK,GAAG,WAAW,GAAG,YAAa,CAAC;YACzC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,GAAG,YAAa,GAAG,CAAC,CAAC,CAAC;YAC1E,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;SAC9C;IACL,CAAC;IAED,IAAI,CAAC,MAAqB;QACtB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IAC1B,CAAC;IAED,QAAQ;QACJ,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,WAAW,CAAC,eAAuB;QAC/B,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC;YACpB,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;;YAEnB,IAAI,CAAC,OAAO,GAAG,CAAC,GAAG,GAAG,eAAe,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;IAChE,CAAC;CACJ"}
@@ -11,6 +11,7 @@ export default class DownloadFileInfo {
11
11
  isCompleted: boolean;
12
12
  isFailed: boolean;
13
13
  lastSuccessfulChunkNumber: number | null;
14
+ temporaryDownloadPath: string | null;
14
15
  /**
15
16
  * How many bytes have been downloaded counting only completed chunks.
16
17
  */
@@ -24,25 +25,28 @@ export default class DownloadFileInfo {
24
25
  chunkCount: number;
25
26
  chunks: DownloadFileChunkInfo[];
26
27
  failures: DownloadError[];
27
- downloadName: string | null;
28
28
  /**
29
29
  * @param externalId ID of the file - returned in Filemail web API transfer response.
30
30
  * @param url Absolute url to the file on Fileserver.
31
31
  * @param name File name as it is returned from Filemail web API (relative to transfer folder, / is the path separator - api convention).
32
32
  * @param sizeInBytes Size of the file - obtained from Filemail web API transfer response.
33
- * @param downloadPath Optional: aboslute download path where the file should be saved. When null: it will be set automatically by the downloader
34
- * based on download folder + the {@link name}, or {@link downloadName} if specified.
35
- * @param downloadName Use it to override the 'name' property when building final download location. E.g. /path/to/file.txt.
36
- * When {@link downloadPath} is specified this field has no effect.
33
+ * @param downloadPath Optional: absolute download path where the file should be saved. This param is also used when restoring interrupted download.
34
+ * When this parameter is null it will be set automatically by the downloader based on download folder (configured in the downloader) + {@link name}.
35
+ * @param chunkCount How many chunks this file contains. Note: zero-byte (empty) files have 1 chunk.
36
+ * @param temporaryDownloadPath Temporary download path - where the file is physically download until it is complete (and then renamed to {@link downloadPath}).
37
37
  */
38
- constructor(externalId: string, url: string, name: string, sizeInBytes: number, downloadPath?: string | null, downloadName?: string | null, chunkCount?: number | null);
38
+ constructor(externalId: string, url: string, name: string, sizeInBytes: number, downloadPath?: string | null, chunkCount?: number | null, temporaryDownloadPath?: string | null);
39
39
  start(): void;
40
40
  starting(): void;
41
41
  fail(reason: DownloadError): void;
42
- complete(): void;
42
+ complete(finalDownloadPath: string): void;
43
43
  chunkStarted(chunk: DownloadFileChunkInfo): void;
44
44
  chunkCompleted(chunk: DownloadFileChunkInfo): void;
45
45
  chunkFailed(chunk: DownloadFileChunkInfo): void;
46
+ /**
47
+ * Updates file's {@link downloadedBytes} by adding number of downloaded bytes of every pending chunk to {@link downloadedBytes_bank}.
48
+ * Once {@link downloadedBytes} is updated - progress in percent is updated too ({@link percent}).
49
+ */
46
50
  updateProgress(): void;
47
51
  get lastProgressTick(): number | null;
48
52
  get hasDownloadPath(): boolean;
@@ -16,12 +16,12 @@ class DownloadFileInfo {
16
16
  * @param url Absolute url to the file on Fileserver.
17
17
  * @param name File name as it is returned from Filemail web API (relative to transfer folder, / is the path separator - api convention).
18
18
  * @param sizeInBytes Size of the file - obtained from Filemail web API transfer response.
19
- * @param downloadPath Optional: aboslute download path where the file should be saved. When null: it will be set automatically by the downloader
20
- * based on download folder + the {@link name}, or {@link downloadName} if specified.
21
- * @param downloadName Use it to override the 'name' property when building final download location. E.g. /path/to/file.txt.
22
- * When {@link downloadPath} is specified this field has no effect.
19
+ * @param downloadPath Optional: absolute download path where the file should be saved. This param is also used when restoring interrupted download.
20
+ * When this parameter is null it will be set automatically by the downloader based on download folder (configured in the downloader) + {@link name}.
21
+ * @param chunkCount How many chunks this file contains. Note: zero-byte (empty) files have 1 chunk.
22
+ * @param temporaryDownloadPath Temporary download path - where the file is physically download until it is complete (and then renamed to {@link downloadPath}).
23
23
  */
24
- constructor(externalId, url, name, sizeInBytes, downloadPath = null, downloadName = null, chunkCount = null) {
24
+ constructor(externalId, url, name, sizeInBytes, downloadPath = null, chunkCount = null, temporaryDownloadPath = null) {
25
25
  _DownloadFileInfo_lastProgressTick.set(this, null);
26
26
  _DownloadFileInfo_downloadPath.set(this, null);
27
27
  _DownloadFileInfo_pendingChunks.set(this, []);
@@ -31,6 +31,7 @@ class DownloadFileInfo {
31
31
  this.isCompleted = false;
32
32
  this.isFailed = false;
33
33
  this.lastSuccessfulChunkNumber = null;
34
+ this.temporaryDownloadPath = null;
34
35
  /**
35
36
  * How many bytes have been downloaded counting only completed chunks.
36
37
  */
@@ -48,9 +49,8 @@ class DownloadFileInfo {
48
49
  this.url = url;
49
50
  this.name = name;
50
51
  this.sizeInBytes = sizeInBytes;
51
- if (downloadPath)
52
- __classPrivateFieldSet(this, _DownloadFileInfo_downloadPath, downloadPath, "f");
53
- this.downloadName = downloadName;
52
+ __classPrivateFieldSet(this, _DownloadFileInfo_downloadPath, downloadPath, "f");
53
+ this.temporaryDownloadPath = temporaryDownloadPath;
54
54
  if (chunkCount !== null)
55
55
  this.chunkCount = chunkCount;
56
56
  }
@@ -64,7 +64,8 @@ class DownloadFileInfo {
64
64
  this.isFailed = true;
65
65
  this.failures.push(reason);
66
66
  }
67
- complete() {
67
+ complete(finalDownloadPath) {
68
+ this.downloadPath = finalDownloadPath;
68
69
  this.isFailed = false;
69
70
  this.isCompleted = true;
70
71
  }
@@ -92,6 +93,10 @@ class DownloadFileInfo {
92
93
  if (idx > -1)
93
94
  __classPrivateFieldGet(this, _DownloadFileInfo_pendingChunks, "f").splice(idx, 1);
94
95
  }
96
+ /**
97
+ * Updates file's {@link downloadedBytes} by adding number of downloaded bytes of every pending chunk to {@link downloadedBytes_bank}.
98
+ * Once {@link downloadedBytes} is updated - progress in percent is updated too ({@link percent}).
99
+ */
95
100
  updateProgress() {
96
101
  __classPrivateFieldSet(this, _DownloadFileInfo_lastProgressTick, new Date().getTime(), "f");
97
102
  let downloaded = this.downloadedBytes_bank;
@@ -1 +1 @@
1
- {"version":3,"file":"downloadFileInfo.js","sourceRoot":"","sources":["../../../../src/downloader/dtos/downloadFileInfo.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"downloadFileInfo.js","sourceRoot":"","sources":["../../../../src/downloader/dtos/downloadFileInfo.ts"],"names":[],"mappings":"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"}
@@ -1,26 +1,30 @@
1
+ /**
2
+ * Note: this is a JSON DTO interface - short property names are to minimize state size on disk in case there are downloads with lots of files.
3
+ */
1
4
  interface DownloadTrackerFileInfo {
2
5
  /**
3
- * External ID (as comes from FS api)
4
- */
5
- id: string;
6
- /**
7
- * Download url
6
+ * Download url.
8
7
  */
9
8
  u: string;
10
9
  /**
11
- * Size in bytes
10
+ * Size in bytes.
12
11
  */
13
12
  s: number;
14
13
  /**
15
- * File name (as comes from FS api)
14
+ * File name (as it came from api, so potentially including folders, separator is always a forward slash). E.g. /some/folder/file.txt
16
15
  */
17
16
  n: string;
18
17
  /**
19
- * Absolute download path
18
+ * Absolute download path - final file download download path. E.g. C:\downloads\file.txt
20
19
  */
21
20
  dp: string;
22
21
  /**
23
- * Number of chunks
22
+ * Temporary download path - physical file download download path until it is complete. Ee.g. C:\downloads\unconfiormed_123456.fmdownload
23
+ * Allows avoiding naming conflicts and indicating to end users that file is in progress.
24
+ */
25
+ tdp: string | null;
26
+ /**
27
+ * Number of chunks.
24
28
  */
25
29
  cc: number;
26
30
  }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Note: this is a JSON DTO interface - short property names are to minimize state size on disk in case there are downloads with lots of files.
3
+ */
4
+ interface DownloadTrackerFileProgressInfo {
5
+ /**
6
+ * Number of last successful chunk (only consecutive chunks count).
7
+ */
8
+ ok: number | null;
9
+ /**
10
+ * Is this file in "failed" state?
11
+ */
12
+ er: boolean;
13
+ /**
14
+ * Is this file in "completed" state?
15
+ */
16
+ c: boolean;
17
+ /**
18
+ * Was this file ever written?
19
+ */
20
+ wr: boolean;
21
+ }
22
+ export default DownloadTrackerFileProgressInfo;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=downloadTrackerFileProgressInfo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"downloadTrackerFileProgressInfo.js","sourceRoot":"","sources":["../../../../src/downloader/dtos/downloadTrackerFileProgressInfo.ts"],"names":[],"mappings":""}
@@ -1,6 +1,6 @@
1
- import type DownloadFileProgress from "../downloadStatus/downloadFileProgress";
1
+ import type DownloadTrackerFileProgressInfo from "./downloadTrackerFileProgressInfo";
2
2
  interface DownloadTrackerProgressInfo {
3
- pendingFiles: Array<DownloadFileProgress>;
3
+ trackedFiles: Record<string, DownloadTrackerFileProgressInfo>;
4
4
  activeTime: number;
5
5
  }
6
6
  export default DownloadTrackerProgressInfo;
@@ -0,0 +1,8 @@
1
+ import type DownloadErrorCode from "../dtos/downloadErrorCode";
2
+ interface DownloadTrackingFailedEventArgs {
3
+ downloadId: string;
4
+ reason: string;
5
+ errorCode: DownloadErrorCode;
6
+ error: Error | null;
7
+ }
8
+ export default DownloadTrackingFailedEventArgs;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=downloadTrackingFailedEventArgs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"downloadTrackingFailedEventArgs.js","sourceRoot":"","sources":["../../../../src/downloader/eventArgs/downloadTrackingFailedEventArgs.ts"],"names":[],"mappings":""}
@@ -9,12 +9,15 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _FilesDownloader_instances, _FilesDownloader_transferId, _FilesDownloader_trackId, _FilesDownloader_downloadId, _FilesDownloader_files, _FilesDownloader_downloadState, _FilesDownloader_options, _FilesDownloader_semaphore, _FilesDownloader_fileSystem, _FilesDownloader_apiClient, _FilesDownloader_fileserverClientFactory, _FilesDownloader_chunkStreamProviderFactory, _FilesDownloader_eventsEngine, _FilesDownloader_deleteEntireDownload, _FilesDownloader_registerTransferDownload, _FilesDownloader_addEventListeners, _FilesDownloader_removeEventListeners, _FilesDownloader_onFileSupersized, _FilesDownloader_onFileFailed;
12
+ var _FilesDownloader_instances, _FilesDownloader_transferId, _FilesDownloader_trackId, _FilesDownloader_downloadId, _FilesDownloader_files, _FilesDownloader_downloadState, _FilesDownloader_options, _FilesDownloader_semaphore, _FilesDownloader_fileSystem, _FilesDownloader_apiClient, _FilesDownloader_fileserverClientFactory, _FilesDownloader_chunkStreamProviderFactory, _FilesDownloader_eventsEngine, _FilesDownloader_ongoingChunkDownloads, _FilesDownloader_ongoingFileDownloads, _FilesDownloader_deleteAllTemporaryAndCompletedFiles, _FilesDownloader_registerTransferDownload, _FilesDownloader_addEventListeners, _FilesDownloader_removeEventListeners, _FilesDownloader_onFileCompleted, _FilesDownloader_onFileCompleting, _FilesDownloader_onFileSupersized, _FilesDownloader_onFileFailed, _FilesDownloader_createDownloadFile, _FilesDownloader_autoGenerateUniqueDownloadFile, _FilesDownloader_downloadAllChunksForFile, _FilesDownloader_downloadSingleChunk, _FilesDownloader_cleanupDownloaderStateAfterFilesLoop, _FilesDownloader_isDownloaderRunning, _FilesDownloader_cleanupEmptyDownloadFolderIfConfigured, _FilesDownloader_doTheFinalFileRenameAfterFilesIsDownloaded;
13
13
  import DownloadState from "./downloadStatus/downloadState.js";
14
14
  import DownloadError from "./dtos/downloadError.js";
15
15
  import TransferDownloadEvent from "./dtos/downloadEvent.js";
16
16
  import ChunkDownloader from "./chunkDownloader.js";
17
17
  import TransferStatus from "../utils/types/transferStatus.js";
18
+ import DownloadErrorCode from "./dtos/downloadErrorCode.js";
19
+ import PseudoRandom from "../utils/pseudoRandom.js";
20
+ import DownloadFilePromise from "./downloadStatus/downloadFilePromise.js";
18
21
  class FilesDownloader {
19
22
  constructor(transferId, trackId, downloadId, files, oldState, fileSystem, semaphore, eventsEngine, options, apiClient, fileserverClientFactory, chunkStreamProviderFactory) {
20
23
  _FilesDownloader_instances.add(this);
@@ -30,13 +33,28 @@ class FilesDownloader {
30
33
  _FilesDownloader_fileserverClientFactory.set(this, void 0);
31
34
  _FilesDownloader_chunkStreamProviderFactory.set(this, void 0);
32
35
  _FilesDownloader_eventsEngine.set(this, void 0);
36
+ _FilesDownloader_ongoingChunkDownloads.set(this, void 0);
37
+ _FilesDownloader_ongoingFileDownloads.set(this, void 0);
38
+ _FilesDownloader_onFileCompleted.set(this, async (args) => {
39
+ __classPrivateFieldGet(this, _FilesDownloader_ongoingFileDownloads, "f")[args.file.id]?.complete();
40
+ });
41
+ _FilesDownloader_onFileCompleting.set(this, async (args) => {
42
+ // note the args.file.downloadPath may not be final - if a file with this name eixsts the following method will generate new name e.g. "file.txt" --> "file (1).txt"
43
+ const finalDownloadPath = await __classPrivateFieldGet(this, _FilesDownloader_instances, "m", _FilesDownloader_doTheFinalFileRenameAfterFilesIsDownloaded).call(this, args.file);
44
+ __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileCompleted(args.file.id, finalDownloadPath);
45
+ });
33
46
  _FilesDownloader_onFileSupersized.set(this, async (fileArgs) => {
34
- if (await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").getFileSize(fileArgs.file.downloadPath) > fileArgs.file.size)
35
- await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").truncateFile(fileArgs.file.downloadPath, fileArgs.file.size);
47
+ if (fileArgs.file.temporaryDownloadPath && await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").getFileSize(fileArgs.file.temporaryDownloadPath) > fileArgs.file.size)
48
+ await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").truncateFile(fileArgs.file.temporaryDownloadPath, fileArgs.file.size);
36
49
  });
37
50
  _FilesDownloader_onFileFailed.set(this, async (args) => {
38
- if (__classPrivateFieldGet(this, _FilesDownloader_options, "f").deleteFailedFilesFromDisk)
39
- await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").deleteFile(args.file.downloadPath);
51
+ __classPrivateFieldGet(this, _FilesDownloader_ongoingFileDownloads, "f")[args.file.id]?.complete();
52
+ if (__classPrivateFieldGet(this, _FilesDownloader_options, "f").deleteFailedFilesFromDisk) {
53
+ if (args.file.downloadPath && args.file.downloaded > 0)
54
+ await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").deleteFile(args.file.downloadPath);
55
+ if (args.file.temporaryDownloadPath)
56
+ await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").deleteFile(args.file.temporaryDownloadPath);
57
+ }
40
58
  });
41
59
  if (!transferId)
42
60
  throw new DownloadError(`No transfer specified`);
@@ -58,99 +76,68 @@ class FilesDownloader {
58
76
  __classPrivateFieldSet(this, _FilesDownloader_apiClient, apiClient, "f");
59
77
  __classPrivateFieldSet(this, _FilesDownloader_fileserverClientFactory, fileserverClientFactory, "f");
60
78
  __classPrivateFieldSet(this, _FilesDownloader_chunkStreamProviderFactory, chunkStreamProviderFactory, "f");
79
+ __classPrivateFieldSet(this, _FilesDownloader_ongoingChunkDownloads, {}, "f");
80
+ __classPrivateFieldSet(this, _FilesDownloader_ongoingFileDownloads, {}, "f");
61
81
  }
62
82
  async start() {
63
83
  try {
64
- let fileDownloaderIsFinished = false;
65
84
  __classPrivateFieldGet(this, _FilesDownloader_instances, "m", _FilesDownloader_addEventListeners).call(this);
66
- while (fileDownloaderIsFinished === false) {
85
+ let isDownloaderRunning = true;
86
+ while (isDownloaderRunning) {
67
87
  __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").start();
68
- const ongoingChunkDownloads = {};
69
88
  // MAIN FILE LOOP
70
89
  for (const file of __classPrivateFieldGet(this, _FilesDownloader_files, "f")) {
71
90
  if (file.isCompleted || file.isFailed)
72
91
  continue;
73
- const fileExistsAndHasCorrectSize = await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").pathExists(file.downloadPath)
74
- && await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").getFileSize(file.downloadPath) === file.sizeInBytes;
75
- if (__classPrivateFieldGet(this, _FilesDownloader_options, "f").preventOverwrites && fileExistsAndHasCorrectSize && file.wasEverWritten === false) {
76
- // TODO: adjust total progress accordingly, but we can't just add bytes - this will ruin download speed calc...
77
- // see https://filemail.atlassian.net/browse/FILEMAIL-3537
78
- file.downloadedBytes_bank = file.sizeInBytes;
79
- file.updateProgress();
80
- if (__classPrivateFieldGet(this, _FilesDownloader_options, "f").failFileWhenPreventingOverwrite)
81
- __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileFailed(file, new DownloadError(`File ${file.downloadPath} already exists and download option "preventOverwrites" is set to true`));
82
- else
83
- __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileCompleted(file);
84
- continue;
85
- }
86
- __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileStarting(file);
87
- if (fileExistsAndHasCorrectSize === false) {
88
- try {
89
- __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileCreating(file);
90
- await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").createFile(file.downloadPath, file.sizeInBytes);
91
- __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileCreated(file);
92
- }
93
- catch (fileWriteErr) {
94
- const errorCode = __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").fileErrorToDownloadErrorCode(fileWriteErr);
95
- __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileFailed(file, new DownloadError(`File ${file.downloadPath} could not be created with specific size. See 'cause' for more details.`, { cause: fileWriteErr }, errorCode));
92
+ if (__classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").isRunning === false)
93
+ break;
94
+ // figure out if we are downloading a new file or resuming a file that was interrupted
95
+ if (file.wasEverWritten) {
96
+ // this a resumed file (recreated from progress.json) - it must already exist under its temporary path
97
+ if (!file.temporaryDownloadPath) {
98
+ __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileFailed(file, new DownloadError(`File ${file.downloadPath} was supposed to be resumed but its temporary path is not known.`, undefined, DownloadErrorCode.ResumedFilePathNotSpecified));
96
99
  continue;
97
100
  }
98
- }
99
- if (file.chunks.length) {
100
- // MAIN CHUNK LOOP
101
- for (const chunk of file.chunks) {
102
- if (chunk.isCompleted || chunk.isFailed)
103
- continue;
104
- const releaseSemaphore = await __classPrivateFieldGet(this, _FilesDownloader_semaphore, "f").acquire();
105
- if (__classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").isRunning === false) {
106
- // downloader is not running - stop trying more chunks
107
- releaseSemaphore();
108
- break;
109
- }
110
- if (file.isFailed) {
111
- // do not try to download more chunks if the file has failed
112
- releaseSemaphore();
113
- break;
114
- }
115
- const chunkDownloader = new ChunkDownloader(__classPrivateFieldGet(this, _FilesDownloader_transferId, "f"), file, chunk, __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f"), __classPrivateFieldGet(this, _FilesDownloader_options, "f"), __classPrivateFieldGet(this, _FilesDownloader_fileserverClientFactory, "f"), __classPrivateFieldGet(this, _FilesDownloader_chunkStreamProviderFactory, "f"), __classPrivateFieldGet(this, _FilesDownloader_eventsEngine, "f"));
116
- const chunkPromise = chunkDownloader.download();
117
- ongoingChunkDownloads[chunk.id] = chunkPromise;
118
- chunkPromise.finally(() => {
119
- releaseSemaphore();
120
- delete ongoingChunkDownloads[chunk.id];
121
- });
101
+ if ((await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").pathExists(file.temporaryDownloadPath)) === false) {
102
+ __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileFailed(file, new DownloadError(`File ${file.downloadPath} was supposed to be resumed at ${file.temporaryDownloadPath}, but it does not exist on disk anymore.`, undefined, DownloadErrorCode.ResumedFileNotFound));
103
+ continue;
122
104
  }
123
- if (__classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").isRunning === false)
124
- break;
125
105
  }
126
106
  else {
127
- // zerobyte file
128
- file.updateProgress();
129
- __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileCompleted(file);
107
+ // in some edge cases the temporary file may exist nad its name be persisted in the tracker file
108
+ // but the wasEverWrittenFlag was not yet set - just abandon such temporary file (it will be 'empty' - null bytes only)
109
+ if (file.temporaryDownloadPath)
110
+ __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").deleteFile(file.temporaryDownloadPath);
111
+ // this is a new file - create it
112
+ await __classPrivateFieldGet(this, _FilesDownloader_instances, "m", _FilesDownloader_createDownloadFile).call(this, file);
130
113
  }
114
+ __classPrivateFieldGet(this, _FilesDownloader_ongoingFileDownloads, "f")[file.externalId] = new DownloadFilePromise(file.externalId);
115
+ __classPrivateFieldGet(this, _FilesDownloader_ongoingFileDownloads, "f")[file.externalId].awaiter.then(id => {
116
+ delete __classPrivateFieldGet(this, _FilesDownloader_ongoingFileDownloads, "f")[id];
117
+ });
118
+ __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileStarting(file);
119
+ // note: this call does not really wait for all chunks to be downloaded, but until all chunks of a file have been **scheduled**
120
+ await __classPrivateFieldGet(this, _FilesDownloader_instances, "m", _FilesDownloader_downloadAllChunksForFile).call(this, file);
121
+ // so when we are here, the file is not complete
122
+ // to track completeness of a file we look at events emitted by this.#downloadState
131
123
  }
132
- // wait for remaining pending chunks
133
- await Promise.allSettled(Object.values(ongoingChunkDownloads));
134
124
  // when we got here it's either pause request, stop request (which is just like pause but without waiting for pending chunks), abort request (cancel the download entirely) or everything is complete;
125
+ // wait for any remaining pending chunks
126
+ await Promise.allSettled(Object.values(__classPrivateFieldGet(this, _FilesDownloader_ongoingChunkDownloads, "f")));
127
+ // wait for any remaining pending files
128
+ // note: we cannot rely just on chunk downloads being completed, because downloading chunks
129
+ // doesn't a file is complete; last phase of file completion is actually renaming the file
130
+ // from a temporary name (unconfirmed_123.fmdownload) to its real name (which may need adjustments if a file with same already exists
131
+ // in such case a rename will be executed automatically e.g. file.txt --> file (1).txt).
132
+ await Promise.allSettled(Object.values(__classPrivateFieldGet(this, _FilesDownloader_ongoingFileDownloads, "f")).map(x => x.awaiter));
135
133
  if (__classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").status === TransferStatus.Pausing) {
136
- // set status to paused and await until resume/abort; the main while loop based on `fileDownloaderIsFinished` will continue;
134
+ // set status to paused and await until resume/abort
137
135
  await __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").paused();
138
136
  }
139
- if (__classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").status === TransferStatus.Aborting) {
140
- __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").aborted();
141
- if (__classPrivateFieldGet(this, _FilesDownloader_options, "f").deleteAbortedDownloadsFromDisk)
142
- await __classPrivateFieldGet(this, _FilesDownloader_instances, "m", _FilesDownloader_deleteEntireDownload).call(this);
143
- }
144
- else if (__classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").allFilesCompletedOrFailed) {
145
- await __classPrivateFieldGet(this, _FilesDownloader_instances, "m", _FilesDownloader_registerTransferDownload).call(this);
146
- __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").completed();
147
- }
148
- if (__classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").status === TransferStatus.Completed || __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").status === TransferStatus.Aborted) {
149
- fileDownloaderIsFinished = true;
150
- if (__classPrivateFieldGet(this, _FilesDownloader_options, "f").deleteEmptyDownloadFoldersAfterDownload && await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").folderIsEmpty(__classPrivateFieldGet(this, _FilesDownloader_options, "f").downloadFolder))
151
- await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").deleteFolder(__classPrivateFieldGet(this, _FilesDownloader_options, "f").downloadFolder);
152
- }
137
+ await __classPrivateFieldGet(this, _FilesDownloader_instances, "m", _FilesDownloader_cleanupDownloaderStateAfterFilesLoop).call(this);
138
+ isDownloaderRunning = __classPrivateFieldGet(this, _FilesDownloader_instances, "m", _FilesDownloader_isDownloaderRunning).call(this);
153
139
  }
140
+ await __classPrivateFieldGet(this, _FilesDownloader_instances, "m", _FilesDownloader_cleanupEmptyDownloadFolderIfConfigured).call(this);
154
141
  return __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").getCurrentState(true);
155
142
  }
156
143
  catch (error) {
@@ -165,15 +152,18 @@ class FilesDownloader {
165
152
  }
166
153
  }
167
154
  requestPause() {
155
+ Object.values(__classPrivateFieldGet(this, _FilesDownloader_ongoingFileDownloads, "f")).forEach(filePromise => filePromise.complete());
168
156
  return __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").requestPause({ interruptPendingChunks: false });
169
157
  }
170
158
  requestStop() {
159
+ Object.values(__classPrivateFieldGet(this, _FilesDownloader_ongoingFileDownloads, "f")).forEach(filePromise => filePromise.complete());
171
160
  return __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").requestPause({ interruptPendingChunks: true });
172
161
  }
173
162
  resume() {
174
163
  return __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").resume();
175
164
  }
176
165
  requestAbort() {
166
+ Object.values(__classPrivateFieldGet(this, _FilesDownloader_ongoingFileDownloads, "f")).forEach(filePromise => filePromise.complete());
177
167
  return __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").requestAbort();
178
168
  }
179
169
  get currentState() {
@@ -183,9 +173,13 @@ class FilesDownloader {
183
173
  return __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").status;
184
174
  }
185
175
  }
186
- _FilesDownloader_transferId = new WeakMap(), _FilesDownloader_trackId = new WeakMap(), _FilesDownloader_downloadId = new WeakMap(), _FilesDownloader_files = new WeakMap(), _FilesDownloader_downloadState = new WeakMap(), _FilesDownloader_options = new WeakMap(), _FilesDownloader_semaphore = new WeakMap(), _FilesDownloader_fileSystem = new WeakMap(), _FilesDownloader_apiClient = new WeakMap(), _FilesDownloader_fileserverClientFactory = new WeakMap(), _FilesDownloader_chunkStreamProviderFactory = new WeakMap(), _FilesDownloader_eventsEngine = new WeakMap(), _FilesDownloader_onFileSupersized = new WeakMap(), _FilesDownloader_onFileFailed = new WeakMap(), _FilesDownloader_instances = new WeakSet(), _FilesDownloader_deleteEntireDownload = async function _FilesDownloader_deleteEntireDownload() {
187
- for (const file of __classPrivateFieldGet(this, _FilesDownloader_files, "f"))
188
- await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").deleteFile(file.downloadPath);
176
+ _FilesDownloader_transferId = new WeakMap(), _FilesDownloader_trackId = new WeakMap(), _FilesDownloader_downloadId = new WeakMap(), _FilesDownloader_files = new WeakMap(), _FilesDownloader_downloadState = new WeakMap(), _FilesDownloader_options = new WeakMap(), _FilesDownloader_semaphore = new WeakMap(), _FilesDownloader_fileSystem = new WeakMap(), _FilesDownloader_apiClient = new WeakMap(), _FilesDownloader_fileserverClientFactory = new WeakMap(), _FilesDownloader_chunkStreamProviderFactory = new WeakMap(), _FilesDownloader_eventsEngine = new WeakMap(), _FilesDownloader_ongoingChunkDownloads = new WeakMap(), _FilesDownloader_ongoingFileDownloads = new WeakMap(), _FilesDownloader_onFileCompleted = new WeakMap(), _FilesDownloader_onFileCompleting = new WeakMap(), _FilesDownloader_onFileSupersized = new WeakMap(), _FilesDownloader_onFileFailed = new WeakMap(), _FilesDownloader_instances = new WeakSet(), _FilesDownloader_deleteAllTemporaryAndCompletedFiles = async function _FilesDownloader_deleteAllTemporaryAndCompletedFiles() {
177
+ for (const file of __classPrivateFieldGet(this, _FilesDownloader_files, "f")) {
178
+ if (file.temporaryDownloadPath)
179
+ await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").deleteFile(file.temporaryDownloadPath);
180
+ if (file.isCompleted)
181
+ await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").deleteFile(file.downloadPath);
182
+ }
189
183
  }, _FilesDownloader_registerTransferDownload = async function _FilesDownloader_registerTransferDownload() {
190
184
  __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").registeringTransferDownload();
191
185
  await __classPrivateFieldGet(this, _FilesDownloader_apiClient, "f").registerTransferDownload({
@@ -195,11 +189,106 @@ _FilesDownloader_transferId = new WeakMap(), _FilesDownloader_trackId = new Weak
195
189
  browser: __classPrivateFieldGet(this, _FilesDownloader_options, "f").userAgent,
196
190
  });
197
191
  }, _FilesDownloader_addEventListeners = function _FilesDownloader_addEventListeners() {
192
+ __classPrivateFieldGet(this, _FilesDownloader_eventsEngine, "f").addEventListener(TransferDownloadEvent.FileDownloadCompleted, __classPrivateFieldGet(this, _FilesDownloader_onFileCompleted, "f"));
193
+ __classPrivateFieldGet(this, _FilesDownloader_eventsEngine, "f").addEventListener(TransferDownloadEvent.FileDownloadCompleting, __classPrivateFieldGet(this, _FilesDownloader_onFileCompleting, "f"));
198
194
  __classPrivateFieldGet(this, _FilesDownloader_eventsEngine, "f").addEventListener(TransferDownloadEvent.FileDownloadFailed, __classPrivateFieldGet(this, _FilesDownloader_onFileFailed, "f"));
199
195
  __classPrivateFieldGet(this, _FilesDownloader_eventsEngine, "f").addEventListener(TransferDownloadEvent.PossibleSupersizedFile, __classPrivateFieldGet(this, _FilesDownloader_onFileSupersized, "f"));
200
196
  }, _FilesDownloader_removeEventListeners = function _FilesDownloader_removeEventListeners() {
197
+ __classPrivateFieldGet(this, _FilesDownloader_eventsEngine, "f").removeEventListener(TransferDownloadEvent.FileDownloadCompleted, __classPrivateFieldGet(this, _FilesDownloader_onFileCompleted, "f"));
198
+ __classPrivateFieldGet(this, _FilesDownloader_eventsEngine, "f").removeEventListener(TransferDownloadEvent.FileDownloadCompleting, __classPrivateFieldGet(this, _FilesDownloader_onFileCompleting, "f"));
201
199
  __classPrivateFieldGet(this, _FilesDownloader_eventsEngine, "f").removeEventListener(TransferDownloadEvent.FileDownloadFailed, __classPrivateFieldGet(this, _FilesDownloader_onFileFailed, "f"));
202
200
  __classPrivateFieldGet(this, _FilesDownloader_eventsEngine, "f").removeEventListener(TransferDownloadEvent.PossibleSupersizedFile, __classPrivateFieldGet(this, _FilesDownloader_onFileSupersized, "f"));
201
+ }, _FilesDownloader_createDownloadFile = async function _FilesDownloader_createDownloadFile(file) {
202
+ __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileCreating(file);
203
+ await __classPrivateFieldGet(this, _FilesDownloader_instances, "m", _FilesDownloader_autoGenerateUniqueDownloadFile).call(this, file);
204
+ __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileCreated(file);
205
+ }, _FilesDownloader_autoGenerateUniqueDownloadFile = async function _FilesDownloader_autoGenerateUniqueDownloadFile(file) {
206
+ let counter = 0;
207
+ do {
208
+ const newFileName = `unconfirmed_${PseudoRandom.generateString(10)}.fmdownload`;
209
+ const newPath = __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").replaceFilenameInPath(file.downloadPath, newFileName);
210
+ if (await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").createFile(newPath, false, file.sizeInBytes)) {
211
+ // eslint-disable-next-line no-param-reassign
212
+ file.temporaryDownloadPath = newPath;
213
+ return;
214
+ }
215
+ counter += 1;
216
+ } while (counter < 10000);
217
+ throw new DownloadError(`Downloader could not generate unique download path for ${file.downloadPath}. It tried until counter=${counter}`, undefined, DownloadErrorCode.TooManyFileRenameAttempts);
218
+ }, _FilesDownloader_downloadAllChunksForFile = async function _FilesDownloader_downloadAllChunksForFile(file) {
219
+ if (file.chunks.length) {
220
+ // MAIN CHUNK LOOP
221
+ for (const chunk of file.chunks) {
222
+ if (chunk.isCompleted || chunk.isFailed)
223
+ continue;
224
+ const downloadScheduled = await __classPrivateFieldGet(this, _FilesDownloader_instances, "m", _FilesDownloader_downloadSingleChunk).call(this, file, chunk);
225
+ if (downloadScheduled === false) {
226
+ // downloader is not running or file is in failed state - stop the chunk loop
227
+ break;
228
+ }
229
+ }
230
+ }
231
+ else {
232
+ // zerobyte file
233
+ file.updateProgress();
234
+ __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").fileCompleting(file);
235
+ }
236
+ }, _FilesDownloader_downloadSingleChunk = async function _FilesDownloader_downloadSingleChunk(file, chunk) {
237
+ const releaseSemaphore = await __classPrivateFieldGet(this, _FilesDownloader_semaphore, "f").acquire();
238
+ if (__classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").isRunning === false) {
239
+ // downloader is not running - stop trying more chunks
240
+ releaseSemaphore();
241
+ return false;
242
+ }
243
+ if (file.isFailed) {
244
+ // do not try to download more chunks if the file has failed
245
+ releaseSemaphore();
246
+ return false;
247
+ }
248
+ const chunkDownloader = new ChunkDownloader(__classPrivateFieldGet(this, _FilesDownloader_transferId, "f"), file, chunk, __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f"), __classPrivateFieldGet(this, _FilesDownloader_options, "f"), __classPrivateFieldGet(this, _FilesDownloader_fileserverClientFactory, "f"), __classPrivateFieldGet(this, _FilesDownloader_chunkStreamProviderFactory, "f"), __classPrivateFieldGet(this, _FilesDownloader_eventsEngine, "f"));
249
+ const chunkPromise = chunkDownloader.download();
250
+ __classPrivateFieldGet(this, _FilesDownloader_ongoingChunkDownloads, "f")[chunk.id] = chunkPromise;
251
+ chunkPromise.finally(() => {
252
+ releaseSemaphore();
253
+ delete __classPrivateFieldGet(this, _FilesDownloader_ongoingChunkDownloads, "f")[chunk.id];
254
+ });
255
+ return true;
256
+ }, _FilesDownloader_cleanupDownloaderStateAfterFilesLoop = async function _FilesDownloader_cleanupDownloaderStateAfterFilesLoop() {
257
+ if (__classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").status === TransferStatus.Aborting) {
258
+ __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").aborted();
259
+ if (__classPrivateFieldGet(this, _FilesDownloader_options, "f").deleteAbortedDownloadsFromDisk)
260
+ await __classPrivateFieldGet(this, _FilesDownloader_instances, "m", _FilesDownloader_deleteAllTemporaryAndCompletedFiles).call(this);
261
+ }
262
+ else if (__classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").allFilesCompletedOrFailed) {
263
+ await __classPrivateFieldGet(this, _FilesDownloader_instances, "m", _FilesDownloader_registerTransferDownload).call(this);
264
+ __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").completed();
265
+ }
266
+ }, _FilesDownloader_isDownloaderRunning = function _FilesDownloader_isDownloaderRunning() {
267
+ return __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").status !== TransferStatus.Completed && __classPrivateFieldGet(this, _FilesDownloader_downloadState, "f").status !== TransferStatus.Aborted;
268
+ }, _FilesDownloader_cleanupEmptyDownloadFolderIfConfigured = async function _FilesDownloader_cleanupEmptyDownloadFolderIfConfigured() {
269
+ if (__classPrivateFieldGet(this, _FilesDownloader_options, "f").deleteEmptyDownloadFoldersAfterDownload && await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").folderIsEmpty(__classPrivateFieldGet(this, _FilesDownloader_options, "f").downloadFolder))
270
+ await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").deleteFolder(__classPrivateFieldGet(this, _FilesDownloader_options, "f").downloadFolder);
271
+ }, _FilesDownloader_doTheFinalFileRenameAfterFilesIsDownloaded = async function _FilesDownloader_doTheFinalFileRenameAfterFilesIsDownloaded(file) {
272
+ let created = false;
273
+ let counter = 0;
274
+ const original = __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").parseFilePath(file.downloadPath);
275
+ let newPathFormatted = file.downloadPath;
276
+ do {
277
+ created = await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").createFile(newPathFormatted, false, file.size);
278
+ if (!created) {
279
+ counter += 1;
280
+ const newPath = {
281
+ dir: original.dir,
282
+ name: `${original.name} (${counter})`,
283
+ ext: original.ext,
284
+ };
285
+ newPathFormatted = __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").formatFilePath(newPath);
286
+ }
287
+ } while (created === false && counter < 10000);
288
+ if (!created)
289
+ throw new DownloadError(`Downloader could not rename temp file ${file.temporaryDownloadPath} to ${file.downloadPath}. It tried until counter=${counter}`, undefined, DownloadErrorCode.TooManyFileRenameAttempts);
290
+ await __classPrivateFieldGet(this, _FilesDownloader_fileSystem, "f").renameFile(file.temporaryDownloadPath, newPathFormatted);
291
+ return newPathFormatted;
203
292
  };
204
293
  export default FilesDownloader;
205
294
  //# sourceMappingURL=filesDownloader.js.map