UNPKG

transloadit

Version:
94 lines 3.9 kB
import { stat } from 'node:fs/promises'; import { basename } from 'node:path'; import debug from 'debug'; import pMap from 'p-map'; import { Upload } from 'tus-js-client'; const log = debug('transloadit'); export async function sendTusRequest({ streamsMap, assembly, requestedChunkSize, uploadConcurrency, onProgress, }) { const streamLabels = Object.keys(streamsMap); let totalBytes = 0; let lastEmittedProgress = 0; const sizes = {}; const haveUnknownLengthStreams = streamLabels.some((label) => !streamsMap[label]?.path); // Initialize size data await pMap(streamLabels, async (label) => { const streamInfo = streamsMap[label]; if (!streamInfo) { throw new Error(`Stream info not found for label: ${label}`); } const { path } = streamInfo; if (path) { const { size } = await stat(path); sizes[label] = size; totalBytes += size; } }, { concurrency: 5 }); const uploadProgresses = {}; async function uploadSingleStream(label) { uploadProgresses[label] = 0; const streamInfo = streamsMap[label]; if (!streamInfo) { throw new Error(`Stream info not found for label: ${label}`); } const { stream, path } = streamInfo; const size = sizes[label]; let chunkSize = requestedChunkSize; let uploadLengthDeferred; const isStreamLengthKnown = !!path; if (!isStreamLengthKnown) { // tus-js-client requires these options to be set for unknown size streams // https://github.com/tus/tus-js-client/blob/master/docs/api.md#uploadlengthdeferred uploadLengthDeferred = true; if (chunkSize === Number.POSITIVE_INFINITY) chunkSize = 50e6; } const onTusProgress = (bytesUploaded) => { uploadProgresses[label] = bytesUploaded; // get all uploaded bytes for all files let uploadedBytes = 0; for (const l of streamLabels) { uploadedBytes += uploadProgresses[l] ?? 0; } // don't send redundant progress if (lastEmittedProgress < uploadedBytes) { lastEmittedProgress = uploadedBytes; // If we have any unknown length streams, we cannot trust totalBytes // totalBytes should then be undefined to mimic behavior of form uploads. onProgress({ uploadedBytes, totalBytes: haveUnknownLengthStreams ? undefined : totalBytes, }); } }; const filename = path ? basename(path) : label; await new Promise((resolve, reject) => { if (!assembly.assembly_ssl_url) { reject(new Error('assembly_ssl_url is not present in the assembly status')); return; } const tusOptions = { endpoint: assembly.tus_url, metadata: { assembly_url: assembly.assembly_ssl_url, fieldname: label, filename, }, onError: reject, onProgress: onTusProgress, onSuccess: resolve, }; // tus-js-client doesn't like undefined/null if (size != null) tusOptions.uploadSize = size; if (chunkSize) tusOptions.chunkSize = chunkSize; if (uploadLengthDeferred) tusOptions.uploadLengthDeferred = uploadLengthDeferred; const tusUpload = new Upload(stream, tusOptions); tusUpload.start(); }); log(label, 'upload done'); } await pMap(streamLabels, uploadSingleStream, { concurrency: uploadConcurrency }); } //# sourceMappingURL=tus.js.map