Skip to content

Commit 512d6c0

Browse files
committed
refactor: update progress callback handling in download and upload services
1 parent cf660c7 commit 512d6c0

File tree

8 files changed

+37
-22
lines changed

8 files changed

+37
-22
lines changed

src/services/network/download.service.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import axios from 'axios';
2+
import { DownloadProgressCallback } from '../../types/network.types';
23

34
export class DownloadService {
45
static readonly instance = new DownloadService();
56

67
async downloadFile(
78
url: string,
8-
size: number,
99
options: {
10-
progressCallback?: (progress: number) => void;
10+
progressCallback?: DownloadProgressCallback;
1111
abortController?: AbortController;
1212
rangeHeader?: string;
1313
},
@@ -16,8 +16,7 @@ export class DownloadService {
1616
responseType: 'stream',
1717
onDownloadProgress(progressEvent) {
1818
if (options.progressCallback && progressEvent.loaded) {
19-
const reportedProgress = Math.round((progressEvent.loaded / size) * 100);
20-
options.progressCallback(reportedProgress);
19+
options.progressCallback(progressEvent.loaded);
2120
}
2221
},
2322
headers: {

src/services/network/network-facade.service.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
import { Environment } from '@internxt/inxt-js';
1111
import { randomBytes } from 'node:crypto';
1212
import { Readable, Transform } from 'node:stream';
13-
import { DownloadOptions, UploadOptions, UploadProgressCallback } from '../../types/network.types';
13+
import { DownloadOptions, UploadOptions, UploadProgressCallback, DownloadProgressCallback } from '../../types/network.types';
1414
import { CryptoService } from '../crypto.service';
1515
import { UploadService } from './upload.service';
1616
import { DownloadService } from './download.service';
@@ -62,9 +62,10 @@ export class NetworkFacade {
6262
let fileStream: ReadableStream<Uint8Array>;
6363
const abortable = options?.abortController ?? new AbortController();
6464

65-
const onProgress: UploadProgressCallback = (progress: number) => {
65+
const onProgress: DownloadProgressCallback = (loadedBytes: number) => {
6666
if (!options?.progressCallback) return;
67-
options.progressCallback(progress);
67+
const reportedProgress = Math.round((loadedBytes / size) * 100);
68+
options.progressCallback(reportedProgress);
6869
};
6970

7071
const decryptFile: DecryptFileFunction = async (_, key, iv) => {
@@ -92,7 +93,7 @@ export class NetworkFacade {
9293
throw new Error('Download aborted');
9394
}
9495

95-
const encryptedContentStream = await this.downloadService.downloadFile(downloadable.url, size, {
96+
const encryptedContentStream = await this.downloadService.downloadFile(downloadable.url, {
9697
progressCallback: onProgress,
9798
abortController: options?.abortController,
9899
rangeHeader: rangeOptions?.range,
@@ -140,9 +141,10 @@ export class NetworkFacade {
140141
let encryptionTransform: Transform;
141142
let hash: Buffer;
142143

143-
const onProgress: UploadProgressCallback = (progress: number) => {
144+
const onProgress: UploadProgressCallback = (loadedBytes: number) => {
144145
if (!options?.progressCallback) return;
145-
options.progressCallback(progress);
146+
const reportedProgress = Math.round((loadedBytes / size) * 100);
147+
options.progressCallback(reportedProgress);
146148
};
147149

148150
const encryptFile: EncryptFileFunction = async (_, key, iv) => {
@@ -157,7 +159,7 @@ export class NetworkFacade {
157159
};
158160

159161
const uploadFile: UploadFileFunction = async (url) => {
160-
await this.uploadService.uploadFile(url, size, encryptionTransform, {
162+
await this.uploadService.uploadFile(url, encryptionTransform, {
161163
abortController: abortable,
162164
progressCallback: onProgress,
163165
});

src/services/network/upload.service.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ import { UploadOptions } from '../../types/network.types';
55
export class UploadService {
66
public static readonly instance: UploadService = new UploadService();
77

8-
async uploadFile(url: string, size: number, from: Readable, options: UploadOptions): Promise<{ etag: string }> {
8+
async uploadFile(url: string, from: Readable, options: UploadOptions): Promise<{ etag: string }> {
99
const response = await axios.put(url, from, {
1010
signal: options.abortController?.signal,
1111
onUploadProgress: (progressEvent) => {
1212
if (options.progressCallback && progressEvent.loaded) {
13-
const reportedProgress = Math.round((progressEvent.loaded / size) * 100);
14-
options.progressCallback(reportedProgress);
13+
options.progressCallback(progressEvent.loaded);
1514
}
1615
},
1716
});

src/types/network.types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ export interface NetworkCredentials {
33
pass: string;
44
}
55

6-
export type UploadProgressCallback = (progress: number) => void;
6+
export type DownloadProgressCallback = (downloadedBytes: number) => void;
7+
export type UploadProgressCallback = (uploadedBytes: number) => void;
78
export interface NetworkOperationBaseOptions {
89
progressCallback: UploadProgressCallback;
910
abortController?: AbortController;

test/services/network/download.service.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,6 @@ describe('Download Service', () => {
4848

4949
await sut.downloadFile('https://example.com/file', options);
5050

51-
expect(options.progressCallback).toHaveBeenCalledWith(1);
51+
expect(options.progressCallback).toHaveBeenCalledWith(100);
5252
});
5353
});

test/services/network/network-facade.service.test.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ describe('Network Facade Service', () => {
120120
// eslint-disable-next-line max-len
121121
'index course habit soon assist dragon tragic helmet salute stuff later twice consider grit pulse cement obvious trick sponsor stereo hello win royal more',
122122
'f1858bc9675f9e4f7ab29429',
123+
encryptedContent.length,
123124
writable,
124125
);
125126

@@ -166,6 +167,7 @@ describe('Network Facade Service', () => {
166167
// eslint-disable-next-line max-len
167168
'index course habit soon assist dragon tragic helmet salute stuff later twice consider grit pulse cement obvious trick sponsor stereo hello win royal more',
168169
'f1858bc9675f9e4f7ab29429',
170+
encryptedContent.length,
169171
writable,
170172
);
171173

@@ -214,7 +216,12 @@ describe('Network Facade Service', () => {
214216
const options = { progressCallback: vi.fn() };
215217

216218
vi.spyOn(axios, 'get').mockImplementation((_, config) => {
217-
config?.onDownloadProgress?.({ loaded: 100, total: 100, bytes: 100, lengthComputable: true });
219+
config?.onDownloadProgress?.({
220+
loaded: encryptedContent.length,
221+
total: encryptedContent.length,
222+
bytes: encryptedContent.length,
223+
lengthComputable: true
224+
});
218225
return Promise.resolve({ data: readableContent });
219226
});
220227

@@ -223,13 +230,14 @@ describe('Network Facade Service', () => {
223230
// eslint-disable-next-line max-len
224231
'index course habit soon assist dragon tragic helmet salute stuff later twice consider grit pulse cement obvious trick sponsor stereo hello win royal more',
225232
'f1858bc9675f9e4f7ab29429',
233+
encryptedContent.length,
226234
writable,
227235
undefined,
228236
options,
229237
);
230238

231239
await executeDownload;
232240

233-
expect(options.progressCallback).toHaveBeenCalledWith(1);
241+
expect(options.progressCallback).toHaveBeenCalledWith(100);
234242
});
235243
});

test/services/network/upload.service.test.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
22
import { UploadService } from '../../../src/services/network/upload.service';
33
import nock from 'nock';
44
import { Readable } from 'node:stream';
5+
import crypto from 'node:crypto';
56

67
describe('Upload Service', () => {
78
const sut = UploadService.instance;
@@ -12,9 +13,10 @@ describe('Upload Service', () => {
1213

1314
it('When a file is uploaded and etag is missing, should throw an error', async () => {
1415
const url = 'https://example.com/upload';
16+
const file = crypto.randomBytes(16).toString('hex');
1517
const data = new Readable({
1618
read() {
17-
this.push('test content');
19+
this.push(file);
1820
this.push(null);
1921
},
2022
});
@@ -34,9 +36,10 @@ describe('Upload Service', () => {
3436

3537
it('When a file is uploaded and etag is returned, the etag should be returned', async () => {
3638
const url = 'https://example.com/upload';
39+
const file = crypto.randomBytes(16).toString('hex');
3740
const data = new Readable({
3841
read() {
39-
this.push('test content');
42+
this.push(file);
4043
this.push(null);
4144
},
4245
});
@@ -55,9 +58,10 @@ describe('Upload Service', () => {
5558

5659
it('When a file is uploaded, should update the progress', async () => {
5760
const url = 'https://example.com/upload';
61+
const file = crypto.randomBytes(16).toString('hex');
5862
const data = new Readable({
5963
read() {
60-
this.push('test content');
64+
this.push(file);
6165
this.push(null);
6266
},
6367
});
@@ -71,7 +75,7 @@ describe('Upload Service', () => {
7175
});
7276

7377
await sut.uploadFile(url, data, options);
74-
expect(options.progressCallback).toHaveBeenCalledWith(1);
78+
expect(options.progressCallback).toHaveBeenCalledWith(file.length);
7579
});
7680

7781
it('When a file is uploaded and the upload is aborted, should cancel the request', async () => {

test/webdav/handlers/GET.handler.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ describe('GET request handler', () => {
134134
mockFile.bucket,
135135
mockAuthDetails.user.mnemonic,
136136
mockFile.fileId,
137+
mockFile.size,
137138
expect.any(Object),
138139
undefined,
139140
);
@@ -205,6 +206,7 @@ describe('GET request handler', () => {
205206
mockFile.bucket,
206207
mockAuthDetails.user.mnemonic,
207208
mockFile.fileId,
209+
mockSize - rangeStart,
208210
expect.any(Object),
209211
expectedRangeOptions,
210212
);

0 commit comments

Comments
 (0)