1import { FetchLike } from './client.types';
2import * as Log from '../../log';
3const debug = require('debug')('expo:api:fetch:progress') as typeof console.log;
4
5export function wrapFetchWithProgress(fetch: FetchLike): FetchLike {
6  return (url, init) => {
7    return fetch(url, init).then((res) => {
8      if (res.ok && init?.onProgress) {
9        const totalDownloadSize = res.headers.get('Content-Length');
10        const total = Number(totalDownloadSize);
11
12        debug(`Download size: ${totalDownloadSize}`);
13        if (!totalDownloadSize || isNaN(total) || total < 0) {
14          Log.warn(
15            'Progress callback not supported for network request because "Content-Length" header missing or invalid in response from URL:',
16            url.toString()
17          );
18          return res;
19        }
20
21        let length = 0;
22
23        debug(`Starting progress animation for ${url}`);
24        res.body.on('data', (chunk) => {
25          length += Buffer.byteLength(chunk);
26          onProgress();
27        });
28
29        res.body.on('end', () => {
30          debug(`Finished progress animation for ${url}`);
31          onProgress();
32        });
33
34        const onProgress = () => {
35          const progress = length / total || 0;
36          init.onProgress?.({
37            progress,
38            total,
39            loaded: length,
40          });
41        };
42      }
43      return res;
44    });
45  };
46}
47