filemail-sdk 9.2.1 → 9.3.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.
- package/dist/src/client/downloader/downloaderCore.d.ts.map +1 -1
- package/dist/src/client/downloader/downloaderCore.js +2 -0
- package/dist/src/client/downloader/downloaderCore.js.map +1 -1
- package/dist/src/client/healthMonitor/transferHealthMonitorBase.d.ts.map +1 -1
- package/dist/src/client/healthMonitor/transferHealthMonitorBase.js +2 -1
- package/dist/src/client/healthMonitor/transferHealthMonitorBase.js.map +1 -1
- package/dist/src/downloader/api/node/nodeFileServerDownloadClient.js.map +1 -1
- package/dist/src/utils/api/node/nodeFileserverClientBase.d.ts.map +1 -1
- package/dist/src/utils/api/web/webClientBase.js.map +1 -1
- package/dist/src/utils/api/web/webFileserverClientBase.d.ts.map +1 -1
- package/dist/src/utils/crypto/web/webCryptographyProvider.d.ts +1 -0
- package/dist/src/utils/crypto/web/webCryptographyProvider.d.ts.map +1 -1
- package/dist/src/utils/crypto/web/webCryptographyProvider.js +9 -2
- package/dist/src/utils/crypto/web/webCryptographyProvider.js.map +1 -1
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProvider.d.ts.map +1 -1
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProvider.js +1 -1
- package/dist/src/utils/fileSystem/node/nodeChunkStreamProvider.js.map +1 -1
- package/dist/src/utils/fileSystem/web/chunkStreamProvider/webChunkStreamEncrypter.d.ts +1 -0
- package/dist/src/utils/fileSystem/web/chunkStreamProvider/webChunkStreamEncrypter.d.ts.map +1 -1
- package/dist/src/utils/fileSystem/web/chunkStreamProvider/webChunkStreamEncrypter.js +9 -2
- package/dist/src/utils/fileSystem/web/chunkStreamProvider/webChunkStreamEncrypter.js.map +1 -1
- package/package.json +9 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"downloaderCore.d.ts","sourceRoot":"","sources":["../../../../src/client/downloader/downloaderCore.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,eAAe,MAAM,qCAAqC,CAAC;AACvE,OAAO,KAAK,SAAS,MAAM,8BAA8B,CAAC;AAC1D,OAAO,KAAK,iBAAiB,MAAM,6CAA6C,CAAC;AACjF,OAAO,cAAc,MAAM,qCAAqC,CAAC;AAEjE,OAAO,KAAK,YAAY,MAAM,uCAAuC,CAAC;AAGtE,OAAO,KAAK,eAAe,MAAM,0CAA0C,CAAC;AAC5E,OAAO,KAAK,oBAAoB,MAAM,+CAA+C,CAAC;AAEtF,OAAO,KAAK,0BAA0B,MAAM,sDAAsD,CAAC;AACnG,OAAO,KAAK,uBAAuB,MAAM,4CAA4C,CAAC;AACtF,OAAO,KAAK,YAAY,MAAM,oCAAoC,CAAC;AACnE,OAAO,KAAK,iBAAiB,MAAM,6CAA6C,CAAC;AACjF,OAAO,KAAK,cAAc,MAAM,oCAAoC,CAAC;AACrE,OAAO,KAAK,iBAAiB,MAAM,iDAAiD,CAAC;AAGrF,OAAO,KAAK,oBAAoB,MAAM,4CAA4C,CAAC;AACnF,OAAO,KAAK,+BAA+B,MAAM,qDAAqD,CAAC;AAEvG,MAAM,CAAC,OAAO,OAAO,cAAc;;gBAkBnB,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,oBAAoB,EAAE,0BAA0B,CAAC,MAAM,CAAC,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,UAAU,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,aAAa,EAAE,+BAA+B;IAY7U,IAAI,MAAM,IAAI,cAAc,GAAG,IAAI,CAKlC;IAED,IAAI,KAAK,IAAI,iBAAiB,GAAG,IAAI,CAKpC;IAED,IAAI,UAAU,IAAI,MAAM,GAAG,SAAS,CAEnC;IAEK,KAAK,CAAC,OAAO,EAAE;QAAE,sBAAsB,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"downloaderCore.d.ts","sourceRoot":"","sources":["../../../../src/client/downloader/downloaderCore.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,eAAe,MAAM,qCAAqC,CAAC;AACvE,OAAO,KAAK,SAAS,MAAM,8BAA8B,CAAC;AAC1D,OAAO,KAAK,iBAAiB,MAAM,6CAA6C,CAAC;AACjF,OAAO,cAAc,MAAM,qCAAqC,CAAC;AAEjE,OAAO,KAAK,YAAY,MAAM,uCAAuC,CAAC;AAGtE,OAAO,KAAK,eAAe,MAAM,0CAA0C,CAAC;AAC5E,OAAO,KAAK,oBAAoB,MAAM,+CAA+C,CAAC;AAEtF,OAAO,KAAK,0BAA0B,MAAM,sDAAsD,CAAC;AACnG,OAAO,KAAK,uBAAuB,MAAM,4CAA4C,CAAC;AACtF,OAAO,KAAK,YAAY,MAAM,oCAAoC,CAAC;AACnE,OAAO,KAAK,iBAAiB,MAAM,6CAA6C,CAAC;AACjF,OAAO,KAAK,cAAc,MAAM,oCAAoC,CAAC;AACrE,OAAO,KAAK,iBAAiB,MAAM,iDAAiD,CAAC;AAGrF,OAAO,KAAK,oBAAoB,MAAM,4CAA4C,CAAC;AACnF,OAAO,KAAK,+BAA+B,MAAM,qDAAqD,CAAC;AAEvG,MAAM,CAAC,OAAO,OAAO,cAAc;;gBAkBnB,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,oBAAoB,EAAE,0BAA0B,CAAC,MAAM,CAAC,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,UAAU,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,aAAa,EAAE,+BAA+B;IAY7U,IAAI,MAAM,IAAI,cAAc,GAAG,IAAI,CAKlC;IAED,IAAI,KAAK,IAAI,iBAAiB,GAAG,IAAI,CAKpC;IAED,IAAI,UAAU,IAAI,MAAM,GAAG,SAAS,CAEnC;IAEK,KAAK,CAAC,OAAO,EAAE;QAAE,sBAAsB,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAgB3E,MAAM,IAAI,OAAO;IAKjB,KAAK,IAAI,OAAO;IAMhB,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAI/C,sBAAsB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC;IAYvE,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC;IAYjE,qBAAqB,CAAC,OAAO,EAAE,oBAAoB;IAcnD,uBAAuB;IAsBvB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAqC3E,OAAO,CAAC,yCAAyC;IAU3C,eAAe,CAAC,UAAU,GAAE,MAAM,GAAG,IAAW;CAqNzD"}
|
|
@@ -59,6 +59,7 @@ export default class DownloaderCore {
|
|
|
59
59
|
});
|
|
60
60
|
if (paused)
|
|
61
61
|
await this.#downloadTracker?.saveState();
|
|
62
|
+
this.#healthMonitor.stop();
|
|
62
63
|
return paused;
|
|
63
64
|
}
|
|
64
65
|
resume() {
|
|
@@ -67,6 +68,7 @@ export default class DownloaderCore {
|
|
|
67
68
|
}
|
|
68
69
|
abort() {
|
|
69
70
|
this.#throwIfNotRunning();
|
|
71
|
+
this.#healthMonitor.stop();
|
|
70
72
|
return this.#filesDownloader.requestAbort();
|
|
71
73
|
}
|
|
72
74
|
configureThrottling(options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"downloaderCore.js","sourceRoot":"","sources":["../../../../src/client/downloader/downloaderCore.ts"],"names":[],"mappings":"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","sourcesContent":["import ApiError from \"../../utils/api/apiError.js\";\r\nimport DownloadErrorCode from \"../../downloader/dtos/downloadErrorCode.js\";\r\nimport TransferDownloadEvent from \"../../downloader/dtos/downloadEvent.js\";\r\nimport FilesDownloader from \"../../downloader/filesDownloader.js\";\r\nimport DownloadFileInfo from \"../../downloader/dtos/downloadFileInfo.js\";\r\nimport TransferConcurrencyController from \"../../utils/concurrencyController/transferConcurrencyController.js\";\r\nimport DownloadError from '../../downloader/dtos/downloadError.js';\r\nimport UrlUtil from \"../../utils/api/urlUtil.js\";\r\nimport DownloadTracker from \"../../downloader/downloadTracker.js\";\r\nimport FilesPreparer from \"../../downloader/filesPreparer.js\";\r\nimport DownloadFolderResolver from \"../../downloader/downloadFolderResolver.js\";\r\nimport DownloadRegistrationMode from \"../../downloader/dtos/downloadRegistrationMode.js\";\r\n\r\nimport type DownloadOptions from \"../../downloader/downloadOptions.js\";\r\nimport type ApiClient from \"../../utils/api/apiClient.js\";\r\nimport type ThrottlingOptions from '../../utils/networking/throttlingOptions.js';\r\nimport TransferStatus from '../../utils/types/transferStatus.js';\r\nimport type GetTransferResponse from \"../../utils/api/dtos/getTransferResponse.js\";\r\nimport type DownloadInfo from \"../../downloader/dtos/downloadInfo.js\";\r\nimport type TransferFileDto from \"../../utils/api/dtos/transferFileDto.js\";\r\nimport type GetTransferRequest from \"../../utils/api/dtos/getTransferRequest.js\";\r\nimport type DownloadCommand from \"../../downloader/dtos/downloadCommand.js\";\r\nimport type DownloadFilesCommand from \"../../downloader/dtos/downloadFilesCommand.js\";\r\nimport type DownloaderRestoredState from \"../../downloader/dtos/downloaderRestoredState.js\";\r\nimport type ChunkStreamProviderFactory from \"../../utils/fileSystem/chunkStreamProviderFactory.js\";\r\nimport type FileServerClientFactory from \"../../utils/api/fileServerClientFactory.js\";\r\nimport type EventsEngine from \"../../utils/events/eventsEngine.js\";\r\nimport type FileSystemService from \"../../utils/fileSystem/fileSystemService.js\";\r\nimport type DownloadLogger from \"../../downloader/downloadLogger.js\";\r\nimport type DownloadEventArgs from \"../../downloader/eventArgs/downloadEventArgs.js\";\r\nimport type { DownloadCommandE2eeData } from \"../../downloader/dtos/downloadCommand.js\";\r\nimport type { DownloadTrackingMetadataE2eeData } from \"../../downloader/dtos/downloadTrackingMetadata.js\";\r\nimport type CryptographyProvider from \"../../utils/crypto/cryptographyProvider.js\";\r\nimport type TransferDownloaderHealthMonitor from \"../healthMonitor/transferDownloaderHealthMonitor.js\";\r\n\r\nexport default class DownloaderCore {\r\n readonly #apiClient: ApiClient;\r\n readonly #options: DownloadOptions;\r\n readonly #chunkProviderFactory: ChunkStreamProviderFactory<string>;\r\n readonly #fileserverClientFactory: FileServerClientFactory;\r\n readonly #fileSystem: FileSystemService;\r\n readonly #eventsEngine: EventsEngine;\r\n readonly #logger: DownloadLogger;\r\n readonly #cryptography: CryptographyProvider;\r\n readonly #healthMonitor: TransferDownloaderHealthMonitor;\r\n\r\n #downloadId?: string;\r\n #transferId?: string;\r\n #trackId?: string;\r\n #filesDownloader: FilesDownloader | null = null;\r\n #downloadTracker: DownloadTracker | null = null;\r\n #downloadRegistrationMode: DownloadRegistrationMode = DownloadRegistrationMode.Transfer;\r\n\r\n constructor(options: DownloadOptions, logger: DownloadLogger, apiClient: ApiClient, chunkProviderFactory: ChunkStreamProviderFactory<string>, fileserverClientFactory: FileServerClientFactory, fileSystem: FileSystemService, eventsEngine: EventsEngine, cryptography: CryptographyProvider, healthMonitor: TransferDownloaderHealthMonitor) {\r\n this.#options = options;\r\n this.#logger = logger;\r\n this.#apiClient = apiClient;\r\n this.#chunkProviderFactory = chunkProviderFactory;\r\n this.#fileserverClientFactory = fileserverClientFactory;\r\n this.#fileSystem = fileSystem;\r\n this.#eventsEngine = eventsEngine;\r\n this.#cryptography = cryptography;\r\n this.#healthMonitor = healthMonitor;\r\n }\r\n\r\n get status(): TransferStatus | null {\r\n if (this.#filesDownloader === null)\r\n return null;\r\n\r\n return this.#filesDownloader.status;\r\n }\r\n\r\n get state(): DownloadEventArgs | null {\r\n if (this.#filesDownloader === null)\r\n return null;\r\n\r\n return this.#filesDownloader.getCurrentState(true);\r\n }\r\n\r\n get downloadId(): string | undefined {\r\n return this.#downloadId;\r\n }\r\n\r\n async pause(options: { interruptPendingChunks: boolean }): Promise<boolean> {\r\n this.#throwIfNotRunning();\r\n\r\n const paused = await new Promise<boolean>(resolve => {\r\n const pauseOptions = { ...options, pausedTrigger: resolve };\r\n this.#filesDownloader!.requestPause(pauseOptions);\r\n });\r\n\r\n if (paused)\r\n await this.#downloadTracker?.saveState();\r\n\r\n return paused;\r\n }\r\n\r\n resume(): boolean {\r\n this.#throwIfNotRunning();\r\n return this.#filesDownloader!.resume();\r\n }\r\n\r\n abort(): boolean {\r\n this.#throwIfNotRunning();\r\n return this.#filesDownloader!.requestAbort();\r\n }\r\n\r\n configureThrottling(options: ThrottlingOptions): void {\r\n this.#eventsEngine.emit(TransferDownloadEvent.ConfigureThrottling, options);\r\n }\r\n\r\n async downloadAllFilesZipped(command: DownloadCommand): Promise<DownloadInfo> {\r\n this.#throwIfRunning();\r\n this.#validateOptions();\r\n\r\n this.#trackId = command.trackId;\r\n const transfer = await this.#getEffectiveTransfer(command, 0);\r\n\r\n this.#downloadRegistrationMode = DownloadRegistrationMode.Transfer;\r\n\r\n return this.#downloadZipped(transfer, command.e2eeDataOrTextKey);\r\n }\r\n\r\n async downloadAllFiles(command: DownloadCommand): Promise<DownloadInfo> {\r\n this.#throwIfRunning();\r\n this.#validateOptions();\r\n\r\n this.#trackId = command.trackId;\r\n const transfer = await this.#getEffectiveTransfer(command, -1);\r\n\r\n this.#downloadRegistrationMode = DownloadRegistrationMode.Transfer;\r\n\r\n return this.#download(transfer, transfer.files, command.e2eeDataOrTextKey);\r\n }\r\n\r\n async downloadSpecificFiles(command: DownloadFilesCommand) {\r\n this.#throwIfRunning();\r\n this.#validateOptions();\r\n\r\n this.#trackId = command.trackId;\r\n const transfer = await this.#getEffectiveTransfer(command, 0);\r\n\r\n this.#downloadRegistrationMode = typeof transfer.numberoffiles === `number` && command.files.length === transfer.numberoffiles\r\n ? DownloadRegistrationMode.Transfer\r\n : DownloadRegistrationMode.EverySingleFile;\r\n\r\n return this.#download(transfer, command.files, command.e2eeDataOrTextKey);\r\n }\r\n\r\n async restartFailedDownloader() {\r\n if (!this.#downloadTracker)\r\n throw new Error(`Download tracker hasn't been initialized`);\r\n if (!this.#options.downloadTrackingBaseFolder)\r\n throw new Error(`Download tracking base folder hasn't been populated`);\r\n if (this.#filesDownloader?.status !== TransferStatus.Failed && this.#filesDownloader?.status !== TransferStatus.Aborted)\r\n throw new Error(`Downloader has to be in Failed or Aborted stated`);\r\n\r\n const downloadMetadata = await DownloadTracker.restoreDownloadMetadata(this.#downloadId!, this.#options.downloadTrackingBaseFolder, this.#fileSystem);\r\n const downloadCommandE2eeData = this.createDownloadCommandE2eeDataFromMetadata(downloadMetadata.e2eeData);\r\n\r\n // find out from disk the entire list of files, which were in progress and how many chunks have completed already\r\n const downloaderState = await this.#downloadTracker.restoreDownloaderState();\r\n\r\n // restart from where we left off\r\n const runningInfo = this.#run(downloaderState.files, downloadCommandE2eeData, downloadMetadata.region, downloaderState.state);\r\n runningInfo.then((di: DownloadInfo) => {\r\n this.#eventsEngine.emit(TransferDownloadEvent.RecoveredInterruptedDownload, di.initialState);\r\n });\r\n return runningInfo;\r\n }\r\n\r\n async recoverInterruptedDownload(downloadId: string): Promise<DownloadInfo> {\r\n this.#logger.applyDownloadId(downloadId);\r\n this.#logger.logInfo(`Download recovery requested for ${downloadId}`);\r\n\r\n this.#throwIfRunning();\r\n\r\n if (!this.#options.downloadTrackingBaseFolder)\r\n throw new DownloadError(`The download tracking folder is not specified for ${downloadId}`, undefined, DownloadErrorCode.TrackingNotAvailable);\r\n\r\n this.#downloadId = downloadId;\r\n this.#transferId = downloadId.split(`_`)[0]!;\r\n this.#logger.applyTransferId(this.#transferId);\r\n\r\n const downloadMetadata = await DownloadTracker.restoreDownloadMetadata(this.#downloadId!, this.#options.downloadTrackingBaseFolder, this.#fileSystem);\r\n\r\n const downloadCommandE2eeData = this.createDownloadCommandE2eeDataFromMetadata(downloadMetadata.e2eeData);\r\n\r\n this.#downloadTracker = new DownloadTracker(this.#downloadId!, this.#options, this.#fileSystem, this.#eventsEngine, downloadCommandE2eeData, downloadMetadata.region);\r\n const restoredOptions = await this.#downloadTracker.restoreDownloadOptions();\r\n\r\n // just make sure we are running the same config as when the download was last dumped to disk - otherwise things could get out of sync\r\n this.#options.downloadFolder = restoredOptions.downloadFolder;\r\n this.#options.downloadTrackingBaseFolder = restoredOptions.downloadTrackingBaseFolder;\r\n this.#options.maxChunkSize = restoredOptions.maxChunkSize;\r\n this.#options.checkChunksMd5 = restoredOptions.checkChunksMd5;\r\n\r\n // find out from disk the entire list of files, which were in progress and how many chunks have completed already\r\n const downloaderState = await this.#downloadTracker.restoreDownloaderState();\r\n\r\n // restart from where we left off\r\n const runningInfo = this.#run(downloaderState.files, downloadCommandE2eeData, downloadMetadata.region, downloaderState.state);\r\n runningInfo.then((di: DownloadInfo) => {\r\n this.#eventsEngine.emit(TransferDownloadEvent.RecoveredInterruptedDownload, di.initialState);\r\n });\r\n return runningInfo;\r\n }\r\n\r\n private createDownloadCommandE2eeDataFromMetadata(metadataE2eeData?: DownloadTrackingMetadataE2eeData): DownloadCommandE2eeData | undefined {\r\n if (!metadataE2eeData)\r\n return undefined;\r\n\r\n return {\r\n iv: Buffer.from(metadataE2eeData.ivAsHex, `hex`),\r\n key: Buffer.from(metadataE2eeData.keyAsHex, `hex`),\r\n };\r\n }\r\n\r\n async cleanupDownload(downloadId: string | null = null) {\r\n const cleanupDownloadId = downloadId ?? this.#downloadId;\r\n\r\n if (!cleanupDownloadId)\r\n throw new DownloadError(`Cannot cleanup unknown download`);\r\n\r\n if (!this.#options.downloadTrackingBaseFolder)\r\n throw new DownloadError(`The download tracking folder is not specified for download ${cleanupDownloadId}`);\r\n\r\n this.#logger.applyDownloadId(cleanupDownloadId);\r\n\r\n await DownloadTracker.removeDownloadTrackingFolder(cleanupDownloadId, this.#options.downloadTrackingBaseFolder, this.#fileSystem);\r\n }\r\n\r\n async #downloadZipped(transfer: GetTransferResponse, e2eeDataOrTextKey?: DownloadCommandE2eeData | string): Promise<DownloadInfo> {\r\n const fsClient = this.#fileserverClientFactory.createFileServerTcpDownloadClient(transfer.compressedfileurl!, null, null, transfer.id, ``, this.#options);\r\n const metaData = await fsClient.getCompressedFileMetadata();\r\n\r\n // for now fileservers are not able to validate md5 for chunks of the zip\r\n // note: this should be rather handled in files downloader logic\r\n this.#options.checkChunksMd5 = false;\r\n\r\n const zipFile: TransferFileDto = {\r\n downloadurl: transfer.compressedfileurl!,\r\n fileid: UrlUtil.getQueryStringFromUrl(transfer.compressedfileurl!).compressedfilekey!,\r\n filename: metaData.fileName,\r\n filesize: metaData.fileSize,\r\n compressed: true,\r\n };\r\n\r\n return this.#download(transfer, [zipFile], e2eeDataOrTextKey);\r\n }\r\n\r\n async #download(transfer: GetTransferResponse, files: Array<TransferFileDto>, e2eeDataOrTextKey?: DownloadCommandE2eeData | string): Promise<DownloadInfo> {\r\n this.#transferId = transfer.id;\r\n this.#downloadId = this.#generateDownloadId();\r\n\r\n this.#logger.applyDownloadId(this.#downloadId);\r\n this.#logger.applyTransferId(this.#transferId);\r\n\r\n if (this.#options.downloadFolderTemplate)\r\n this.#options.downloadFolder = DownloadFolderResolver.prepareDownloadFolder(this.#options.downloadFolderTemplate!, transfer);\r\n\r\n const e2eeData = await this.#getE2eeDataOrThrow(transfer, e2eeDataOrTextKey);\r\n\r\n const downloadFiles = this.#mapTransferFilesDtosToFileInfos(files);\r\n const preparer = new FilesPreparer(this.#options.downloadFolder!, this.#options.maxChunkSize, this.#fileSystem);\r\n preparer.prepareFiles(downloadFiles);\r\n\r\n return this.#run(downloadFiles, e2eeData, transfer.region);\r\n }\r\n\r\n async #getE2eeDataOrThrow(transfer: GetTransferResponse, e2eeDataOrTextKey?: string | DownloadCommandE2eeData): Promise<DownloadCommandE2eeData | undefined> {\r\n if (!transfer.e2ee)\r\n return undefined;\r\n\r\n if (!e2eeDataOrTextKey)\r\n throw new DownloadError(`No E2EE data or text key available to decrypt the transfer`);\r\n\r\n if (typeof e2eeDataOrTextKey === `object`)\r\n return e2eeDataOrTextKey;\r\n\r\n if (!transfer.e2ee_keyhash)\r\n throw new DownloadError(`No E2EE db data available to decrypt the transfer`);\r\n\r\n const e2eeDbDataBuffer = Buffer.from(transfer.e2ee_keyhash, `hex`);\r\n\r\n const iv = e2eeDbDataBuffer.subarray(0, 16);\r\n const salt = e2eeDbDataBuffer.subarray(16, 32);\r\n const key = await this.#cryptography.deriveKey(e2eeDataOrTextKey, salt);\r\n\r\n return { iv, key: Buffer.from(key) };\r\n }\r\n\r\n async #run(downloadFiles: Array<DownloadFileInfo>, e2eeData?: DownloadCommandE2eeData, region?: string, restoredState?: DownloaderRestoredState): Promise<DownloadInfo> {\r\n if (!this.#transferId)\r\n throw new DownloadError(`This downloader has no transfer ID specified`);\r\n\r\n if (!this.#downloadId)\r\n throw new DownloadError(`This downloader has no download ID initialized`);\r\n\r\n this.#filesDownloader = new FilesDownloader(\r\n this.#logger,\r\n this.#transferId!,\r\n this.#trackId,\r\n this.#downloadId!,\r\n region,\r\n downloadFiles,\r\n restoredState,\r\n this.#fileSystem,\r\n new TransferConcurrencyController(this.#options.parallelChunks!),\r\n this.#eventsEngine,\r\n this.#cryptography,\r\n this.#options,\r\n this.#apiClient,\r\n this.#fileserverClientFactory,\r\n this.#chunkProviderFactory,\r\n this.#downloadRegistrationMode,\r\n e2eeData,\r\n );\r\n\r\n if (this.#options.downloadTrackingBaseFolder) {\r\n if (!this.#downloadTracker)\r\n this.#downloadTracker = new DownloadTracker(this.#downloadId!, this.#options, this.#fileSystem, this.#eventsEngine, e2eeData, region);\r\n\r\n await this.#downloadTracker.start(downloadFiles);\r\n }\r\n\r\n const initialState = this.#filesDownloader.getCurrentState(false);\r\n\r\n this.#healthMonitor.start();\r\n\r\n const completion = this.#filesDownloader.start();\r\n\r\n completion.finally(() => {\r\n this.#healthMonitor.stop();\r\n });\r\n\r\n return { downloadId: this.#downloadId!, transferId: this.#transferId!, completion, initialState };\r\n }\r\n\r\n async #getEffectiveTransfer(command: DownloadCommand, fileslimit: number) {\r\n let effectiveTransfer: GetTransferResponse | null = null;\r\n\r\n if (command.transfer)\r\n effectiveTransfer = await this.#fetchTransfer(command.transfer, undefined, command.password, fileslimit, command.checkLogintoken);\r\n\r\n if (!effectiveTransfer) {\r\n // still don't know the transfer - must use track ID to fetch it\r\n if (!this.#trackId)\r\n throw new DownloadError(`Could not resolve transfer to be downloaded - missing transfer info and missing track id`);\r\n\r\n effectiveTransfer = await this.#fetchTransfer(undefined, this.#trackId!, command.password, fileslimit, command.checkLogintoken);\r\n }\r\n\r\n if (!effectiveTransfer)\r\n throw new DownloadError(`Could not resolve transfer to be downloaded - transfer=${command.transfer} track=${command.trackId}`);\r\n\r\n if (effectiveTransfer.isexpired === true)\r\n throw new DownloadError(`Transfer is expired transfer=${effectiveTransfer.id}`, undefined, DownloadErrorCode.TransferExpired);\r\n\r\n if (effectiveTransfer.blockdownloads === true)\r\n throw new DownloadError(`Transfer has downloads disabled transfer=${effectiveTransfer.id}`, undefined, DownloadErrorCode.DownloadsDisabled);\r\n\r\n if (fileslimit !== 0 && (!effectiveTransfer.files || effectiveTransfer.files.length === 0))\r\n throw new DownloadError(`Transfer has no files to download transfer=${effectiveTransfer.id}`, undefined, DownloadErrorCode.NoFilesToDownload);\r\n\r\n return effectiveTransfer;\r\n }\r\n\r\n async #fetchTransfer(\r\n transferid?: string | undefined,\r\n trackid?: string | undefined,\r\n password?: string | undefined,\r\n fileslimit?: number | undefined,\r\n checkLogintoken?: boolean,\r\n ): Promise<GetTransferResponse> {\r\n try {\r\n // specifying which file properties we want to get from API\r\n // reason: api adds lots of other unnecessary properties - downloader doesn't need them and if a transfer has lots of files (some can be up to 100k)\r\n // it makes the response much smaller (up to 80% size reduction)\r\n const request: GetTransferRequest = { fileslimit, transferid, trackid, password, fprops: [`fileid`, `filesize`, `filename`, `downloadurl`], checkLogintoken };\r\n return await this.#apiClient.getTransfer(request);\r\n }\r\n catch (error) {\r\n const code = this.#apiErrorToDownloadErrorCode(error);\r\n const downloadError = new DownloadError(`Could not fetch transfer by id=${transferid ?? `---`} track=${trackid ?? `---`}`, { cause: error as Error }, code);\r\n throw downloadError;\r\n }\r\n }\r\n\r\n #apiErrorToDownloadErrorCode(error: unknown) {\r\n if (error instanceof ApiError) {\r\n switch (error.httpStatus) {\r\n case 401: return DownloadErrorCode.InvalidTransferPassword;\r\n case 404: return DownloadErrorCode.TransferNotFound;\r\n case 409: return DownloadErrorCode.TransferInvalidState;\r\n default: break;\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n #throwIfRunning() {\r\n if (this.#filesDownloader)\r\n throw new DownloadError(`This instance of downloader is already in use. Please create a new one.`);\r\n }\r\n\r\n #throwIfNotRunning() {\r\n if (!this.#filesDownloader)\r\n throw new DownloadError(`This instance of downloader is not running yet. Please start the download first.`);\r\n }\r\n\r\n #generateDownloadId(): string {\r\n return `${this.#transferId}_${this.#cryptography.generateRandomString(10)}`;\r\n }\r\n\r\n #mapTransferFilesDtosToFileInfos(files: Array<TransferFileDto>) {\r\n return files.map(file => new DownloadFileInfo(\r\n file.fileid,\r\n file.downloadurl,\r\n file.filename,\r\n file.filesize,\r\n ));\r\n }\r\n\r\n #validateOptions() {\r\n if (!this.#options.downloadFolder && !this.#options.downloadFolderTemplate)\r\n throw new DownloadError(`downloadFolder OR downloadFolderTemplate is required`);\r\n\r\n if (this.#options.maxChunkSize !== null && this.#options.maxChunkSize! <= 0)\r\n throw new DownloadError(`maxChunkSize must be greater than 0. Provide \"null\" if you want to download without chunking.`);\r\n }\r\n}"]}
|
|
1
|
+
{"version":3,"file":"downloaderCore.js","sourceRoot":"","sources":["../../../../src/client/downloader/downloaderCore.ts"],"names":[],"mappings":"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","sourcesContent":["import ApiError from \"../../utils/api/apiError.js\";\r\nimport DownloadErrorCode from \"../../downloader/dtos/downloadErrorCode.js\";\r\nimport TransferDownloadEvent from \"../../downloader/dtos/downloadEvent.js\";\r\nimport FilesDownloader from \"../../downloader/filesDownloader.js\";\r\nimport DownloadFileInfo from \"../../downloader/dtos/downloadFileInfo.js\";\r\nimport TransferConcurrencyController from \"../../utils/concurrencyController/transferConcurrencyController.js\";\r\nimport DownloadError from '../../downloader/dtos/downloadError.js';\r\nimport UrlUtil from \"../../utils/api/urlUtil.js\";\r\nimport DownloadTracker from \"../../downloader/downloadTracker.js\";\r\nimport FilesPreparer from \"../../downloader/filesPreparer.js\";\r\nimport DownloadFolderResolver from \"../../downloader/downloadFolderResolver.js\";\r\nimport DownloadRegistrationMode from \"../../downloader/dtos/downloadRegistrationMode.js\";\r\n\r\nimport type DownloadOptions from \"../../downloader/downloadOptions.js\";\r\nimport type ApiClient from \"../../utils/api/apiClient.js\";\r\nimport type ThrottlingOptions from '../../utils/networking/throttlingOptions.js';\r\nimport TransferStatus from '../../utils/types/transferStatus.js';\r\nimport type GetTransferResponse from \"../../utils/api/dtos/getTransferResponse.js\";\r\nimport type DownloadInfo from \"../../downloader/dtos/downloadInfo.js\";\r\nimport type TransferFileDto from \"../../utils/api/dtos/transferFileDto.js\";\r\nimport type GetTransferRequest from \"../../utils/api/dtos/getTransferRequest.js\";\r\nimport type DownloadCommand from \"../../downloader/dtos/downloadCommand.js\";\r\nimport type DownloadFilesCommand from \"../../downloader/dtos/downloadFilesCommand.js\";\r\nimport type DownloaderRestoredState from \"../../downloader/dtos/downloaderRestoredState.js\";\r\nimport type ChunkStreamProviderFactory from \"../../utils/fileSystem/chunkStreamProviderFactory.js\";\r\nimport type FileServerClientFactory from \"../../utils/api/fileServerClientFactory.js\";\r\nimport type EventsEngine from \"../../utils/events/eventsEngine.js\";\r\nimport type FileSystemService from \"../../utils/fileSystem/fileSystemService.js\";\r\nimport type DownloadLogger from \"../../downloader/downloadLogger.js\";\r\nimport type DownloadEventArgs from \"../../downloader/eventArgs/downloadEventArgs.js\";\r\nimport type { DownloadCommandE2eeData } from \"../../downloader/dtos/downloadCommand.js\";\r\nimport type { DownloadTrackingMetadataE2eeData } from \"../../downloader/dtos/downloadTrackingMetadata.js\";\r\nimport type CryptographyProvider from \"../../utils/crypto/cryptographyProvider.js\";\r\nimport type TransferDownloaderHealthMonitor from \"../healthMonitor/transferDownloaderHealthMonitor.js\";\r\n\r\nexport default class DownloaderCore {\r\n readonly #apiClient: ApiClient;\r\n readonly #options: DownloadOptions;\r\n readonly #chunkProviderFactory: ChunkStreamProviderFactory<string>;\r\n readonly #fileserverClientFactory: FileServerClientFactory;\r\n readonly #fileSystem: FileSystemService;\r\n readonly #eventsEngine: EventsEngine;\r\n readonly #logger: DownloadLogger;\r\n readonly #cryptography: CryptographyProvider;\r\n readonly #healthMonitor: TransferDownloaderHealthMonitor;\r\n\r\n #downloadId?: string;\r\n #transferId?: string;\r\n #trackId?: string;\r\n #filesDownloader: FilesDownloader | null = null;\r\n #downloadTracker: DownloadTracker | null = null;\r\n #downloadRegistrationMode: DownloadRegistrationMode = DownloadRegistrationMode.Transfer;\r\n\r\n constructor(options: DownloadOptions, logger: DownloadLogger, apiClient: ApiClient, chunkProviderFactory: ChunkStreamProviderFactory<string>, fileserverClientFactory: FileServerClientFactory, fileSystem: FileSystemService, eventsEngine: EventsEngine, cryptography: CryptographyProvider, healthMonitor: TransferDownloaderHealthMonitor) {\r\n this.#options = options;\r\n this.#logger = logger;\r\n this.#apiClient = apiClient;\r\n this.#chunkProviderFactory = chunkProviderFactory;\r\n this.#fileserverClientFactory = fileserverClientFactory;\r\n this.#fileSystem = fileSystem;\r\n this.#eventsEngine = eventsEngine;\r\n this.#cryptography = cryptography;\r\n this.#healthMonitor = healthMonitor;\r\n }\r\n\r\n get status(): TransferStatus | null {\r\n if (this.#filesDownloader === null)\r\n return null;\r\n\r\n return this.#filesDownloader.status;\r\n }\r\n\r\n get state(): DownloadEventArgs | null {\r\n if (this.#filesDownloader === null)\r\n return null;\r\n\r\n return this.#filesDownloader.getCurrentState(true);\r\n }\r\n\r\n get downloadId(): string | undefined {\r\n return this.#downloadId;\r\n }\r\n\r\n async pause(options: { interruptPendingChunks: boolean }): Promise<boolean> {\r\n this.#throwIfNotRunning();\r\n\r\n const paused = await new Promise<boolean>(resolve => {\r\n const pauseOptions = { ...options, pausedTrigger: resolve };\r\n this.#filesDownloader!.requestPause(pauseOptions);\r\n });\r\n\r\n if (paused)\r\n await this.#downloadTracker?.saveState();\r\n\r\n this.#healthMonitor.stop();\r\n\r\n return paused;\r\n }\r\n\r\n resume(): boolean {\r\n this.#throwIfNotRunning();\r\n return this.#filesDownloader!.resume();\r\n }\r\n\r\n abort(): boolean {\r\n this.#throwIfNotRunning();\r\n this.#healthMonitor.stop();\r\n return this.#filesDownloader!.requestAbort();\r\n }\r\n\r\n configureThrottling(options: ThrottlingOptions): void {\r\n this.#eventsEngine.emit(TransferDownloadEvent.ConfigureThrottling, options);\r\n }\r\n\r\n async downloadAllFilesZipped(command: DownloadCommand): Promise<DownloadInfo> {\r\n this.#throwIfRunning();\r\n this.#validateOptions();\r\n\r\n this.#trackId = command.trackId;\r\n const transfer = await this.#getEffectiveTransfer(command, 0);\r\n\r\n this.#downloadRegistrationMode = DownloadRegistrationMode.Transfer;\r\n\r\n return this.#downloadZipped(transfer, command.e2eeDataOrTextKey);\r\n }\r\n\r\n async downloadAllFiles(command: DownloadCommand): Promise<DownloadInfo> {\r\n this.#throwIfRunning();\r\n this.#validateOptions();\r\n\r\n this.#trackId = command.trackId;\r\n const transfer = await this.#getEffectiveTransfer(command, -1);\r\n\r\n this.#downloadRegistrationMode = DownloadRegistrationMode.Transfer;\r\n\r\n return this.#download(transfer, transfer.files, command.e2eeDataOrTextKey);\r\n }\r\n\r\n async downloadSpecificFiles(command: DownloadFilesCommand) {\r\n this.#throwIfRunning();\r\n this.#validateOptions();\r\n\r\n this.#trackId = command.trackId;\r\n const transfer = await this.#getEffectiveTransfer(command, 0);\r\n\r\n this.#downloadRegistrationMode = typeof transfer.numberoffiles === `number` && command.files.length === transfer.numberoffiles\r\n ? DownloadRegistrationMode.Transfer\r\n : DownloadRegistrationMode.EverySingleFile;\r\n\r\n return this.#download(transfer, command.files, command.e2eeDataOrTextKey);\r\n }\r\n\r\n async restartFailedDownloader() {\r\n if (!this.#downloadTracker)\r\n throw new Error(`Download tracker hasn't been initialized`);\r\n if (!this.#options.downloadTrackingBaseFolder)\r\n throw new Error(`Download tracking base folder hasn't been populated`);\r\n if (this.#filesDownloader?.status !== TransferStatus.Failed && this.#filesDownloader?.status !== TransferStatus.Aborted)\r\n throw new Error(`Downloader has to be in Failed or Aborted stated`);\r\n\r\n const downloadMetadata = await DownloadTracker.restoreDownloadMetadata(this.#downloadId!, this.#options.downloadTrackingBaseFolder, this.#fileSystem);\r\n const downloadCommandE2eeData = this.createDownloadCommandE2eeDataFromMetadata(downloadMetadata.e2eeData);\r\n\r\n // find out from disk the entire list of files, which were in progress and how many chunks have completed already\r\n const downloaderState = await this.#downloadTracker.restoreDownloaderState();\r\n\r\n // restart from where we left off\r\n const runningInfo = this.#run(downloaderState.files, downloadCommandE2eeData, downloadMetadata.region, downloaderState.state);\r\n runningInfo.then((di: DownloadInfo) => {\r\n this.#eventsEngine.emit(TransferDownloadEvent.RecoveredInterruptedDownload, di.initialState);\r\n });\r\n return runningInfo;\r\n }\r\n\r\n async recoverInterruptedDownload(downloadId: string): Promise<DownloadInfo> {\r\n this.#logger.applyDownloadId(downloadId);\r\n this.#logger.logInfo(`Download recovery requested for ${downloadId}`);\r\n\r\n this.#throwIfRunning();\r\n\r\n if (!this.#options.downloadTrackingBaseFolder)\r\n throw new DownloadError(`The download tracking folder is not specified for ${downloadId}`, undefined, DownloadErrorCode.TrackingNotAvailable);\r\n\r\n this.#downloadId = downloadId;\r\n this.#transferId = downloadId.split(`_`)[0]!;\r\n this.#logger.applyTransferId(this.#transferId);\r\n\r\n const downloadMetadata = await DownloadTracker.restoreDownloadMetadata(this.#downloadId!, this.#options.downloadTrackingBaseFolder, this.#fileSystem);\r\n\r\n const downloadCommandE2eeData = this.createDownloadCommandE2eeDataFromMetadata(downloadMetadata.e2eeData);\r\n\r\n this.#downloadTracker = new DownloadTracker(this.#downloadId!, this.#options, this.#fileSystem, this.#eventsEngine, downloadCommandE2eeData, downloadMetadata.region);\r\n const restoredOptions = await this.#downloadTracker.restoreDownloadOptions();\r\n\r\n // just make sure we are running the same config as when the download was last dumped to disk - otherwise things could get out of sync\r\n this.#options.downloadFolder = restoredOptions.downloadFolder;\r\n this.#options.downloadTrackingBaseFolder = restoredOptions.downloadTrackingBaseFolder;\r\n this.#options.maxChunkSize = restoredOptions.maxChunkSize;\r\n this.#options.checkChunksMd5 = restoredOptions.checkChunksMd5;\r\n\r\n // find out from disk the entire list of files, which were in progress and how many chunks have completed already\r\n const downloaderState = await this.#downloadTracker.restoreDownloaderState();\r\n\r\n // restart from where we left off\r\n const runningInfo = this.#run(downloaderState.files, downloadCommandE2eeData, downloadMetadata.region, downloaderState.state);\r\n runningInfo.then((di: DownloadInfo) => {\r\n this.#eventsEngine.emit(TransferDownloadEvent.RecoveredInterruptedDownload, di.initialState);\r\n });\r\n return runningInfo;\r\n }\r\n\r\n private createDownloadCommandE2eeDataFromMetadata(metadataE2eeData?: DownloadTrackingMetadataE2eeData): DownloadCommandE2eeData | undefined {\r\n if (!metadataE2eeData)\r\n return undefined;\r\n\r\n return {\r\n iv: Buffer.from(metadataE2eeData.ivAsHex, `hex`),\r\n key: Buffer.from(metadataE2eeData.keyAsHex, `hex`),\r\n };\r\n }\r\n\r\n async cleanupDownload(downloadId: string | null = null) {\r\n const cleanupDownloadId = downloadId ?? this.#downloadId;\r\n\r\n if (!cleanupDownloadId)\r\n throw new DownloadError(`Cannot cleanup unknown download`);\r\n\r\n if (!this.#options.downloadTrackingBaseFolder)\r\n throw new DownloadError(`The download tracking folder is not specified for download ${cleanupDownloadId}`);\r\n\r\n this.#logger.applyDownloadId(cleanupDownloadId);\r\n\r\n await DownloadTracker.removeDownloadTrackingFolder(cleanupDownloadId, this.#options.downloadTrackingBaseFolder, this.#fileSystem);\r\n }\r\n\r\n async #downloadZipped(transfer: GetTransferResponse, e2eeDataOrTextKey?: DownloadCommandE2eeData | string): Promise<DownloadInfo> {\r\n const fsClient = this.#fileserverClientFactory.createFileServerTcpDownloadClient(transfer.compressedfileurl!, null, null, transfer.id, ``, this.#options);\r\n const metaData = await fsClient.getCompressedFileMetadata();\r\n\r\n // for now fileservers are not able to validate md5 for chunks of the zip\r\n // note: this should be rather handled in files downloader logic\r\n this.#options.checkChunksMd5 = false;\r\n\r\n const zipFile: TransferFileDto = {\r\n downloadurl: transfer.compressedfileurl!,\r\n fileid: UrlUtil.getQueryStringFromUrl(transfer.compressedfileurl!).compressedfilekey!,\r\n filename: metaData.fileName,\r\n filesize: metaData.fileSize,\r\n compressed: true,\r\n };\r\n\r\n return this.#download(transfer, [zipFile], e2eeDataOrTextKey);\r\n }\r\n\r\n async #download(transfer: GetTransferResponse, files: Array<TransferFileDto>, e2eeDataOrTextKey?: DownloadCommandE2eeData | string): Promise<DownloadInfo> {\r\n this.#transferId = transfer.id;\r\n this.#downloadId = this.#generateDownloadId();\r\n\r\n this.#logger.applyDownloadId(this.#downloadId);\r\n this.#logger.applyTransferId(this.#transferId);\r\n\r\n if (this.#options.downloadFolderTemplate)\r\n this.#options.downloadFolder = DownloadFolderResolver.prepareDownloadFolder(this.#options.downloadFolderTemplate!, transfer);\r\n\r\n const e2eeData = await this.#getE2eeDataOrThrow(transfer, e2eeDataOrTextKey);\r\n\r\n const downloadFiles = this.#mapTransferFilesDtosToFileInfos(files);\r\n const preparer = new FilesPreparer(this.#options.downloadFolder!, this.#options.maxChunkSize, this.#fileSystem);\r\n preparer.prepareFiles(downloadFiles);\r\n\r\n return this.#run(downloadFiles, e2eeData, transfer.region);\r\n }\r\n\r\n async #getE2eeDataOrThrow(transfer: GetTransferResponse, e2eeDataOrTextKey?: string | DownloadCommandE2eeData): Promise<DownloadCommandE2eeData | undefined> {\r\n if (!transfer.e2ee)\r\n return undefined;\r\n\r\n if (!e2eeDataOrTextKey)\r\n throw new DownloadError(`No E2EE data or text key available to decrypt the transfer`);\r\n\r\n if (typeof e2eeDataOrTextKey === `object`)\r\n return e2eeDataOrTextKey;\r\n\r\n if (!transfer.e2ee_keyhash)\r\n throw new DownloadError(`No E2EE db data available to decrypt the transfer`);\r\n\r\n const e2eeDbDataBuffer = Buffer.from(transfer.e2ee_keyhash, `hex`);\r\n\r\n const iv = e2eeDbDataBuffer.subarray(0, 16);\r\n const salt = e2eeDbDataBuffer.subarray(16, 32);\r\n const key = await this.#cryptography.deriveKey(e2eeDataOrTextKey, salt);\r\n\r\n return { iv, key: Buffer.from(key) };\r\n }\r\n\r\n async #run(downloadFiles: Array<DownloadFileInfo>, e2eeData?: DownloadCommandE2eeData, region?: string, restoredState?: DownloaderRestoredState): Promise<DownloadInfo> {\r\n if (!this.#transferId)\r\n throw new DownloadError(`This downloader has no transfer ID specified`);\r\n\r\n if (!this.#downloadId)\r\n throw new DownloadError(`This downloader has no download ID initialized`);\r\n\r\n this.#filesDownloader = new FilesDownloader(\r\n this.#logger,\r\n this.#transferId!,\r\n this.#trackId,\r\n this.#downloadId!,\r\n region,\r\n downloadFiles,\r\n restoredState,\r\n this.#fileSystem,\r\n new TransferConcurrencyController(this.#options.parallelChunks!),\r\n this.#eventsEngine,\r\n this.#cryptography,\r\n this.#options,\r\n this.#apiClient,\r\n this.#fileserverClientFactory,\r\n this.#chunkProviderFactory,\r\n this.#downloadRegistrationMode,\r\n e2eeData,\r\n );\r\n\r\n if (this.#options.downloadTrackingBaseFolder) {\r\n if (!this.#downloadTracker)\r\n this.#downloadTracker = new DownloadTracker(this.#downloadId!, this.#options, this.#fileSystem, this.#eventsEngine, e2eeData, region);\r\n\r\n await this.#downloadTracker.start(downloadFiles);\r\n }\r\n\r\n const initialState = this.#filesDownloader.getCurrentState(false);\r\n\r\n this.#healthMonitor.start();\r\n\r\n const completion = this.#filesDownloader.start();\r\n\r\n completion.finally(() => {\r\n this.#healthMonitor.stop();\r\n });\r\n\r\n return { downloadId: this.#downloadId!, transferId: this.#transferId!, completion, initialState };\r\n }\r\n\r\n async #getEffectiveTransfer(command: DownloadCommand, fileslimit: number) {\r\n let effectiveTransfer: GetTransferResponse | null = null;\r\n\r\n if (command.transfer)\r\n effectiveTransfer = await this.#fetchTransfer(command.transfer, undefined, command.password, fileslimit, command.checkLogintoken);\r\n\r\n if (!effectiveTransfer) {\r\n // still don't know the transfer - must use track ID to fetch it\r\n if (!this.#trackId)\r\n throw new DownloadError(`Could not resolve transfer to be downloaded - missing transfer info and missing track id`);\r\n\r\n effectiveTransfer = await this.#fetchTransfer(undefined, this.#trackId!, command.password, fileslimit, command.checkLogintoken);\r\n }\r\n\r\n if (!effectiveTransfer)\r\n throw new DownloadError(`Could not resolve transfer to be downloaded - transfer=${command.transfer} track=${command.trackId}`);\r\n\r\n if (effectiveTransfer.isexpired === true)\r\n throw new DownloadError(`Transfer is expired transfer=${effectiveTransfer.id}`, undefined, DownloadErrorCode.TransferExpired);\r\n\r\n if (effectiveTransfer.blockdownloads === true)\r\n throw new DownloadError(`Transfer has downloads disabled transfer=${effectiveTransfer.id}`, undefined, DownloadErrorCode.DownloadsDisabled);\r\n\r\n if (fileslimit !== 0 && (!effectiveTransfer.files || effectiveTransfer.files.length === 0))\r\n throw new DownloadError(`Transfer has no files to download transfer=${effectiveTransfer.id}`, undefined, DownloadErrorCode.NoFilesToDownload);\r\n\r\n return effectiveTransfer;\r\n }\r\n\r\n async #fetchTransfer(\r\n transferid?: string | undefined,\r\n trackid?: string | undefined,\r\n password?: string | undefined,\r\n fileslimit?: number | undefined,\r\n checkLogintoken?: boolean,\r\n ): Promise<GetTransferResponse> {\r\n try {\r\n // specifying which file properties we want to get from API\r\n // reason: api adds lots of other unnecessary properties - downloader doesn't need them and if a transfer has lots of files (some can be up to 100k)\r\n // it makes the response much smaller (up to 80% size reduction)\r\n const request: GetTransferRequest = { fileslimit, transferid, trackid, password, fprops: [`fileid`, `filesize`, `filename`, `downloadurl`], checkLogintoken };\r\n return await this.#apiClient.getTransfer(request);\r\n }\r\n catch (error) {\r\n const code = this.#apiErrorToDownloadErrorCode(error);\r\n const downloadError = new DownloadError(`Could not fetch transfer by id=${transferid ?? `---`} track=${trackid ?? `---`}`, { cause: error as Error }, code);\r\n throw downloadError;\r\n }\r\n }\r\n\r\n #apiErrorToDownloadErrorCode(error: unknown) {\r\n if (error instanceof ApiError) {\r\n switch (error.httpStatus) {\r\n case 401: return DownloadErrorCode.InvalidTransferPassword;\r\n case 404: return DownloadErrorCode.TransferNotFound;\r\n case 409: return DownloadErrorCode.TransferInvalidState;\r\n default: break;\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n #throwIfRunning() {\r\n if (this.#filesDownloader)\r\n throw new DownloadError(`This instance of downloader is already in use. Please create a new one.`);\r\n }\r\n\r\n #throwIfNotRunning() {\r\n if (!this.#filesDownloader)\r\n throw new DownloadError(`This instance of downloader is not running yet. Please start the download first.`);\r\n }\r\n\r\n #generateDownloadId(): string {\r\n return `${this.#transferId}_${this.#cryptography.generateRandomString(10)}`;\r\n }\r\n\r\n #mapTransferFilesDtosToFileInfos(files: Array<TransferFileDto>) {\r\n return files.map(file => new DownloadFileInfo(\r\n file.fileid,\r\n file.downloadurl,\r\n file.filename,\r\n file.filesize,\r\n ));\r\n }\r\n\r\n #validateOptions() {\r\n if (!this.#options.downloadFolder && !this.#options.downloadFolderTemplate)\r\n throw new DownloadError(`downloadFolder OR downloadFolderTemplate is required`);\r\n\r\n if (this.#options.maxChunkSize !== null && this.#options.maxChunkSize! <= 0)\r\n throw new DownloadError(`maxChunkSize must be greater than 0. Provide \"null\" if you want to download without chunking.`);\r\n }\r\n}"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transferHealthMonitorBase.d.ts","sourceRoot":"","sources":["../../../../src/client/healthMonitor/transferHealthMonitorBase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,YAAY,MAAM,oCAAoC,CAAC;AACnE,OAAO,0BAA0B,MAAM,wCAAwC,CAAC;AAChF,OAAO,6BAA6B,MAAM,qDAAqD,CAAC;AAChG,OAAO,+BAA+B,MAAM,uDAAuD,CAAC;AACpG,OAAO,aAAsC,MAAM,kCAAkC,CAAC;AAEtF,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,yBAAyB,CAAC,CAAC;;IAYrD,SAAS,CAAC,mCAAmC,EAAE,CAAC,GAAG,SAAS,CAAC;gBAIjD,aAAa,EAAE,aAAa,EAAE,oBAAoB,EAAE,YAAY,EAAE,mBAAmB,SAAS;IAY1G,KAAK;IAWL,OAAO,CAAC,UAAU;IAOlB,IAAI;IAQJ,OAAO,CAAC,gCAAgC;IAKxC,OAAO,CAAC,oCAAoC;IAK5C,SAAS,CAAC,QAAQ,CAAC,2BAA2B,IAAI,MAAM;IACxD,SAAS,CAAC,QAAQ,CAAC,8BAA8B,IAAI,MAAM;IAE3D,OAAO,CAAC,2BAA2B,CAEjC;IAEF,SAAS,CAAC,QAAQ,CAAC,2CAA2C,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM;IAE1F,OAAO,CAAC,8BAA8B,CAapC;IAEF,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,WAAW,
|
|
1
|
+
{"version":3,"file":"transferHealthMonitorBase.d.ts","sourceRoot":"","sources":["../../../../src/client/healthMonitor/transferHealthMonitorBase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,YAAY,MAAM,oCAAoC,CAAC;AACnE,OAAO,0BAA0B,MAAM,wCAAwC,CAAC;AAChF,OAAO,6BAA6B,MAAM,qDAAqD,CAAC;AAChG,OAAO,+BAA+B,MAAM,uDAAuD,CAAC;AACpG,OAAO,aAAsC,MAAM,kCAAkC,CAAC;AAEtF,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,yBAAyB,CAAC,CAAC;;IAYrD,SAAS,CAAC,mCAAmC,EAAE,CAAC,GAAG,SAAS,CAAC;gBAIjD,aAAa,EAAE,aAAa,EAAE,oBAAoB,EAAE,YAAY,EAAE,mBAAmB,SAAS;IAY1G,KAAK;IAWL,OAAO,CAAC,UAAU;IAOlB,IAAI;IAQJ,OAAO,CAAC,gCAAgC;IAKxC,OAAO,CAAC,oCAAoC;IAK5C,SAAS,CAAC,QAAQ,CAAC,2BAA2B,IAAI,MAAM;IACxD,SAAS,CAAC,QAAQ,CAAC,8BAA8B,IAAI,MAAM;IAE3D,OAAO,CAAC,2BAA2B,CAEjC;IAEF,SAAS,CAAC,QAAQ,CAAC,2CAA2C,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM;IAE1F,OAAO,CAAC,8BAA8B,CAapC;IAEF,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,WAAW,CAoBjB;IAEF,OAAO,CAAC,iCAAiC;IAIzC,OAAO,CAAC,kBAAkB;IAS1B,SAAS,CAAC,QAAQ,CAAC,6BAA6B,CAAC,+BAA+B,CAAC,EAAE,CAAC,GAAG,MAAM;YAE/E,yCAAyC;IA8BvD,OAAO,CAAC,sBAAsB;IAO9B,OAAO,CAAC,aAAa;IAKrB,SAAS,CAAC,QAAQ,CAAC,mBAAmB,IAAI,6BAA6B;IAEvE,OAAO,CAAC,oCAAoC;IAa5C,OAAO,CAAC,2CAA2C;IAanD,OAAO,CAAC,+BAA+B;IAavC,OAAO,CAAC,yCAAyC;IAajD,OAAO,CAAC,0BAA0B;IAalC,gBAAgB,CAAC,SAAS,EAAE,0BAA0B,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,6BAA6B,KAAK,IAAI,GAAG,IAAI;IAC9H,gBAAgB,CAAC,SAAS,EAAE,0BAA0B,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,+BAA+B,KAAK,IAAI,GAAG,IAAI;CAIrI"}
|
|
@@ -64,7 +64,8 @@ export default class TransferHealthMonitorBase {
|
|
|
64
64
|
this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);
|
|
65
65
|
}
|
|
66
66
|
checkHealth = async () => {
|
|
67
|
-
const
|
|
67
|
+
const history = this.#currentPeriodProgressHistory;
|
|
68
|
+
const currentPeriodLastProgressEvent = history.length > 0 ? history[history.length - 1].eventArgs : undefined;
|
|
68
69
|
const isHealthy = this.determineIsHealthy(currentPeriodLastProgressEvent);
|
|
69
70
|
this.lastProgressEventFromPreviousPeriod = currentPeriodLastProgressEvent || this.lastProgressEventFromPreviousPeriod;
|
|
70
71
|
if (isHealthy) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transferHealthMonitorBase.js","sourceRoot":"","sources":["../../../../src/client/healthMonitor/transferHealthMonitorBase.ts"],"names":[],"mappings":"AACA,OAAO,0BAA0B,MAAM,wCAAwC,CAAC;AAKhF,MAAM,CAAC,OAAO,OAAgB,yBAAyB;IAC1C,cAAc,CAAgB;IAC9B,qBAAqB,CAAe;IAE7C,oBAAoB,CAAS;IAE7B,QAAQ,CAA4C;IAEpD,cAAc,CAAqB;IAEnC,6BAA6B,GAAqC,EAAE,CAAC;IAE3D,mCAAmC,CAAgB;IAE7D,mBAAmB,GAAG,IAAI,CAAC;IAE3B,YAAY,aAA4B,EAAE,oBAAkC,EAAE,mBAAmB,GAAG,MAAM;QACtG,IAAI,CAAC,aAAa;YACd,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACrD,IAAI,CAAC,oBAAoB;YACrB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAEpD,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;QACpC,IAAI,CAAC,qBAAqB,GAAG,oBAAoB,CAAC;QAElD,IAAI,CAAC,oBAAoB,GAAG,mBAAmB,CAAC;IACpD,CAAC;IAED,KAAK;QACD,IAAI,IAAI,CAAC,QAAQ;YACb,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAEzD,IAAI,CAAC,UAAU,EAAE,CAAC;QAElB,IAAI,CAAC,gCAAgC,EAAE,CAAC;QAExC,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACpF,CAAC;IAEO,UAAU;QACd,IAAI,CAAC,6BAA6B,GAAG,EAAE,CAAC;QACxC,IAAI,CAAC,mCAAmC,GAAG,SAAS,CAAC;QACrD,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC1B,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;IACpC,CAAC;IAED,IAAI;QACA,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAE5B,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAE1B,IAAI,CAAC,oCAAoC,EAAE,CAAC;IAChD,CAAC;IAEO,gCAAgC;QACpC,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAClH,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,IAAI,CAAC,8BAA8B,EAAE,EAAE,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC5H,CAAC;IAEO,oCAAoC;QACxC,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,IAAI,CAAC,2BAA2B,CAAC,CAAC;QACrH,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,IAAI,CAAC,8BAA8B,EAAE,EAAE,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC/H,CAAC;IAKO,2BAA2B,GAAG,CAAC,SAAkB,EAAE,EAAE;QACzD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,2CAA2C,CAAC,SAAS,CAAC,CAAC;IACtF,CAAC,CAAC;IAIM,8BAA8B,GAAG,CAAC,SAAY,EAAE,EAAE;QACtD,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAEzE,IAAI,IAAI,CAAC,mBAAmB;YACxB,OAAO;QAEX,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAErD,IAAI,CAAC,SAAS;YACV,OAAO;QAEX,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC,CAAC;IAEM,kBAAkB,CAAC,oBAAuB;QAC9C,IAAI,CAAC,6BAA6B,GAAG,EAAE,CAAC;QACxC,IAAI,CAAC,mCAAmC,GAAG,oBAAoB,CAAC;QAEhE,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAEhC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACpF,CAAC;IAEO,WAAW,GAAG,KAAK,IAAmB,EAAE;QAC5C,MAAM,8BAA8B,GAAG,IAAI,CAAC,6BAA6B,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;QAE5F,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,8BAA8B,CAAC,CAAC;QAE1E,IAAI,CAAC,mCAAmC,GAAG,8BAA8B,IAAI,IAAI,CAAC,mCAAmC,CAAC;QAEtH,IAAI,SAAS,EAAE,CAAC;YACZ,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;YAChC,IAAI,CAAC,aAAa,EAAE,CAAC;QACzB,CAAC;aACI,CAAC;YACF,IAAI,CAAC,mBAAmB,GAAG,KAAK,CAAC;YACjC,MAAM,IAAI,CAAC,yCAAyC,EAAE,CAAC;QAC3D,CAAC;QAED,IAAI,CAAC,iCAAiC,EAAE,CAAC;QAEzC,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACpF,CAAC,CAAC;IAEM,iCAAiC;QACrC,IAAI,CAAC,6BAA6B,GAAG,EAAE,CAAC;IAC5C,CAAC;IAEO,kBAAkB,CAAC,+BAA8C;QACrE,MAAM,iCAAiC,GAAG,IAAI,CAAC,6BAA6B,CAAC,+BAA+B,CAAC,CAAC;QAC9G,MAAM,wCAAwC,GAAG,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QAE9H,MAAM,mBAAmB,GAAG,iCAAiC,GAAG,wCAAwC,CAAC;QAEzG,OAAO,mBAAmB,GAAG,CAAC,CAAC;IACnC,CAAC;IAIO,KAAK,CAAC,yCAAyC;QACnD,IAAI,CAAC,oCAAoC,EAAE,CAAC;QAE5C,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,KAAK,EAAE,mBAAmB,EAAE,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,gBAAgB,EAAE,CAAC;QAEhH,IAAI,gBAAgB;YAChB,IAAI,CAAC,2CAA2C,EAAE,CAAC;aAClD,CAAC;YACF,IAAI,CAAC,+BAA+B,CAAC,mBAAmB,CAAC,CAAC;YAC1D,OAAO;QACX,CAAC;QAED,MAAM,kBAAkB,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC;QAEhE,MAAM,yBAAyB,GAAG,IAAI,CAAC,cAAc;YACjD,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,qBAAqB,CAAC,IAAI,CAAC,cAAc,CAAC;YAChE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAEjC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,MAAM,kBAAkB,CAAC;QAClF,MAAM,wBAAwB,GAAG,MAAM,yBAAyB,CAAC;QAEjE,IAAI,WAAW,IAAI,wBAAwB,EAAE,QAAQ,KAAK,IAAI;YAC1D,IAAI,CAAC,0BAA0B,EAAE,CAAC;aACjC,CAAC;YACF,MAAM,gBAAgB,GAAG,IAAI,CAAC,sBAAsB,CAAC,wBAAwB,CAAC,CAAC;YAE/E,IAAI,CAAC,yCAAyC,CAAC,gBAAgB,EAAE,wBAAwB,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;QACtH,CAAC;IACL,CAAC;IAEO,sBAAsB,CAAC,wBAAyD;QACpF,IAAI,CAAC,wBAAwB;YACzB,OAAO,SAAS,CAAC;QAErB,OAAO,wBAAwB,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IAC9D,CAAC;IAEO,aAAa;QACjB,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC7C,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,0BAA0B,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACnF,CAAC;IAIO,oCAAoC;QACxC,MAAM,SAAS,GAAoC;YAC/C,MAAM,EAAE;gBACJ,QAAQ,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;gBAChC,GAAG,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;gBAC3B,UAAU,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;aACrC;YACD,GAAG,IAAI,CAAC,mCAAmC;SAC9C,CAAC;QAEF,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,0BAA0B,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACrF,CAAC;IAEO,2CAA2C;QAC/C,MAAM,SAAS,GAAoC;YAC/C,MAAM,EAAE;gBACJ,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;gBAC1B,GAAG,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;gBAC3B,UAAU,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;aACrC;YACD,GAAG,IAAI,CAAC,mCAAmC;SAC9C,CAAC;QAEF,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,0BAA0B,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACrF,CAAC;IAEO,+BAA+B,CAAC,KAAa;QACjD,MAAM,SAAS,GAAoC;YAC/C,MAAM,EAAE;gBACJ,QAAQ,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE;gBACpC,GAAG,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE;gBAC1B,UAAU,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE;aACpC;YACD,GAAG,IAAI,CAAC,mCAAmC;SAC9C,CAAC;QAEF,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,0BAA0B,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACrF,CAAC;IAEO,yCAAyC,CAAC,gBAA4C,EAAE,eAAkC,EAAE,QAA2B;QAC3J,MAAM,SAAS,GAAoC;YAC/C,MAAM,EAAE;gBACJ,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;gBAC1B,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE;gBACvE,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE;aAC3G;YACD,GAAG,IAAI,CAAC,mCAAmC;SAC9C,CAAC;QAEF,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,0BAA0B,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACrF,CAAC;IAEO,0BAA0B;QAC9B,MAAM,SAAS,GAAoC;YAC/C,MAAM,EAAE;gBACJ,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;gBAC1B,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;gBACrB,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;aAC/B;YACD,GAAG,IAAI,CAAC,mCAAmC;SAC9C,CAAC;QAEF,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,0BAA0B,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACrF,CAAC;IAID,gBAAgB,CAAC,SAAiB,EAAE,OAA4B;QAC5D,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACpE,CAAC;CACJ","sourcesContent":["import type EventsEngine from \"../../utils/events/eventsEngine.js\";\r\nimport TransferHealthMonitorEvent from \"./events/transferHealthMonitorEvent.js\";\r\nimport HealthMonitorHealthyEventArgs from \"./events/eventArgs/healthMonitorHealthyEventArgs.js\";\r\nimport HealthMonitorUnhealthyEventArgs from \"./events/eventArgs/healthMonitorUnhealthyEventArgs.js\";\r\nimport OnlineChecker, { OnlineCheckerResult } from \"./onlineChecker/onlineChecker.js\";\r\n\r\nexport default abstract class TransferHealthMonitorBase<T> {\r\n readonly #onlineChecker: OnlineChecker;\r\n readonly #transferEventsEngine: EventsEngine;\r\n\r\n #healthCheckInterval: number;\r\n\r\n #timeout: ReturnType<typeof setTimeout> | undefined;\r\n\r\n #fileServerUrl: string | undefined;\r\n\r\n #currentPeriodProgressHistory: { time: number, eventArgs: T }[] = [];\r\n\r\n protected lastProgressEventFromPreviousPeriod: T | undefined;\r\n\r\n #isCurrentlyHealthy = true;\r\n\r\n constructor(onlineChecker: OnlineChecker, transferEventsEngine: EventsEngine, healthCheckInterval = 15_000) {\r\n if (!onlineChecker)\r\n throw new Error(`Online checker can't be empty`);\r\n if (!transferEventsEngine)\r\n throw new Error(`Events engine can't be empty`);\r\n\r\n this.#onlineChecker = onlineChecker;\r\n this.#transferEventsEngine = transferEventsEngine;\r\n\r\n this.#healthCheckInterval = healthCheckInterval;\r\n }\r\n\r\n start() {\r\n if (this.#timeout)\r\n throw new Error(`Health Monitor is already running`);\r\n\r\n this.resetState();\r\n\r\n this.subscribeToTransferRunningEvents();\r\n\r\n this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);\r\n }\r\n\r\n private resetState() {\r\n this.#currentPeriodProgressHistory = [];\r\n this.lastProgressEventFromPreviousPeriod = undefined;\r\n this.#timeout = undefined;\r\n this.#isCurrentlyHealthy = true;\r\n }\r\n\r\n stop() {\r\n clearTimeout(this.#timeout);\r\n\r\n this.#timeout = undefined;\r\n\r\n this.unsubscribeFromTransferRunningEvents();\r\n }\r\n\r\n private subscribeToTransferRunningEvents() {\r\n this.#transferEventsEngine.addEventListener(this.getFileServerKnownEventName(), this.fileServerKnownEventHandler);\r\n this.#transferEventsEngine.addEventListener(this.getTransferProgressedEventName(), this.transferProgressedEventHandler);\r\n }\r\n\r\n private unsubscribeFromTransferRunningEvents() {\r\n this.#transferEventsEngine.removeEventListener(this.getFileServerKnownEventName(), this.fileServerKnownEventHandler);\r\n this.#transferEventsEngine.removeEventListener(this.getTransferProgressedEventName(), this.transferProgressedEventHandler);\r\n }\r\n\r\n protected abstract getFileServerKnownEventName(): string;\r\n protected abstract getTransferProgressedEventName(): string;\r\n\r\n private fileServerKnownEventHandler = (eventArgs: unknown) => {\r\n this.#fileServerUrl = this.getFileServerUrlFromFileServerKnowEventArgs(eventArgs);\r\n };\r\n\r\n protected abstract getFileServerUrlFromFileServerKnowEventArgs(eventArgs: unknown): string;\r\n\r\n private transferProgressedEventHandler = (eventArgs: T) => {\r\n this.#currentPeriodProgressHistory.push({ time: Date.now(), eventArgs });\r\n\r\n if (this.#isCurrentlyHealthy)\r\n return;\r\n\r\n const isHealthy = this.determineIsHealthy(eventArgs);\r\n\r\n if (!isHealthy)\r\n return;\r\n\r\n this.notifyHealthy();\r\n this.restartHealthCheck(eventArgs);\r\n };\r\n\r\n private restartHealthCheck(currentProgressEvent: T) {\r\n this.#currentPeriodProgressHistory = [];\r\n this.lastProgressEventFromPreviousPeriod = currentProgressEvent;\r\n\r\n this.#isCurrentlyHealthy = true;\r\n\r\n clearTimeout(this.#timeout);\r\n this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);\r\n }\r\n\r\n private checkHealth = async (): Promise<void> => {\r\n const currentPeriodLastProgressEvent = this.#currentPeriodProgressHistory.at(-1)?.eventArgs;\r\n\r\n const isHealthy = this.determineIsHealthy(currentPeriodLastProgressEvent);\r\n\r\n this.lastProgressEventFromPreviousPeriod = currentPeriodLastProgressEvent || this.lastProgressEventFromPreviousPeriod;\r\n\r\n if (isHealthy) {\r\n this.#isCurrentlyHealthy = true;\r\n this.notifyHealthy();\r\n }\r\n else {\r\n this.#isCurrentlyHealthy = false;\r\n await this.figureOutUnhealthyReasonWithNotifications();\r\n }\r\n\r\n this.clearCurrentPeriodProgressHistory();\r\n\r\n this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);\r\n };\r\n\r\n private clearCurrentPeriodProgressHistory() {\r\n this.#currentPeriodProgressHistory = [];\r\n }\r\n\r\n private determineIsHealthy(currentHistoryLastProgressEvent: T | undefined) {\r\n const currentTransferredBytesTotalCount = this.getTransferredBytesTotalCount(currentHistoryLastProgressEvent);\r\n const previousPeriodTransferredBytesTotalCount = this.getTransferredBytesTotalCount(this.lastProgressEventFromPreviousPeriod);\r\n\r\n const bytesSentThisPeriod = currentTransferredBytesTotalCount - previousPeriodTransferredBytesTotalCount;\r\n\r\n return bytesSentThisPeriod > 0;\r\n }\r\n\r\n protected abstract getTransferredBytesTotalCount(currentHistoryLastProgressEvent?: T): number;\r\n\r\n private async figureOutUnhealthyReasonWithNotifications(): Promise<void> {\r\n this.notifyStartedCheckingUnhealthyReason();\r\n\r\n const { isOnline: isInternetOnline, error: internetOnlineError } = await this.#onlineChecker.isInternetOnline();\r\n\r\n if (isInternetOnline)\r\n this.notifyUnhealthyInternetOkRestCheckingReason();\r\n else {\r\n this.notifyUnhealthyNoInternetReason(internetOnlineError);\r\n return;\r\n }\r\n\r\n const isApiOnlinePromise = this.#onlineChecker.isApiReachable();\r\n\r\n const isFileServerOnlinePromise = this.#fileServerUrl\r\n ? this.#onlineChecker.isFileServerReachable(this.#fileServerUrl)\r\n : Promise.resolve(undefined);\r\n\r\n const { isOnline: isApiOnline, error: apiOnlineError } = await isApiOnlinePromise;\r\n const isFileServerOnlineResult = await isFileServerOnlinePromise;\r\n\r\n if (isApiOnline && isFileServerOnlineResult?.isOnline === true)\r\n this.notifyUnhealthyAllOkReason();\r\n else {\r\n const fileServerStatus = this.isOnlineResultToStatus(isFileServerOnlineResult);\r\n\r\n this.notifyUnhealthyApiOrFileServerErrorReason(fileServerStatus, isFileServerOnlineResult?.error, apiOnlineError);\r\n }\r\n }\r\n\r\n private isOnlineResultToStatus(isFileServerOnlineResult: OnlineCheckerResult | undefined): `Ok` | `Error` | `Unknown` {\r\n if (!isFileServerOnlineResult)\r\n return `Unknown`;\r\n\r\n return isFileServerOnlineResult.isOnline ? `Ok` : `Error`;\r\n }\r\n\r\n private notifyHealthy() {\r\n const eventArgs = this.getHealthyEventArgs();\r\n this.#transferEventsEngine.emit(TransferHealthMonitorEvent.Healthy, eventArgs);\r\n }\r\n\r\n protected abstract getHealthyEventArgs(): HealthMonitorHealthyEventArgs;\r\n\r\n private notifyStartedCheckingUnhealthyReason() {\r\n const eventArgs: HealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Checking` },\r\n api: { status: `Checking` },\r\n fileServer: { status: `Checking` },\r\n },\r\n ...this.lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyInternetOkRestCheckingReason() {\r\n const eventArgs: HealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Ok` },\r\n api: { status: `Checking` },\r\n fileServer: { status: `Checking` },\r\n },\r\n ...this.lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyNoInternetReason(error?: Error) {\r\n const eventArgs: HealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Error`, error },\r\n api: { status: `Unknown` },\r\n fileServer: { status: `Unknown` },\r\n },\r\n ...this.lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyApiOrFileServerErrorReason(fileServerStatus: `Ok` | `Error` | `Unknown`, fileServerError: Error | undefined, apiError: Error | undefined) {\r\n const eventArgs: HealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Ok` },\r\n api: apiError ? { status: `Error`, error: apiError } : { status: `Ok` },\r\n fileServer: fileServerError ? { status: `Error`, error: fileServerError } : { status: fileServerStatus },\r\n },\r\n ...this.lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyAllOkReason() {\r\n const eventArgs: HealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Ok` },\r\n api: { status: `Ok` },\r\n fileServer: { status: `Ok` },\r\n },\r\n ...this.lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n addEventListener(eventName: TransferHealthMonitorEvent.Healthy, handler: (event: HealthMonitorHealthyEventArgs) => void): void\r\n addEventListener(eventName: TransferHealthMonitorEvent.Unhealthy, handler: (event: HealthMonitorUnhealthyEventArgs) => void): void\r\n addEventListener(eventName: string, handler: (arg?: any) => void): void {\r\n this.#transferEventsEngine.addEventListener(eventName, handler);\r\n }\r\n}"]}
|
|
1
|
+
{"version":3,"file":"transferHealthMonitorBase.js","sourceRoot":"","sources":["../../../../src/client/healthMonitor/transferHealthMonitorBase.ts"],"names":[],"mappings":"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","sourcesContent":["import type EventsEngine from \"../../utils/events/eventsEngine.js\";\r\nimport TransferHealthMonitorEvent from \"./events/transferHealthMonitorEvent.js\";\r\nimport HealthMonitorHealthyEventArgs from \"./events/eventArgs/healthMonitorHealthyEventArgs.js\";\r\nimport HealthMonitorUnhealthyEventArgs from \"./events/eventArgs/healthMonitorUnhealthyEventArgs.js\";\r\nimport OnlineChecker, { OnlineCheckerResult } from \"./onlineChecker/onlineChecker.js\";\r\n\r\nexport default abstract class TransferHealthMonitorBase<T> {\r\n readonly #onlineChecker: OnlineChecker;\r\n readonly #transferEventsEngine: EventsEngine;\r\n\r\n #healthCheckInterval: number;\r\n\r\n #timeout: ReturnType<typeof setTimeout> | undefined;\r\n\r\n #fileServerUrl: string | undefined;\r\n\r\n #currentPeriodProgressHistory: { time: number, eventArgs: T }[] = [];\r\n\r\n protected lastProgressEventFromPreviousPeriod: T | undefined;\r\n\r\n #isCurrentlyHealthy = true;\r\n\r\n constructor(onlineChecker: OnlineChecker, transferEventsEngine: EventsEngine, healthCheckInterval = 15_000) {\r\n if (!onlineChecker)\r\n throw new Error(`Online checker can't be empty`);\r\n if (!transferEventsEngine)\r\n throw new Error(`Events engine can't be empty`);\r\n\r\n this.#onlineChecker = onlineChecker;\r\n this.#transferEventsEngine = transferEventsEngine;\r\n\r\n this.#healthCheckInterval = healthCheckInterval;\r\n }\r\n\r\n start() {\r\n if (this.#timeout)\r\n throw new Error(`Health Monitor is already running`);\r\n\r\n this.resetState();\r\n\r\n this.subscribeToTransferRunningEvents();\r\n\r\n this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);\r\n }\r\n\r\n private resetState() {\r\n this.#currentPeriodProgressHistory = [];\r\n this.lastProgressEventFromPreviousPeriod = undefined;\r\n this.#timeout = undefined;\r\n this.#isCurrentlyHealthy = true;\r\n }\r\n\r\n stop() {\r\n clearTimeout(this.#timeout);\r\n\r\n this.#timeout = undefined;\r\n\r\n this.unsubscribeFromTransferRunningEvents();\r\n }\r\n\r\n private subscribeToTransferRunningEvents() {\r\n this.#transferEventsEngine.addEventListener(this.getFileServerKnownEventName(), this.fileServerKnownEventHandler);\r\n this.#transferEventsEngine.addEventListener(this.getTransferProgressedEventName(), this.transferProgressedEventHandler);\r\n }\r\n\r\n private unsubscribeFromTransferRunningEvents() {\r\n this.#transferEventsEngine.removeEventListener(this.getFileServerKnownEventName(), this.fileServerKnownEventHandler);\r\n this.#transferEventsEngine.removeEventListener(this.getTransferProgressedEventName(), this.transferProgressedEventHandler);\r\n }\r\n\r\n protected abstract getFileServerKnownEventName(): string;\r\n protected abstract getTransferProgressedEventName(): string;\r\n\r\n private fileServerKnownEventHandler = (eventArgs: unknown) => {\r\n this.#fileServerUrl = this.getFileServerUrlFromFileServerKnowEventArgs(eventArgs);\r\n };\r\n\r\n protected abstract getFileServerUrlFromFileServerKnowEventArgs(eventArgs: unknown): string;\r\n\r\n private transferProgressedEventHandler = (eventArgs: T) => {\r\n this.#currentPeriodProgressHistory.push({ time: Date.now(), eventArgs });\r\n\r\n if (this.#isCurrentlyHealthy)\r\n return;\r\n\r\n const isHealthy = this.determineIsHealthy(eventArgs);\r\n\r\n if (!isHealthy)\r\n return;\r\n\r\n this.notifyHealthy();\r\n this.restartHealthCheck(eventArgs);\r\n };\r\n\r\n private restartHealthCheck(currentProgressEvent: T) {\r\n this.#currentPeriodProgressHistory = [];\r\n this.lastProgressEventFromPreviousPeriod = currentProgressEvent;\r\n\r\n this.#isCurrentlyHealthy = true;\r\n\r\n clearTimeout(this.#timeout);\r\n this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);\r\n }\r\n\r\n private checkHealth = async (): Promise<void> => {\r\n const history = this.#currentPeriodProgressHistory;\r\n const currentPeriodLastProgressEvent = history.length > 0 ? history[history.length - 1].eventArgs : undefined;\r\n\r\n const isHealthy = this.determineIsHealthy(currentPeriodLastProgressEvent);\r\n\r\n this.lastProgressEventFromPreviousPeriod = currentPeriodLastProgressEvent || this.lastProgressEventFromPreviousPeriod;\r\n\r\n if (isHealthy) {\r\n this.#isCurrentlyHealthy = true;\r\n this.notifyHealthy();\r\n }\r\n else {\r\n this.#isCurrentlyHealthy = false;\r\n await this.figureOutUnhealthyReasonWithNotifications();\r\n }\r\n\r\n this.clearCurrentPeriodProgressHistory();\r\n\r\n this.#timeout = setTimeout(() => this.checkHealth(), this.#healthCheckInterval);\r\n };\r\n\r\n private clearCurrentPeriodProgressHistory() {\r\n this.#currentPeriodProgressHistory = [];\r\n }\r\n\r\n private determineIsHealthy(currentHistoryLastProgressEvent: T | undefined) {\r\n const currentTransferredBytesTotalCount = this.getTransferredBytesTotalCount(currentHistoryLastProgressEvent);\r\n const previousPeriodTransferredBytesTotalCount = this.getTransferredBytesTotalCount(this.lastProgressEventFromPreviousPeriod);\r\n\r\n const bytesSentThisPeriod = currentTransferredBytesTotalCount - previousPeriodTransferredBytesTotalCount;\r\n\r\n return bytesSentThisPeriod > 0;\r\n }\r\n\r\n protected abstract getTransferredBytesTotalCount(currentHistoryLastProgressEvent?: T): number;\r\n\r\n private async figureOutUnhealthyReasonWithNotifications(): Promise<void> {\r\n this.notifyStartedCheckingUnhealthyReason();\r\n\r\n const { isOnline: isInternetOnline, error: internetOnlineError } = await this.#onlineChecker.isInternetOnline();\r\n\r\n if (isInternetOnline)\r\n this.notifyUnhealthyInternetOkRestCheckingReason();\r\n else {\r\n this.notifyUnhealthyNoInternetReason(internetOnlineError);\r\n return;\r\n }\r\n\r\n const isApiOnlinePromise = this.#onlineChecker.isApiReachable();\r\n\r\n const isFileServerOnlinePromise = this.#fileServerUrl\r\n ? this.#onlineChecker.isFileServerReachable(this.#fileServerUrl)\r\n : Promise.resolve(undefined);\r\n\r\n const { isOnline: isApiOnline, error: apiOnlineError } = await isApiOnlinePromise;\r\n const isFileServerOnlineResult = await isFileServerOnlinePromise;\r\n\r\n if (isApiOnline && isFileServerOnlineResult?.isOnline === true)\r\n this.notifyUnhealthyAllOkReason();\r\n else {\r\n const fileServerStatus = this.isOnlineResultToStatus(isFileServerOnlineResult);\r\n\r\n this.notifyUnhealthyApiOrFileServerErrorReason(fileServerStatus, isFileServerOnlineResult?.error, apiOnlineError);\r\n }\r\n }\r\n\r\n private isOnlineResultToStatus(isFileServerOnlineResult: OnlineCheckerResult | undefined): `Ok` | `Error` | `Unknown` {\r\n if (!isFileServerOnlineResult)\r\n return `Unknown`;\r\n\r\n return isFileServerOnlineResult.isOnline ? `Ok` : `Error`;\r\n }\r\n\r\n private notifyHealthy() {\r\n const eventArgs = this.getHealthyEventArgs();\r\n this.#transferEventsEngine.emit(TransferHealthMonitorEvent.Healthy, eventArgs);\r\n }\r\n\r\n protected abstract getHealthyEventArgs(): HealthMonitorHealthyEventArgs;\r\n\r\n private notifyStartedCheckingUnhealthyReason() {\r\n const eventArgs: HealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Checking` },\r\n api: { status: `Checking` },\r\n fileServer: { status: `Checking` },\r\n },\r\n ...this.lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyInternetOkRestCheckingReason() {\r\n const eventArgs: HealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Ok` },\r\n api: { status: `Checking` },\r\n fileServer: { status: `Checking` },\r\n },\r\n ...this.lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyNoInternetReason(error?: Error) {\r\n const eventArgs: HealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Error`, error },\r\n api: { status: `Unknown` },\r\n fileServer: { status: `Unknown` },\r\n },\r\n ...this.lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyApiOrFileServerErrorReason(fileServerStatus: `Ok` | `Error` | `Unknown`, fileServerError: Error | undefined, apiError: Error | undefined) {\r\n const eventArgs: HealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Ok` },\r\n api: apiError ? { status: `Error`, error: apiError } : { status: `Ok` },\r\n fileServer: fileServerError ? { status: `Error`, error: fileServerError } : { status: fileServerStatus },\r\n },\r\n ...this.lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n private notifyUnhealthyAllOkReason() {\r\n const eventArgs: HealthMonitorUnhealthyEventArgs = {\r\n reason: {\r\n internet: { status: `Ok` },\r\n api: { status: `Ok` },\r\n fileServer: { status: `Ok` },\r\n },\r\n ...this.lastProgressEventFromPreviousPeriod,\r\n };\r\n\r\n this.#transferEventsEngine.emit(TransferHealthMonitorEvent.Unhealthy, eventArgs);\r\n }\r\n\r\n addEventListener(eventName: TransferHealthMonitorEvent.Healthy, handler: (event: HealthMonitorHealthyEventArgs) => void): void\r\n addEventListener(eventName: TransferHealthMonitorEvent.Unhealthy, handler: (event: HealthMonitorUnhealthyEventArgs) => void): void\r\n addEventListener(eventName: string, handler: (arg?: any) => void): void {\r\n this.#transferEventsEngine.addEventListener(eventName, handler);\r\n }\r\n}"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeFileServerDownloadClient.js","sourceRoot":"","sources":["../../../../../src/downloader/api/node/nodeFileServerDownloadClient.ts"],"names":[],"mappings":"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","sourcesContent":["import got, { Got, Headers as GotHeaders, Options as GotOptions, Request as GotRequest } from \"got\";\r\nimport { pipeline } from \"stream/promises\";\r\n\r\nimport type DownloadOptions from \"../../downloadOptions.js\";\r\nimport type ChunkStreamProvider from \"../../../utils/fileSystem/chunkStreamProvider.js\";\r\nimport { type BaseResponse, isBaseResponse } from \"../../../utils/api/dtos/baseResponse.js\";\r\nimport type GetRangehashResponse from \"../../../utils/api/dtos/getRangehashResponse.js\";\r\nimport type GetCompressedFileMetadataResponse from \"../../../utils/api/dtos/getCompressedFileMetadataResponse.js\";\r\nimport type FileServerDownloadClient from \"../fileServerDownloadClient.js\";\r\nimport NodeFileServerClientBase from \"../../../utils/api/node/nodeFileserverClientBase.js\";\r\nimport UrlUtil from \"../../../utils/api/urlUtil.js\";\r\nimport { retryEconnresetWorkaround } from \"../../../utils/api/node/gotWorkarounds.js\";\r\n\r\nexport default class NodeFileServerDownloadClient extends NodeFileServerClientBase implements FileServerDownloadClient {\r\n #downloadUrl: string;\r\n #start: number | null;\r\n #end: number | null;\r\n #options: DownloadOptions;\r\n #fileName: string;\r\n #transferId: string;\r\n #fileserverClient: Got;\r\n #downloadStream: GotRequest | null = null;\r\n #downloadIdleTimeoutInMs: number;\r\n\r\n constructor(downloadUrl: string, start: number | null, end: number | null, transferId: string, fileName: string, options: DownloadOptions, downloadIdleTimeoutInMs: number) {\r\n super();\r\n\r\n this.#downloadUrl = downloadUrl;\r\n this.#start = start;\r\n this.#end = end;\r\n this.#options = options;\r\n this.#transferId = transferId;\r\n this.#fileName = fileName;\r\n this.#fileserverClient = this.#createBaseGotInstance();\r\n this.#downloadIdleTimeoutInMs = downloadIdleTimeoutInMs;\r\n }\r\n\r\n async download(chunkStreamProvider: ChunkStreamProvider): Promise<void> {\r\n this.#throwIfRunning();\r\n\r\n const downloadRequest = this.#createGotChunkDownloadOptions();\r\n this.#downloadStream = got.stream(this.#downloadUrl, { ...downloadRequest });\r\n const { fileStream, decipherStream } = await chunkStreamProvider.getChunkWriteStream();\r\n\r\n const progressHandler = this.getDataTransferProgressHandler();\r\n this.#downloadStream.on(`downloadProgress`, progressHandler);\r\n\r\n if (decipherStream) {\r\n return await pipeline(\r\n this.#downloadStream,\r\n decipherStream,\r\n fileStream,\r\n );\r\n }\r\n\r\n return pipeline(\r\n this.#downloadStream,\r\n fileStream,\r\n );\r\n }\r\n\r\n release(): void {\r\n this.#downloadStream?.destroy();\r\n this.#downloadStream = null;\r\n }\r\n\r\n async getMd5Checksum(): Promise<string> {\r\n if (this.#start === null || this.#end === null)\r\n throw new Error(`MD5 checksum cannot be calculated if the start or end is not known --> ${this.#downloadUrl}:${this.#start}:${this.#end}`);\r\n\r\n const rangeHashOptions = this.#crateGotRangeHashOptions();\r\n const md5response = await this.#fileserverClient(`GetRangehash.ashx`, rangeHashOptions).json<GetRangehashResponse>();\r\n\r\n this.#throwIfResponseNotOk(md5response);\r\n\r\n if (!md5response.hash)\r\n throw new Error(`Range hash is empty --> ${this.#downloadUrl}:${this.#start}:${this.#end}`);\r\n\r\n return md5response.hash;\r\n }\r\n\r\n async getCompressedFileMetadata(): Promise<GetCompressedFileMetadataResponse> {\r\n this.#throwIfRunning();\r\n\r\n const metadataResponse = await got.head(this.#downloadUrl);\r\n\r\n if (metadataResponse.statusCode !== 200)\r\n throw new Error(`HTTP ${metadataResponse.statusCode}`);\r\n\r\n const disposition = metadataResponse.headers[`content-disposition`];\r\n let fileName = ``;\r\n if (disposition && disposition.indexOf(`attachment;`) === 0) {\r\n const filenameRegex = /filename\\*?=['\"]?(?:UTF-\\d['\"]*)?([^;\\r\\n\"']*)['\"]?;?/;\r\n const matches = filenameRegex.exec(disposition);\r\n if (matches && matches.length > 1 && matches[1])\r\n fileName = matches[1];\r\n }\r\n return {\r\n fileSize: parseInt(metadataResponse.headers[`content-length`]!, 10),\r\n fileName,\r\n };\r\n }\r\n\r\n #throwIfRunning() {\r\n if (this.#downloadStream)\r\n throw new Error(`Attempted to run a chunk download while it is already running`);\r\n }\r\n\r\n #throwIfResponseNotOk(response: BaseResponse<unknown>) {\r\n if (!isBaseResponse(response))\r\n throw new Error(`FS response is not a valid base response object --> ${this.#downloadUrl}:${this.#start}:${this.#end}`);\r\n\r\n if (response.responsestatus !== `OK`)\r\n throw new Error(`${response.responsestatus}: ${response.errormessage}`);\r\n }\r\n\r\n #crateGotRangeHashOptions() {\r\n return {\r\n searchParams: {\r\n transferid: this.#transferId,\r\n thefilename: this.#fileName,\r\n position: this.#start!,\r\n length: 1 + this.#end! - this.#start!,\r\n },\r\n retry: {\r\n limit: 5,\r\n backoffLimit: 10000,\r\n },\r\n };\r\n }\r\n\r\n #createGotChunkDownloadOptions(): GotOptions {\r\n const query = UrlUtil.getQueryStringFromUrl(this.#downloadUrl);\r\n const headers: GotHeaders = {};\r\n\r\n if (this.#options.userAgent)\r\n headers[`User-Agent`] = this.#options.userAgent;\r\n\r\n if (this.#start !== null && this.#end !== null)\r\n headers.Range = `bytes=${this.#start}-${this.#end}`;\r\n\r\n return new GotOptions({\r\n headers,\r\n searchParams: {\r\n ...query, // need to unfold original query - when using url with query included got will replace the query with provided searchParams option\r\n skipreg: true, // make sure to implement download registrations - figure out a good way for file-by-file scenarios (current desktop v2 is a bit verbose...)\r\n skipcheck: true,\r\n },\r\n timeout: {\r\n socket: this.#downloadIdleTimeoutInMs > 0 ? this.#downloadIdleTimeoutInMs : undefined,\r\n },\r\n });\r\n }\r\n\r\n #createBaseGotInstance(): Got {\r\n const headers: GotHeaders = {};\r\n\r\n if (this.#options.userAgent)\r\n headers[`User-Agent`] = this.#options.userAgent;\r\n\r\n return got.extend({\r\n prefixUrl: UrlUtil.getHostFromUrl(this.#downloadUrl),\r\n headers,\r\n retry: {\r\n ...retryEconnresetWorkaround,\r\n },\r\n });\r\n }\r\n}"]}
|
|
1
|
+
{"version":3,"file":"nodeFileServerDownloadClient.js","sourceRoot":"","sources":["../../../../../src/downloader/api/node/nodeFileServerDownloadClient.ts"],"names":[],"mappings":"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","sourcesContent":["import got, { Got, Headers as GotHeaders, Options as GotOptions, Request as GotRequest } from \"got\";\r\nimport { pipeline } from \"stream/promises\";\r\n\r\nimport type DownloadOptions from \"../../downloadOptions.js\";\r\nimport type ChunkStreamProvider from \"../../../utils/fileSystem/chunkStreamProvider.js\";\r\nimport { type BaseResponse, isBaseResponse } from \"../../../utils/api/dtos/baseResponse.js\";\r\nimport type GetRangehashResponse from \"../../../utils/api/dtos/getRangehashResponse.js\";\r\nimport type GetCompressedFileMetadataResponse from \"../../../utils/api/dtos/getCompressedFileMetadataResponse.js\";\r\nimport type FileServerDownloadClient from \"../fileServerDownloadClient.js\";\r\nimport NodeFileServerClientBase from \"../../../utils/api/node/nodeFileserverClientBase.js\";\r\nimport UrlUtil from \"../../../utils/api/urlUtil.js\";\r\nimport { retryEconnresetWorkaround } from \"../../../utils/api/node/gotWorkarounds.js\";\r\n\r\nexport default class NodeFileServerDownloadClient extends NodeFileServerClientBase implements FileServerDownloadClient {\r\n #downloadUrl: string;\r\n #start: number | null;\r\n #end: number | null;\r\n #options: DownloadOptions;\r\n #fileName: string;\r\n #transferId: string;\r\n #fileserverClient: Got;\r\n #downloadStream: GotRequest | null = null;\r\n #downloadIdleTimeoutInMs: number;\r\n\r\n constructor(downloadUrl: string, start: number | null, end: number | null, transferId: string, fileName: string, options: DownloadOptions, downloadIdleTimeoutInMs: number) {\r\n super();\r\n\r\n this.#downloadUrl = downloadUrl;\r\n this.#start = start;\r\n this.#end = end;\r\n this.#options = options;\r\n this.#transferId = transferId;\r\n this.#fileName = fileName;\r\n this.#fileserverClient = this.#createBaseGotInstance();\r\n this.#downloadIdleTimeoutInMs = downloadIdleTimeoutInMs;\r\n }\r\n\r\n async download(chunkStreamProvider: ChunkStreamProvider): Promise<void> {\r\n this.#throwIfRunning();\r\n\r\n const downloadRequest = this.#createGotChunkDownloadOptions();\r\n this.#downloadStream = got.stream(this.#downloadUrl, { ...downloadRequest });\r\n const { fileStream, decipherStream } = await chunkStreamProvider.getChunkWriteStream();\r\n\r\n const progressHandler = this.getDataTransferProgressHandler();\r\n this.#downloadStream.on(`downloadProgress`, progressHandler);\r\n\r\n if (decipherStream) {\r\n return await pipeline(\r\n this.#downloadStream,\r\n decipherStream as unknown as NodeJS.ReadWriteStream,\r\n fileStream,\r\n );\r\n }\r\n\r\n return pipeline(\r\n this.#downloadStream,\r\n fileStream,\r\n );\r\n }\r\n\r\n release(): void {\r\n this.#downloadStream?.destroy();\r\n this.#downloadStream = null;\r\n }\r\n\r\n async getMd5Checksum(): Promise<string> {\r\n if (this.#start === null || this.#end === null)\r\n throw new Error(`MD5 checksum cannot be calculated if the start or end is not known --> ${this.#downloadUrl}:${this.#start}:${this.#end}`);\r\n\r\n const rangeHashOptions = this.#crateGotRangeHashOptions();\r\n const md5response = await this.#fileserverClient(`GetRangehash.ashx`, rangeHashOptions).json<GetRangehashResponse>();\r\n\r\n this.#throwIfResponseNotOk(md5response);\r\n\r\n if (!md5response.hash)\r\n throw new Error(`Range hash is empty --> ${this.#downloadUrl}:${this.#start}:${this.#end}`);\r\n\r\n return md5response.hash;\r\n }\r\n\r\n async getCompressedFileMetadata(): Promise<GetCompressedFileMetadataResponse> {\r\n this.#throwIfRunning();\r\n\r\n const metadataResponse = await got.head(this.#downloadUrl);\r\n\r\n if (metadataResponse.statusCode !== 200)\r\n throw new Error(`HTTP ${metadataResponse.statusCode}`);\r\n\r\n const disposition = metadataResponse.headers[`content-disposition`];\r\n let fileName = ``;\r\n if (disposition && disposition.indexOf(`attachment;`) === 0) {\r\n const filenameRegex = /filename\\*?=['\"]?(?:UTF-\\d['\"]*)?([^;\\r\\n\"']*)['\"]?;?/;\r\n const matches = filenameRegex.exec(disposition);\r\n if (matches && matches.length > 1 && matches[1])\r\n fileName = matches[1];\r\n }\r\n return {\r\n fileSize: parseInt(metadataResponse.headers[`content-length`]!, 10),\r\n fileName,\r\n };\r\n }\r\n\r\n #throwIfRunning() {\r\n if (this.#downloadStream)\r\n throw new Error(`Attempted to run a chunk download while it is already running`);\r\n }\r\n\r\n #throwIfResponseNotOk(response: BaseResponse<unknown>) {\r\n if (!isBaseResponse(response))\r\n throw new Error(`FS response is not a valid base response object --> ${this.#downloadUrl}:${this.#start}:${this.#end}`);\r\n\r\n if (response.responsestatus !== `OK`)\r\n throw new Error(`${response.responsestatus}: ${response.errormessage}`);\r\n }\r\n\r\n #crateGotRangeHashOptions() {\r\n return {\r\n searchParams: {\r\n transferid: this.#transferId,\r\n thefilename: this.#fileName,\r\n position: this.#start!,\r\n length: 1 + this.#end! - this.#start!,\r\n },\r\n retry: {\r\n limit: 5,\r\n backoffLimit: 10000,\r\n },\r\n };\r\n }\r\n\r\n #createGotChunkDownloadOptions(): GotOptions {\r\n const query = UrlUtil.getQueryStringFromUrl(this.#downloadUrl);\r\n const headers: GotHeaders = {};\r\n\r\n if (this.#options.userAgent)\r\n headers[`User-Agent`] = this.#options.userAgent;\r\n\r\n if (this.#start !== null && this.#end !== null)\r\n headers.Range = `bytes=${this.#start}-${this.#end}`;\r\n\r\n return new GotOptions({\r\n headers,\r\n searchParams: {\r\n ...query, // need to unfold original query - when using url with query included got will replace the query with provided searchParams option\r\n skipreg: true, // make sure to implement download registrations - figure out a good way for file-by-file scenarios (current desktop v2 is a bit verbose...)\r\n skipcheck: true,\r\n },\r\n timeout: {\r\n socket: this.#downloadIdleTimeoutInMs > 0 ? this.#downloadIdleTimeoutInMs : undefined,\r\n },\r\n });\r\n }\r\n\r\n #createBaseGotInstance(): Got {\r\n const headers: GotHeaders = {};\r\n\r\n if (this.#options.userAgent)\r\n headers[`User-Agent`] = this.#options.userAgent;\r\n\r\n return got.extend({\r\n prefixUrl: UrlUtil.getHostFromUrl(this.#downloadUrl),\r\n headers,\r\n retry: {\r\n ...retryEconnresetWorkaround,\r\n },\r\n });\r\n }\r\n}"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeFileserverClientBase.d.ts","sourceRoot":"","sources":["../../../../../src/utils/api/node/nodeFileserverClientBase.ts"],"names":[],"mappings":"AACA,OAAO,cAAc,MAAM,qBAAqB,CAAC;AAEjD,MAAM,CAAC,OAAO,OAAO,wBAAyB,SAAQ,cAAc;IAChE,SAAS,CAAC,8BAA8B,
|
|
1
|
+
{"version":3,"file":"nodeFileserverClientBase.d.ts","sourceRoot":"","sources":["../../../../../src/utils/api/node/nodeFileserverClientBase.ts"],"names":[],"mappings":"AACA,OAAO,cAAc,MAAM,qBAAqB,CAAC;AAEjD,MAAM,CAAC,OAAO,OAAO,wBAAyB,SAAQ,cAAc;IAChE,SAAS,CAAC,8BAA8B,KAG5B,UAAU;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE;CAgBhD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webClientBase.js","sourceRoot":"","sources":["../../../../../src/utils/api/web/webClientBase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAE1C,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,gBAAgB,MAAM,wBAAwB,CAAC;AACtD,OAAO,mBAAmB,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,eAAe,MAAM,qCAAqC,CAAC;AAClE,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAKhD,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,aAAa;IACjC,YAAY,CAAe;IAE9C;QACI,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,YAAY,GAAG,IAAI,eAAe,EAAE,CAAC;IAC9C,CAAC;IAEM,gBAAgB,CAAC,SAAiB,EAAE,OAA6B;QACpE,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;IAEM,mBAAmB,CAAC,SAAiB,EAAE,OAA6B;QACvE,IAAI,CAAC,YAAY,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAES,cAAc,CAAC,KAAc,EAAE,YAAoB,EAAE,iBAA+B;QAC1F,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAClD,OAAO,IAAI,QAAQ,CAAC,YAAY,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;IAEO,kBAAkB,CAAC,KAAc;QACrC,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC;YACzB,OAAO,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC;QAElC,OAAO,SAAS,CAAC;IACrB,CAAC;IAEO,aAAa,CAAC,KAAc,EAAE,iBAA+B;QACjE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC;YAC1B,OAAO,KAAc,CAAC;QAE1B,MAAM,qBAAqB,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAE9D,IAAI,qBAAqB,EAAE,CAAC;YACxB,MAAM,mBAAmB,GAAG,qBAAqB,CAAC,YAAY,IAAI,qBAAqB,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,qBAAqB,CAAC,SAAS,IAAI,SAAS,CAAC;YAC9J,MAAM,SAAS,GAAG,GAAG,qBAAqB,CAAC,cAAc,KAAK,mBAAmB,EAAE,CAAC;YAEpF,OAAO,IAAI,gBAAgB,CAAC,SAAS,EAAE,mBAAmB,EAAE,qBAAqB,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"webClientBase.js","sourceRoot":"","sources":["../../../../../src/utils/api/web/webClientBase.ts"],"names":[],"mappings":"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","sourcesContent":["import axios, { AxiosError } from \"axios\";\r\n\r\nimport ApiError from \"../apiError.js\";\r\nimport ApiFilemailError from \"../apiFilemailError.js\";\r\nimport ApiFilemail449Error from \"../apiFilemail449Error.js\";\r\nimport { isBaseResponse } from \"../dtos/baseResponse.js\";\r\nimport WebEventsEngine from \"../../events/web/webEventsEngine.js\";\r\nimport ApiClientBase from \"../apiClientBase.js\";\r\n\r\nimport type EventsEngine from \"../../events/eventsEngine.js\";\r\nimport type { BaseResponse } from \"../dtos/baseResponse.js\";\r\n\r\nexport default class WebClientBase extends ApiClientBase {\r\n protected readonly eventsEngine: EventsEngine;\r\n\r\n constructor() {\r\n super();\r\n this.eventsEngine = new WebEventsEngine();\r\n }\r\n\r\n public addEventListener(eventName: string, handler: (event: any) => void): void {\r\n this.eventsEngine.addEventListener(eventName, handler);\r\n }\r\n\r\n public removeEventListener(eventName: string, handler: (event: any) => void): void {\r\n this.eventsEngine.removeEventListener(eventName, handler);\r\n }\r\n\r\n protected createApiError(error: unknown, errorMessage: string, idleTimeoutSignal?: AbortSignal) {\r\n const cause = this.getErrorCause(error, idleTimeoutSignal);\r\n const httpStatus = this.getErrorHttpStatus(error);\r\n return new ApiError(errorMessage, httpStatus, { cause });\r\n }\r\n\r\n private getErrorHttpStatus(error: unknown): number | undefined {\r\n if (axios.isAxiosError(error))\r\n return error.response?.status;\r\n\r\n return undefined;\r\n }\r\n\r\n private getErrorCause(error: unknown, idleTimeoutSignal?: AbortSignal): Error {\r\n if (!axios.isAxiosError(error))\r\n return error as Error;\r\n\r\n const filemailErrorResponse = this.tryGetErrorResponse(error);\r\n\r\n if (filemailErrorResponse) {\r\n const filemailErrorReason = filemailErrorResponse.errormessage || filemailErrorResponse.errorcode?.toString() || filemailErrorResponse.exception || `UNKNOWN`;\r\n const errorText = `${filemailErrorResponse.responsestatus}: ${filemailErrorReason}`;\r\n\r\n return new ApiFilemailError(errorText, filemailErrorReason, filemailErrorResponse.responsestatus, { cause: error as Error });\r\n }\r\n\r\n const response449Message = this.tryGet449Response(error);\r\n\r\n if (response449Message)\r\n return new ApiFilemail449Error(response449Message);\r\n\r\n const errorReasonText = this.getErrorReasonText(error, idleTimeoutSignal);\r\n\r\n return new Error(errorReasonText, { cause: error as Error });\r\n }\r\n\r\n private tryGetErrorResponse(error: AxiosError<any, any>): BaseResponse<unknown> | null {\r\n try {\r\n if (this.isBaseNotOkResponse(error.response?.data))\r\n return error.response.data;\r\n\r\n if (typeof error.response?.data !== `string`)\r\n return null;\r\n\r\n const response = JSON.parse(error.response?.data);\r\n\r\n if (this.isBaseNotOkResponse(response))\r\n return response;\r\n\r\n return null;\r\n }\r\n catch {\r\n return null;\r\n }\r\n }\r\n\r\n private isBaseNotOkResponse(obj: any): obj is BaseResponse<unknown> {\r\n return isBaseResponse(obj) && obj.responsestatus !== `OK`;\r\n }\r\n\r\n private tryGet449Response(error: AxiosError<any, any>): string | null {\r\n try {\r\n if (error.response?.status !== 449)\r\n return null;\r\n\r\n if (typeof error.response?.data !== `string`)\r\n return null;\r\n\r\n return error.response?.data;\r\n }\r\n catch {\r\n return null;\r\n }\r\n }\r\n\r\n private getErrorReasonText(error: AxiosError<any, any>, idleTimeoutSignal?: AbortSignal): string {\r\n const isIdleTimeout = error.code === `ERR_CANCELED` && idleTimeoutSignal?.aborted;\r\n const isRequestTimeout = error.code === `ECONNABORTED` && error.message.startsWith(`timeout`);\r\n\r\n if (isIdleTimeout || isRequestTimeout)\r\n return `Timeout`;\r\n\r\n if (error.response?.status)\r\n return `${error.response.status}: ${error.response.statusText || error.code || error.message}`;\r\n\r\n if (error.code)\r\n return error.code;\r\n\r\n if (error.message)\r\n return error.message;\r\n\r\n return `UKNOWN API ERROR`;\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webFileserverClientBase.d.ts","sourceRoot":"","sources":["../../../../../src/utils/api/web/webFileserverClientBase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAG3C,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,uBAAwB,SAAQ,aAAa;IAC9D,SAAS,CAAC,8BAA8B,
|
|
1
|
+
{"version":3,"file":"webFileserverClientBase.d.ts","sourceRoot":"","sources":["../../../../../src/utils/api/web/webFileserverClientBase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAG3C,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,uBAAwB,SAAQ,aAAa;IAC9D,SAAS,CAAC,8BAA8B,KAG5B,UAAU,kBAAkB;CAgB3C"}
|
|
@@ -3,6 +3,7 @@ export default class WebCryptographyProvider implements CryptographyProvider {
|
|
|
3
3
|
#private;
|
|
4
4
|
deriveKey(userInputKey: string, salt: Uint8Array): Promise<Uint8Array>;
|
|
5
5
|
generateHmac(encryptionKey: Uint8Array): Promise<Uint8Array>;
|
|
6
|
+
private ensureArrayBuffer;
|
|
6
7
|
generateRandomString(length: number): string;
|
|
7
8
|
generateRandomInteger(min: number, max: number): number;
|
|
8
9
|
generateRandomBytes(length: number): Uint8Array;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webCryptographyProvider.d.ts","sourceRoot":"","sources":["../../../../../src/utils/crypto/web/webCryptographyProvider.ts"],"names":[],"mappings":"AAAA,OAAO,oBAAoB,MAAM,4BAA4B,CAAC;AAE9D,MAAM,CAAC,OAAO,OAAO,uBAAwB,YAAW,oBAAoB;;IAGlE,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"webCryptographyProvider.d.ts","sourceRoot":"","sources":["../../../../../src/utils/crypto/web/webCryptographyProvider.ts"],"names":[],"mappings":"AAAA,OAAO,oBAAoB,MAAM,4BAA4B,CAAC;AAE9D,MAAM,CAAC,OAAO,OAAO,uBAAwB,YAAW,oBAAoB;;IAGlE,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IA4BtE,YAAY,CAAC,aAAa,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAoBlE,OAAO,CAAC,iBAAiB;IAOzB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAO5C,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAMvD,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU;CAGlD"}
|
|
@@ -3,10 +3,11 @@ export default class WebCryptographyProvider {
|
|
|
3
3
|
async deriveKey(userInputKey, salt) {
|
|
4
4
|
const iterations = 10_000;
|
|
5
5
|
const encoder = new TextEncoder();
|
|
6
|
+
const saltBytes = this.ensureArrayBuffer(salt);
|
|
6
7
|
const keyMaterial = await crypto.subtle.importKey(`raw`, encoder.encode(userInputKey), { name: `PBKDF2` }, false, [`deriveBits`]);
|
|
7
8
|
const derivedBits = await crypto.subtle.deriveBits({
|
|
8
9
|
name: `PBKDF2`,
|
|
9
|
-
salt,
|
|
10
|
+
salt: saltBytes,
|
|
10
11
|
iterations,
|
|
11
12
|
hash: `SHA-256`,
|
|
12
13
|
}, keyMaterial, 256);
|
|
@@ -14,12 +15,18 @@ export default class WebCryptographyProvider {
|
|
|
14
15
|
}
|
|
15
16
|
async generateHmac(encryptionKey) {
|
|
16
17
|
const knownData = `filemail-known-value`;
|
|
17
|
-
const
|
|
18
|
+
const keyBytes = this.ensureArrayBuffer(encryptionKey);
|
|
19
|
+
const key = await crypto.subtle.importKey(`raw`, keyBytes, { name: `HMAC`, hash: `SHA-256` }, false, [`sign`]);
|
|
18
20
|
const encoder = new TextEncoder();
|
|
19
21
|
const data = encoder.encode(knownData);
|
|
20
22
|
const signature = await crypto.subtle.sign(`HMAC`, key, data);
|
|
21
23
|
return new Uint8Array(signature);
|
|
22
24
|
}
|
|
25
|
+
ensureArrayBuffer(value) {
|
|
26
|
+
if (value.buffer instanceof ArrayBuffer)
|
|
27
|
+
return value;
|
|
28
|
+
return new Uint8Array(value);
|
|
29
|
+
}
|
|
23
30
|
generateRandomString(length) {
|
|
24
31
|
const randomValues = crypto.getRandomValues(new Uint32Array(length));
|
|
25
32
|
return Array.from(randomValues)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webCryptographyProvider.js","sourceRoot":"","sources":["../../../../../src/utils/crypto/web/webCryptographyProvider.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,OAAO,uBAAuB;IACxC,6BAA6B,GAAG,sCAAsC,CAAC;IAEvE,KAAK,CAAC,SAAS,CAAC,YAAoB,EAAE,IAAgB;QAClD,MAAM,UAAU,GAAG,MAAM,CAAC;QAE1B,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"webCryptographyProvider.js","sourceRoot":"","sources":["../../../../../src/utils/crypto/web/webCryptographyProvider.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,OAAO,uBAAuB;IACxC,6BAA6B,GAAG,sCAAsC,CAAC;IAEvE,KAAK,CAAC,SAAS,CAAC,YAAoB,EAAE,IAAgB;QAClD,MAAM,UAAU,GAAG,MAAM,CAAC;QAE1B,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAE/C,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAC7C,KAAK,EACL,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,EAC5B,EAAE,IAAI,EAAE,QAAQ,EAAE,EAClB,KAAK,EACL,CAAC,YAAY,CAAC,CACjB,CAAC;QAEF,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,CAC9C;YACI,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,SAAS;YACf,UAAU;YACV,IAAI,EAAE,SAAS;SAClB,EACD,WAAW,EACX,GAAG,CACN,CAAC;QAEF,OAAO,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,aAAyB;QACxC,MAAM,SAAS,GAAG,sBAAsB,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC;QAEvD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CACrC,KAAK,EACL,QAAQ,EACR,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EACjC,KAAK,EACL,CAAC,MAAM,CAAC,CACX,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAEvC,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAE9D,OAAO,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IAEO,iBAAiB,CAAC,KAAiB;QACvC,IAAI,KAAK,CAAC,MAAM,YAAY,WAAW;YACnC,OAAO,KAAgC,CAAC;QAE5C,OAAO,IAAI,UAAU,CAAC,KAAK,CAA4B,CAAC;IAC5D,CAAC;IAED,oBAAoB,CAAC,MAAc;QAC/B,MAAM,YAAY,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QACrE,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC;aAC1B,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,6BAA6B,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,6BAA6B,CAAC,MAAM,CAAC,CAAC;aACtG,IAAI,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,qBAAqB,CAAC,GAAW,EAAE,GAAW;QAC1C,MAAM,YAAY,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;QACrC,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,mBAAmB,CAAC,MAAc;QAC9B,OAAO,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1D,CAAC;CACJ","sourcesContent":["import CryptographyProvider from \"../cryptographyProvider.js\";\r\n\r\nexport default class WebCryptographyProvider implements CryptographyProvider {\r\n #randomStringGeneratorCharSet = `abcdefghijklmnopqrstuvwxyz0123456789`;\r\n\r\n async deriveKey(userInputKey: string, salt: Uint8Array): Promise<Uint8Array> {\r\n const iterations = 10_000;\r\n\r\n const encoder = new TextEncoder();\r\n const saltBytes = this.ensureArrayBuffer(salt);\r\n\r\n const keyMaterial = await crypto.subtle.importKey(\r\n `raw`,\r\n encoder.encode(userInputKey),\r\n { name: `PBKDF2` },\r\n false,\r\n [`deriveBits`],\r\n );\r\n\r\n const derivedBits = await crypto.subtle.deriveBits(\r\n {\r\n name: `PBKDF2`,\r\n salt: saltBytes,\r\n iterations,\r\n hash: `SHA-256`,\r\n },\r\n keyMaterial,\r\n 256,\r\n );\r\n\r\n return new Uint8Array(derivedBits);\r\n }\r\n\r\n async generateHmac(encryptionKey: Uint8Array): Promise<Uint8Array> {\r\n const knownData = `filemail-known-value`;\r\n const keyBytes = this.ensureArrayBuffer(encryptionKey);\r\n\r\n const key = await crypto.subtle.importKey(\r\n `raw`,\r\n keyBytes,\r\n { name: `HMAC`, hash: `SHA-256` },\r\n false,\r\n [`sign`],\r\n );\r\n\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(knownData);\r\n\r\n const signature = await crypto.subtle.sign(`HMAC`, key, data);\r\n\r\n return new Uint8Array(signature);\r\n }\r\n\r\n private ensureArrayBuffer(value: Uint8Array): Uint8Array<ArrayBuffer> {\r\n if (value.buffer instanceof ArrayBuffer)\r\n return value as Uint8Array<ArrayBuffer>;\r\n\r\n return new Uint8Array(value) as Uint8Array<ArrayBuffer>;\r\n }\r\n\r\n generateRandomString(length: number): string {\r\n const randomValues = crypto.getRandomValues(new Uint32Array(length));\r\n return Array.from(randomValues)\r\n .map(val => this.#randomStringGeneratorCharSet.charAt(val % this.#randomStringGeneratorCharSet.length))\r\n .join(``);\r\n }\r\n\r\n generateRandomInteger(min: number, max: number): number {\r\n const randomBuffer = new Uint32Array(1);\r\n crypto.getRandomValues(randomBuffer);\r\n return min + (randomBuffer[0] % (max - min + 1));\r\n }\r\n\r\n generateRandomBytes(length: number): Uint8Array {\r\n return crypto.getRandomValues(new Uint8Array(length));\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeChunkStreamProvider.d.ts","sourceRoot":"","sources":["../../../../../src/utils/fileSystem/node/nodeChunkStreamProvider.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAMvC,OAAO,KAAK,mBAAmB,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,2BAA2B,CAAC;AAEnF,MAAM,CAAC,OAAO,OAAO,uBAAwB,YAAW,mBAAmB;;IACvE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IAapC,IAAI,UAAU,IAAI,OAAO,CAYxB;gBAEW,YAAY,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,cAAc,EAAE,iCAAiC,GAAG,SAAS;IAavJ,OAAO,CAAC,+BAA+B;IAUjC,cAAc,CAAC,MAAM,EAAE,KAAK,GAAG,QAAQ,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAmBpF,kBAAkB,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"nodeChunkStreamProvider.d.ts","sourceRoot":"","sources":["../../../../../src/utils/fileSystem/node/nodeChunkStreamProvider.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAMvC,OAAO,KAAK,mBAAmB,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,2BAA2B,CAAC;AAEnF,MAAM,CAAC,OAAO,OAAO,uBAAwB,YAAW,mBAAmB;;IACvE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IAapC,IAAI,UAAU,IAAI,OAAO,CAYxB;gBAEW,YAAY,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,cAAc,EAAE,iCAAiC,GAAG,SAAS;IAavJ,OAAO,CAAC,+BAA+B;IAUjC,cAAc,CAAC,MAAM,EAAE,KAAK,GAAG,QAAQ,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAmBpF,kBAAkB,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;IAyC5E,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,OAAO,CAAC,mBAAmB;IAOrB,mBAAmB,IAAI,OAAO,CAAC;QAAE,UAAU,EAAE,QAAQ,CAAC;QAAC,cAAc,CAAC,EAAE,QAAQ,CAAA;KAAE,CAAC;IA8BnF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB9B,OAAO,CAAC,WAAW,CAQjB;IAEF,OAAO,CAAC,aAAa,CAQnB;CACL"}
|
|
@@ -2,7 +2,7 @@ import fs from "fs/promises";
|
|
|
2
2
|
import { constants as fsConsts } from "fs";
|
|
3
3
|
import crypto from "crypto";
|
|
4
4
|
import { pipeline, finished } from "stream/promises";
|
|
5
|
-
import { PassThrough } from
|
|
5
|
+
import { PassThrough } from "stream";
|
|
6
6
|
import { ReadableStream } from "stream/web";
|
|
7
7
|
import { createCipher, createDecipher } from 'aes-ctr-concurrent';
|
|
8
8
|
import FsError from '../fsError.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeChunkStreamProvider.js","sourceRoot":"","sources":["../../../../../src/utils/fileSystem/node/nodeChunkStreamProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"fs/promises\";\r\nimport { ReadStream, WriteStream, constants as fsConsts } from \"fs\";\r\nimport crypto, { Cipher, Decipher } from \"crypto\";\r\nimport { pipeline, finished } from \"stream/promises\";\r\nimport { PassThrough } from 'stream';\r\n\r\nimport { ReadableStream } from \"stream/web\";\r\nimport type { Writable } from \"stream\";\r\n\r\nimport { createCipher, createDecipher } from 'aes-ctr-concurrent';\r\n\r\nimport FsError from '../fsError.js';\r\n\r\nimport type ChunkStreamProvider from \"../chunkStreamProvider.js\";\r\nimport type { PauseSignal } from \"../../../uploader/pauseController.js\";\r\nimport type { ChunkStreamProviderEncryptionData } from \"../chunkStreamProvider.js\";\r\n\r\nexport default class NodeChunkStreamProvider implements ChunkStreamProvider {\r\n readonly chunkStartPosition: number;\r\n readonly chunkLengthInBytes: number;\r\n\r\n readonly #encryptionData?: ChunkStreamProviderEncryptionData;\r\n readonly #fullFilePath: string;\r\n\r\n #fileReadHandle: fs.FileHandle | null = null;\r\n #fileReadStream: ReadStream | null = null;\r\n #fileReadCipherStream: Cipher | null = null;\r\n #fileReadPassThroughStream: PassThrough | null = null;\r\n #fileWriteHandle: fs.FileHandle | null = null;\r\n #fileWriteStream: WriteStream | null = null;\r\n #fileWriteDecipherStream: Decipher | null = null;\r\n\r\n get isReleased(): boolean {\r\n const isFileReadHandleReleased = this.#fileReadHandle === null;\r\n const isFileReadStreamReleased = this.#fileReadStream?.destroyed ?? true;\r\n const isFileReadCipherStreamReleased = this.#fileReadCipherStream?.destroyed ?? true;\r\n const isFileReadPassThroughStreamReleased = this.#fileReadPassThroughStream?.destroyed ?? true;\r\n const isFileWriteHandleReleased = this.#fileWriteHandle === null;\r\n const isFileWriteStreamReleased = this.#fileWriteStream?.destroyed ?? true;\r\n const isFileWriteDecipherStreamReleased = this.#fileWriteDecipherStream?.destroyed ?? true;\r\n\r\n return isFileReadHandleReleased && isFileReadStreamReleased && isFileReadCipherStreamReleased\r\n && isFileReadPassThroughStreamReleased && isFileWriteStreamReleased && isFileWriteDecipherStreamReleased\r\n && isFileWriteHandleReleased;\r\n }\r\n\r\n constructor(fullFilePath: string, chunkStartPosition: number, chunkLengthInBytes: number, encryptionData: ChunkStreamProviderEncryptionData | undefined) {\r\n this.throwIfEncryptionDataIsNotValid(encryptionData);\r\n\r\n this.#fullFilePath = fullFilePath;\r\n this.#encryptionData = encryptionData;\r\n this.chunkStartPosition = chunkStartPosition;\r\n\r\n if (chunkLengthInBytes < 0)\r\n throw new FsError(`chunkLengthInBytes can't be a negative value`);\r\n\r\n this.chunkLengthInBytes = chunkLengthInBytes;\r\n }\r\n\r\n private throwIfEncryptionDataIsNotValid(encryptionData: ChunkStreamProviderEncryptionData | undefined) {\r\n if (!encryptionData)\r\n return;\r\n\r\n if (encryptionData.iv.length !== 16)\r\n throw new FsError(`Encryption IV must be 16 bytes long`);\r\n if (encryptionData.key.length !== 32)\r\n throw new FsError(`Encryption key must be 32 bytes long`);\r\n }\r\n\r\n async getMd5Checksum(format: `hex` | `base64`, pauseSignal?: PauseSignal): Promise<string> {\r\n try {\r\n const fileStream = await this.getChunkReadStream(pauseSignal);\r\n\r\n const hash = crypto.createHash(`md5`);\r\n\r\n await pipeline(fileStream, hash);\r\n\r\n return hash.digest(format);\r\n }\r\n catch (error) {\r\n throw new FsError(`ComputingFileMd5ChecksumException`, { cause: error as Error });\r\n }\r\n finally {\r\n if (!this.isReleased)\r\n await this.release();\r\n }\r\n }\r\n\r\n async getChunkReadStream(pauseSignal?: PauseSignal): Promise<ReadableStream> {\r\n try {\r\n if (!this.isReleased)\r\n await this.release();\r\n\r\n this.#fileReadHandle = await fs.open(this.#fullFilePath, fsConsts.O_RDONLY);\r\n\r\n this.#fileReadStream = this.#fileReadHandle.createReadStream({\r\n start: this.chunkStartPosition,\r\n end: this.getChunkEndPosition(),\r\n });\r\n\r\n this.#fileReadPassThroughStream = new PassThrough();\r\n\r\n if (this.#encryptionData) {\r\n this.#fileReadCipherStream = createCipher(Buffer.from(this.#encryptionData.key), Buffer.from(this.#encryptionData.iv), this.chunkStartPosition);\r\n this.#fileReadStream.pipe(this.#fileReadCipherStream).pipe(this.#fileReadPassThroughStream);\r\n }\r\n else\r\n this.#fileReadStream.pipe(this.#fileReadPassThroughStream);\r\n\r\n pauseSignal?.addEventListener(`pause`, () => {\r\n this.#fileReadStream?.destroy();\r\n this.#fileReadCipherStream?.destroy();\r\n this.#fileReadPassThroughStream?.end();\r\n });\r\n\r\n return ReadableStream.from(this.#fileReadPassThroughStream);\r\n }\r\n catch (error) {\r\n if (!this.isReleased)\r\n await this.release();\r\n\r\n throw new FsError(`CreatingFileReadStreamException`, { cause: error as Error });\r\n }\r\n }\r\n\r\n getChunkBlob(): Promise<Blob> {\r\n throw new Error(`Not implemented for NodeJS`);\r\n }\r\n\r\n private getChunkEndPosition() {\r\n if (this.chunkLengthInBytes === 0)\r\n return this.chunkStartPosition;\r\n\r\n return this.chunkStartPosition + this.chunkLengthInBytes - 1;\r\n }\r\n\r\n async getChunkWriteStream(): Promise<{ fileStream: Writable, decipherStream?: Writable }> {\r\n try {\r\n if (!this.isReleased)\r\n await this.release();\r\n\r\n this.#fileWriteHandle = await fs.open(this.#fullFilePath, fsConsts.O_WRONLY);\r\n\r\n this.#fileWriteStream = this.#fileWriteHandle.createWriteStream({\r\n start: this.chunkStartPosition,\r\n });\r\n\r\n if (!this.#encryptionData)\r\n return { fileStream: this.#fileWriteStream };\r\n\r\n this.#fileWriteDecipherStream = createDecipher(Buffer.from(this.#encryptionData.key), Buffer.from(this.#encryptionData.iv), this.chunkStartPosition);\r\n\r\n return { fileStream: this.#fileWriteStream, decipherStream: this.#fileWriteDecipherStream };\r\n }\r\n catch (error) {\r\n if (!this.isReleased)\r\n await this.release();\r\n\r\n throw new FsError(`CreatingFileWriteStreamException`, { cause: error as Error });\r\n }\r\n }\r\n\r\n async release(): Promise<void> {\r\n await Promise.allSettled([\r\n this.closeHandle(this.#fileReadHandle),\r\n this.destroyStream(this.#fileReadStream),\r\n this.destroyStream(this.#fileReadCipherStream),\r\n this.destroyStream(this.#fileReadPassThroughStream),\r\n this.closeHandle(this.#fileWriteHandle),\r\n this.destroyStream(this.#fileWriteStream),\r\n this.destroyStream(this.#fileWriteDecipherStream),\r\n ]);\r\n\r\n this.#fileReadHandle = null;\r\n this.#fileReadStream = null;\r\n this.#fileReadCipherStream = null;\r\n this.#fileReadPassThroughStream = null;\r\n this.#fileWriteHandle = null;\r\n this.#fileWriteStream = null;\r\n this.#fileWriteDecipherStream = null;\r\n }\r\n\r\n private closeHandle = async (handle: fs.FileHandle | null): Promise<void> => {\r\n if (!handle)\r\n return;\r\n\r\n try {\r\n await handle.close();\r\n }\r\n catch { /* ignore errors during handle closing */ }\r\n };\r\n\r\n private destroyStream = async (stream: ReadStream | Writable | Cipher | Decipher | PassThrough | null): Promise<void> => {\r\n if (!stream || stream.destroyed)\r\n return;\r\n\r\n stream.once(`error`, () => { /* absorb premature close errors */ });\r\n const finishPromise = finished(stream).catch(() => { /* safely ignore */ });\r\n stream.destroy();\r\n await finishPromise;\r\n };\r\n}"]}
|
|
1
|
+
{"version":3,"file":"nodeChunkStreamProvider.js","sourceRoot":"","sources":["../../../../../src/utils/fileSystem/node/nodeChunkStreamProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"fs/promises\";\r\nimport { ReadStream, WriteStream, constants as fsConsts } from \"fs\";\r\nimport crypto from \"crypto\";\r\nimport { pipeline, finished } from \"stream/promises\";\r\nimport { PassThrough, Transform } from \"stream\";\r\n\r\nimport { ReadableStream } from \"stream/web\";\r\nimport type { Writable } from \"stream\";\r\n\r\nimport { createCipher, createDecipher } from 'aes-ctr-concurrent';\r\n\r\nimport FsError from '../fsError.js';\r\n\r\nimport type ChunkStreamProvider from \"../chunkStreamProvider.js\";\r\nimport type { PauseSignal } from \"../../../uploader/pauseController.js\";\r\nimport type { ChunkStreamProviderEncryptionData } from \"../chunkStreamProvider.js\";\r\n\r\nexport default class NodeChunkStreamProvider implements ChunkStreamProvider {\r\n readonly chunkStartPosition: number;\r\n readonly chunkLengthInBytes: number;\r\n\r\n readonly #encryptionData?: ChunkStreamProviderEncryptionData;\r\n readonly #fullFilePath: string;\r\n\r\n #fileReadHandle: fs.FileHandle | null = null;\r\n #fileReadStream: ReadStream | null = null;\r\n #fileReadCipherStream: Transform | null = null;\r\n #fileReadPassThroughStream: PassThrough | null = null;\r\n #fileWriteHandle: fs.FileHandle | null = null;\r\n #fileWriteStream: WriteStream | null = null;\r\n #fileWriteDecipherStream: Transform | null = null;\r\n\r\n get isReleased(): boolean {\r\n const isFileReadHandleReleased = this.#fileReadHandle === null;\r\n const isFileReadStreamReleased = this.#fileReadStream?.destroyed ?? true;\r\n const isFileReadCipherStreamReleased = this.#fileReadCipherStream?.destroyed ?? true;\r\n const isFileReadPassThroughStreamReleased = this.#fileReadPassThroughStream?.destroyed ?? true;\r\n const isFileWriteHandleReleased = this.#fileWriteHandle === null;\r\n const isFileWriteStreamReleased = this.#fileWriteStream?.destroyed ?? true;\r\n const isFileWriteDecipherStreamReleased = this.#fileWriteDecipherStream?.destroyed ?? true;\r\n\r\n return isFileReadHandleReleased && isFileReadStreamReleased && isFileReadCipherStreamReleased\r\n && isFileReadPassThroughStreamReleased && isFileWriteStreamReleased && isFileWriteDecipherStreamReleased\r\n && isFileWriteHandleReleased;\r\n }\r\n\r\n constructor(fullFilePath: string, chunkStartPosition: number, chunkLengthInBytes: number, encryptionData: ChunkStreamProviderEncryptionData | undefined) {\r\n this.throwIfEncryptionDataIsNotValid(encryptionData);\r\n\r\n this.#fullFilePath = fullFilePath;\r\n this.#encryptionData = encryptionData;\r\n this.chunkStartPosition = chunkStartPosition;\r\n\r\n if (chunkLengthInBytes < 0)\r\n throw new FsError(`chunkLengthInBytes can't be a negative value`);\r\n\r\n this.chunkLengthInBytes = chunkLengthInBytes;\r\n }\r\n\r\n private throwIfEncryptionDataIsNotValid(encryptionData: ChunkStreamProviderEncryptionData | undefined) {\r\n if (!encryptionData)\r\n return;\r\n\r\n if (encryptionData.iv.length !== 16)\r\n throw new FsError(`Encryption IV must be 16 bytes long`);\r\n if (encryptionData.key.length !== 32)\r\n throw new FsError(`Encryption key must be 32 bytes long`);\r\n }\r\n\r\n async getMd5Checksum(format: `hex` | `base64`, pauseSignal?: PauseSignal): Promise<string> {\r\n try {\r\n const fileStream = await this.getChunkReadStream(pauseSignal);\r\n\r\n const hash = crypto.createHash(`md5`);\r\n\r\n await pipeline(fileStream, hash);\r\n\r\n return hash.digest(format);\r\n }\r\n catch (error) {\r\n throw new FsError(`ComputingFileMd5ChecksumException`, { cause: error as Error });\r\n }\r\n finally {\r\n if (!this.isReleased)\r\n await this.release();\r\n }\r\n }\r\n\r\n async getChunkReadStream(pauseSignal?: PauseSignal): Promise<ReadableStream> {\r\n try {\r\n if (!this.isReleased)\r\n await this.release();\r\n\r\n this.#fileReadHandle = await fs.open(this.#fullFilePath, fsConsts.O_RDONLY);\r\n\r\n this.#fileReadStream = this.#fileReadHandle.createReadStream({\r\n start: this.chunkStartPosition,\r\n end: this.getChunkEndPosition(),\r\n });\r\n\r\n this.#fileReadPassThroughStream = new PassThrough();\r\n\r\n if (this.#encryptionData) {\r\n this.#fileReadCipherStream = createCipher(\r\n Buffer.from(this.#encryptionData.key),\r\n Buffer.from(this.#encryptionData.iv),\r\n this.chunkStartPosition,\r\n ) as Transform;\r\n this.#fileReadStream.pipe(this.#fileReadCipherStream).pipe(this.#fileReadPassThroughStream);\r\n }\r\n else\r\n this.#fileReadStream.pipe(this.#fileReadPassThroughStream);\r\n\r\n pauseSignal?.addEventListener(`pause`, () => {\r\n this.#fileReadStream?.destroy();\r\n this.#fileReadCipherStream?.destroy();\r\n this.#fileReadPassThroughStream?.end();\r\n });\r\n\r\n return ReadableStream.from(this.#fileReadPassThroughStream);\r\n }\r\n catch (error) {\r\n if (!this.isReleased)\r\n await this.release();\r\n\r\n throw new FsError(`CreatingFileReadStreamException`, { cause: error as Error });\r\n }\r\n }\r\n\r\n getChunkBlob(): Promise<Blob> {\r\n throw new Error(`Not implemented for NodeJS`);\r\n }\r\n\r\n private getChunkEndPosition() {\r\n if (this.chunkLengthInBytes === 0)\r\n return this.chunkStartPosition;\r\n\r\n return this.chunkStartPosition + this.chunkLengthInBytes - 1;\r\n }\r\n\r\n async getChunkWriteStream(): Promise<{ fileStream: Writable, decipherStream?: Writable }> {\r\n try {\r\n if (!this.isReleased)\r\n await this.release();\r\n\r\n this.#fileWriteHandle = await fs.open(this.#fullFilePath, fsConsts.O_WRONLY);\r\n\r\n this.#fileWriteStream = this.#fileWriteHandle.createWriteStream({\r\n start: this.chunkStartPosition,\r\n });\r\n\r\n if (!this.#encryptionData)\r\n return { fileStream: this.#fileWriteStream };\r\n\r\n this.#fileWriteDecipherStream = createDecipher(\r\n Buffer.from(this.#encryptionData.key),\r\n Buffer.from(this.#encryptionData.iv),\r\n this.chunkStartPosition,\r\n ) as Transform;\r\n\r\n return { fileStream: this.#fileWriteStream, decipherStream: this.#fileWriteDecipherStream };\r\n }\r\n catch (error) {\r\n if (!this.isReleased)\r\n await this.release();\r\n\r\n throw new FsError(`CreatingFileWriteStreamException`, { cause: error as Error });\r\n }\r\n }\r\n\r\n async release(): Promise<void> {\r\n await Promise.allSettled([\r\n this.closeHandle(this.#fileReadHandle),\r\n this.destroyStream(this.#fileReadStream),\r\n this.destroyStream(this.#fileReadCipherStream),\r\n this.destroyStream(this.#fileReadPassThroughStream),\r\n this.closeHandle(this.#fileWriteHandle),\r\n this.destroyStream(this.#fileWriteStream),\r\n this.destroyStream(this.#fileWriteDecipherStream),\r\n ]);\r\n\r\n this.#fileReadHandle = null;\r\n this.#fileReadStream = null;\r\n this.#fileReadCipherStream = null;\r\n this.#fileReadPassThroughStream = null;\r\n this.#fileWriteHandle = null;\r\n this.#fileWriteStream = null;\r\n this.#fileWriteDecipherStream = null;\r\n }\r\n\r\n private closeHandle = async (handle: fs.FileHandle | null): Promise<void> => {\r\n if (!handle)\r\n return;\r\n\r\n try {\r\n await handle.close();\r\n }\r\n catch { /* ignore errors during handle closing */ }\r\n };\r\n\r\n private destroyStream = async (stream: ReadStream | Writable | Transform | PassThrough | null): Promise<void> => {\r\n if (!stream || stream.destroyed)\r\n return;\r\n\r\n stream.once(`error`, () => { /* absorb premature close errors */ });\r\n const finishPromise = finished(stream).catch(() => { /* safely ignore */ });\r\n stream.destroy();\r\n await finishPromise;\r\n };\r\n}\r\n"]}
|
|
@@ -5,6 +5,7 @@ export default class WebChunkStreamEncrypter {
|
|
|
5
5
|
chunkBlob: Blob;
|
|
6
6
|
constructor(chunkStartPosition: number, iv: Uint8Array, key: Uint8Array, chunkBlob: Blob);
|
|
7
7
|
encryptBlob(): Promise<Blob>;
|
|
8
|
+
private ensureArrayBuffer;
|
|
8
9
|
private incrementIvByFullBlocks;
|
|
9
10
|
private ivToBigInt;
|
|
10
11
|
private bigIntToIV;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webChunkStreamEncrypter.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/fileSystem/web/chunkStreamProvider/webChunkStreamEncrypter.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,OAAO,OAAO,uBAAuB;IACxC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,EAAE,EAAE,UAAU,CAAC;IACf,GAAG,EAAE,UAAU,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;gBAEJ,kBAAkB,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI;IAgBlF,WAAW;
|
|
1
|
+
{"version":3,"file":"webChunkStreamEncrypter.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/fileSystem/web/chunkStreamProvider/webChunkStreamEncrypter.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,OAAO,OAAO,uBAAuB;IACxC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,EAAE,EAAE,UAAU,CAAC;IACf,GAAG,EAAE,UAAU,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;gBAEJ,kBAAkB,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI;IAgBlF,WAAW;IA+BjB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,uBAAuB;IAW/B,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,UAAU;CAWrB"}
|
|
@@ -25,18 +25,25 @@ export default class WebChunkStreamEncrypter {
|
|
|
25
25
|
const chunkBytesArray = new Uint8Array(chunkBuffer);
|
|
26
26
|
const fullAesBlocksIncrement = BigInt(this.chunkStartPosition) / AES_BLOCK_SIZE_IN_BYTES;
|
|
27
27
|
const incrementedIv = this.incrementIvByFullBlocks(this.iv, fullAesBlocksIncrement);
|
|
28
|
+
const keyBytes = this.ensureArrayBuffer(this.key);
|
|
29
|
+
const counterBytes = this.ensureArrayBuffer(incrementedIv);
|
|
28
30
|
// AES works on blocks but it might happen that our chunk starts within an encryption block
|
|
29
31
|
// so we need to append some zeros at the beginning of the block and do the encryption
|
|
30
32
|
// and then discard these leading extra bytes
|
|
31
33
|
const aesBlockOffset = this.chunkStartPosition % Number(AES_BLOCK_SIZE_IN_BYTES);
|
|
32
34
|
const chunkDataPrefixedWithZeros = new Uint8Array(aesBlockOffset + chunkBytesArray.length);
|
|
33
35
|
chunkDataPrefixedWithZeros.set(chunkBytesArray, aesBlockOffset);
|
|
34
|
-
const cryptoKey = await crypto.subtle.importKey(`raw`,
|
|
35
|
-
const encryptedDataBuffer = await crypto.subtle.encrypt({ name: `AES-CTR`, counter:
|
|
36
|
+
const cryptoKey = await crypto.subtle.importKey(`raw`, keyBytes, { name: `AES-CTR` }, false, [`encrypt`]);
|
|
37
|
+
const encryptedDataBuffer = await crypto.subtle.encrypt({ name: `AES-CTR`, counter: counterBytes, length: 128 }, cryptoKey, chunkDataPrefixedWithZeros.buffer);
|
|
36
38
|
// Remove the leading extra bytes
|
|
37
39
|
const encryptedChunk = encryptedDataBuffer.slice(aesBlockOffset);
|
|
38
40
|
return new Blob([encryptedChunk]);
|
|
39
41
|
}
|
|
42
|
+
ensureArrayBuffer(value) {
|
|
43
|
+
if (value.buffer instanceof ArrayBuffer)
|
|
44
|
+
return value;
|
|
45
|
+
return new Uint8Array(value);
|
|
46
|
+
}
|
|
40
47
|
incrementIvByFullBlocks(originalIv, fullBlocksToIncrement) {
|
|
41
48
|
let ivBigInt = this.ivToBigInt(originalIv);
|
|
42
49
|
ivBigInt += fullBlocksToIncrement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webChunkStreamEncrypter.js","sourceRoot":"","sources":["../../../../../../src/utils/fileSystem/web/chunkStreamProvider/webChunkStreamEncrypter.ts"],"names":[],"mappings":"AAAA,MAAM,uBAAuB,GAAG,GAAG,CAAC;AACpC,MAAM,MAAM,GAAG,mCAAmC,CAAC;AACnD,MAAM,kBAAkB,GAAG,MAAM,GAAG,EAAE,CAAC;AAEvC,MAAM,CAAC,OAAO,OAAO,uBAAuB;IACxC,kBAAkB,CAAS;IAC3B,EAAE,CAAa;IACf,GAAG,CAAa;IAChB,SAAS,CAAO;IAEhB,YAAY,kBAA0B,EAAE,EAAc,EAAE,GAAe,EAAE,SAAe;QACpF,IAAI,kBAAkB,GAAG,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC9D,IAAI,EAAE,CAAC,MAAM,KAAK,EAAE;YAChB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAChD,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE;YACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QACjD,IAAI,CAAC,SAAS;YACV,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAEpD,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;QAC7C,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,WAAW;QACb,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;QACvD,MAAM,eAAe,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;QAEpD,MAAM,sBAAsB,GAAG,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,uBAAuB,CAAC;QACzF,MAAM,aAAa,GAAG,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,EAAE,EAAE,sBAAsB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"webChunkStreamEncrypter.js","sourceRoot":"","sources":["../../../../../../src/utils/fileSystem/web/chunkStreamProvider/webChunkStreamEncrypter.ts"],"names":[],"mappings":"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","sourcesContent":["const AES_BLOCK_SIZE_IN_BYTES = 16n;\r\nconst IV_MAX = 0xffffffffffffffffffffffffffffffffn;\r\nconst IV_OVERFLOW_MODULO = IV_MAX + 1n;\r\n\r\nexport default class WebChunkStreamEncrypter {\r\n chunkStartPosition: number;\r\n iv: Uint8Array;\r\n key: Uint8Array;\r\n chunkBlob: Blob;\r\n\r\n constructor(chunkStartPosition: number, iv: Uint8Array, key: Uint8Array, chunkBlob: Blob) {\r\n if (chunkStartPosition < 0)\r\n throw new Error(`Chunk start position can't be negative`);\r\n if (iv.length !== 16)\r\n throw new Error(`IV must be 16 bytes long`);\r\n if (key.length !== 32)\r\n throw new Error(`Key must be 32 bytes long`);\r\n if (!chunkBlob)\r\n throw new Error(`Chunk blob has to be defined`);\r\n\r\n this.chunkStartPosition = chunkStartPosition;\r\n this.iv = iv;\r\n this.key = key;\r\n this.chunkBlob = chunkBlob;\r\n }\r\n\r\n async encryptBlob() {\r\n const chunkBuffer = await this.chunkBlob.arrayBuffer();\r\n const chunkBytesArray = new Uint8Array(chunkBuffer);\r\n\r\n const fullAesBlocksIncrement = BigInt(this.chunkStartPosition) / AES_BLOCK_SIZE_IN_BYTES;\r\n const incrementedIv = this.incrementIvByFullBlocks(this.iv, fullAesBlocksIncrement);\r\n const keyBytes = this.ensureArrayBuffer(this.key);\r\n const counterBytes = this.ensureArrayBuffer(incrementedIv);\r\n\r\n // AES works on blocks but it might happen that our chunk starts within an encryption block\r\n // so we need to append some zeros at the beginning of the block and do the encryption\r\n // and then discard these leading extra bytes\r\n const aesBlockOffset = this.chunkStartPosition % Number(AES_BLOCK_SIZE_IN_BYTES);\r\n\r\n const chunkDataPrefixedWithZeros = new Uint8Array(aesBlockOffset + chunkBytesArray.length);\r\n chunkDataPrefixedWithZeros.set(chunkBytesArray, aesBlockOffset);\r\n\r\n const cryptoKey = await crypto.subtle.importKey(`raw`, keyBytes, { name: `AES-CTR` }, false, [`encrypt`]);\r\n\r\n const encryptedDataBuffer = await crypto.subtle.encrypt(\r\n { name: `AES-CTR`, counter: counterBytes, length: 128 },\r\n cryptoKey,\r\n chunkDataPrefixedWithZeros.buffer,\r\n );\r\n\r\n // Remove the leading extra bytes\r\n const encryptedChunk = encryptedDataBuffer.slice(aesBlockOffset);\r\n\r\n return new Blob([encryptedChunk]);\r\n }\r\n\r\n private ensureArrayBuffer(value: Uint8Array): Uint8Array<ArrayBuffer> {\r\n if (value.buffer instanceof ArrayBuffer)\r\n return value as Uint8Array<ArrayBuffer>;\r\n\r\n return new Uint8Array(value) as Uint8Array<ArrayBuffer>;\r\n }\r\n\r\n private incrementIvByFullBlocks(originalIv: Uint8Array, fullBlocksToIncrement: bigint): Uint8Array {\r\n let ivBigInt = this.ivToBigInt(originalIv);\r\n\r\n ivBigInt += fullBlocksToIncrement;\r\n\r\n if (ivBigInt > IV_MAX)\r\n ivBigInt %= IV_OVERFLOW_MODULO;\r\n\r\n return this.bigIntToIV(ivBigInt);\r\n }\r\n\r\n private ivToBigInt(iv: Uint8Array): bigint {\r\n let hex = ``;\r\n\r\n for (const byte of iv)\r\n hex += byte.toString(16).padStart(2, `0`);\r\n\r\n return BigInt(`0x${hex}`);\r\n }\r\n\r\n private bigIntToIV(num: bigint): Uint8Array {\r\n const ivLength = 16;\r\n\r\n const hex = num.toString(16).padStart(ivLength * 2, `0`);\r\n const iv = new Uint8Array(ivLength);\r\n\r\n for (let i = 0; i < ivLength; i++)\r\n iv[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\r\n\r\n return iv;\r\n }\r\n}"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "filemail-sdk",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.3.1",
|
|
4
4
|
"description": "Library for transferring files to and from Filemail.com",
|
|
5
5
|
"author": "Filemail AS",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
@@ -37,22 +37,22 @@
|
|
|
37
37
|
"@tsconfig/node20": "^20.1.4",
|
|
38
38
|
"@types/lodash.throttle": "^4.1.7",
|
|
39
39
|
"@types/mock-fs": "^4.13.1",
|
|
40
|
-
"@types/sinon": "^
|
|
40
|
+
"@types/sinon": "^21.0.0",
|
|
41
41
|
"@types/spark-md5": "^3.0.5",
|
|
42
|
-
"@types/uuid": "^
|
|
42
|
+
"@types/uuid": "^11.0.0",
|
|
43
43
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
44
44
|
"@typescript-eslint/parser": "^8.0.0",
|
|
45
45
|
"ava": "^6.0.0",
|
|
46
46
|
"console-gui-tools": "^3.0.2",
|
|
47
|
-
"del-cli": "
|
|
47
|
+
"del-cli": "^7.0.0",
|
|
48
48
|
"eslint": "^9.0.0",
|
|
49
49
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
50
50
|
"eslint-plugin-import": "^2.26.0",
|
|
51
51
|
"fetch-mock": "^12.5.4",
|
|
52
|
-
"globals": "^
|
|
53
|
-
"mock-fs": "5.
|
|
54
|
-
"nock": "^
|
|
55
|
-
"sinon": "^
|
|
52
|
+
"globals": "^16.5.0",
|
|
53
|
+
"mock-fs": "^5.5.0",
|
|
54
|
+
"nock": "^14.0.10",
|
|
55
|
+
"sinon": "^21.0.1",
|
|
56
56
|
"typescript": "^5.0.4"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"promisified-udp-client": "^1.0.0",
|
|
67
67
|
"spark-md5": "^3.0.2",
|
|
68
68
|
"tap-tc": "^4.4.4",
|
|
69
|
-
"uuid": "^
|
|
69
|
+
"uuid": "^13.0.0"
|
|
70
70
|
},
|
|
71
71
|
"ava": {
|
|
72
72
|
"files": [
|