UNPKG

@datocms/cma-client-node

Version:
83 lines 3.62 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { createWriteStream, promises } from 'node:fs'; import { basename, join } from 'node:path'; import { URL } from 'node:url'; import { CanceledPromiseError, getFetchFn, makeCancelablePromise, } from '@datocms/rest-client-utils'; import { dir } from 'tmp-promise'; export function downloadFile(url, { onProgress, fetchFn: customFetchFn } = {}) { const fetchFn = getFetchFn(customFetchFn); const controller = new AbortController(); return makeCancelablePromise(() => __awaiter(this, void 0, void 0, function* () { if (controller.signal.aborted) throw new CanceledPromiseError(); const { path: tmpDir, cleanup: deleteTmpDir } = yield dir({ unsafeCleanup: true, }); if (controller.signal.aborted) { yield deleteTmpDir(); throw new CanceledPromiseError(); } const res = yield fetchFn(url, { signal: controller.signal, redirect: 'follow', }); if (!res.ok) { throw new Error(`Failed to download ${url}: ${res.status} ${res.statusText}`); } const filePath = join(tmpDir, basename(new URL(url).pathname)); if (res.body) { const fileStream = createWriteStream(filePath); const reader = res.body.getReader(); const contentLengthHeader = res.headers.get('content-length'); const total = contentLengthHeader ? Number.parseInt(contentLengthHeader, 10) : null; let receivedLength = 0; while (true) { if (controller.signal.aborted) { throw new CanceledPromiseError(); } const { done, value } = yield reader.read(); if (done) break; receivedLength += value.length; fileStream.write(Buffer.from(value)); if (onProgress && total !== null) { onProgress({ type: 'DOWNLOADING_FILE', payload: { url, progress: Math.round((receivedLength / total) * 100), }, }); } } yield new Promise((resolve, reject) => { fileStream.on('error', reject); fileStream.on('finish', () => resolve(undefined)); fileStream.end(); }); } else { const arrayBuffer = yield res.arrayBuffer(); yield promises.writeFile(filePath, Buffer.from(arrayBuffer)); } if (controller.signal.aborted) throw new CanceledPromiseError(); return { filePath, deleteFile: deleteTmpDir, }; }), () => { controller.abort(); }); } //# sourceMappingURL=downloadFile.js.map