UNPKG

@rpldy/chunked-sender

Version:

adds chunked upload capabilities on top of the regular XHR uploads

98 lines (97 loc) 3.63 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _shared = require("@rpldy/shared"); var _simpleState = require("@rpldy/simple-state"); var _sender = _interopRequireDefault(require("@rpldy/sender")); var _utils = require("../utils"); var _consts = require("../consts"); var _ChunkedSendError = _interopRequireDefault(require("./ChunkedSendError")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const getContentRangeValue = (chunk, data, item) => data && `bytes ${chunk.start}-${chunk.start + data.size - 1}/${item.file.size}`; const mergeWithUndefined = (0, _shared.getMerge)({ undefinedOverwrites: true }); const getSkippedResult = () => ({ request: Promise.resolve({ state: _shared.FILE_STATES.FINISHED, response: "skipping chunk as instructed by CHUNK_START handler", status: 200 }), abort: () => true, senderType: "chunk-skipped-sender" }); const uploadChunkWithUpdatedData = (chunk, chunkedState, item, onProgress, trigger) => { const state = chunkedState.getState(); const unwrappedOptions = (0, _simpleState.unwrap)(state.sendOptions); const headers = { ...unwrappedOptions.headers }; if (state.sendWithRangeHeader !== false) { headers["Content-Range"] = getContentRangeValue(chunk, chunk.data, item); } else { _shared.logger.debugLog(`chunkedSender.sendChunk: excluding content-range header as sendWithRangeHeader is false for chunk ${chunk.id}`); } const sendOptions = { ...unwrappedOptions, headers }; const chunkItem = (0, _shared.createBatchItem)(chunk.data, chunk.id); const onChunkProgress = e => { onProgress(e, [chunk]); }; const chunkIndex = state.chunks.indexOf(chunk); return (0, _shared.triggerUpdater)(trigger, _consts.CHUNK_EVENTS.CHUNK_START, { item: (0, _simpleState.unwrap)(item), chunk: (0, _shared.pick)(chunk, ["id", "start", "end", "index", "attempt"]), chunkItem: { ...chunkItem }, sendOptions, url: state.url, chunkIndex, remainingCount: state.chunks.length, totalCount: state.chunkCount, onProgress }).then(response => { let result; const updatedData = typeof response === "boolean" ? response === false ? { stop: true } : {} : response || {}; if (updatedData.stop) { _shared.logger.debugLog(`chunkedSender.sendChunk: received false from CHUNK_START handler - skipping chunk ${chunkIndex}, item ${item.id}`); result = getSkippedResult(); } else { result = (0, _sender.default)([chunkItem], updatedData?.url || state.url, mergeWithUndefined({}, sendOptions, updatedData?.sendOptions), onChunkProgress); } return result; }); }; const sendChunk = (chunk, chunkedState, item, onProgress, trigger) => { if (!chunk.data) { chunkedState.updateState(() => { chunk.data = (0, _utils.getChunkDataFromFile)(item.file, chunk.start, chunk.end); }); } if (!chunk.data) { throw new _ChunkedSendError.default("chunk failure - failed to slice"); } const url = chunkedState.getState().url; _shared.logger.debugLog(`chunkedSender.sendChunk: about to send chunk ${chunk.id} [${chunk.start}-${chunk.end}] to: ${url || ""}`); const chunkXhrRequest = uploadChunkWithUpdatedData(chunk, chunkedState, item, onProgress, trigger); return { request: chunkXhrRequest.then(({ request }) => request), abort: () => { chunkXhrRequest.then(({ abort }) => abort()); return true; }, senderType: "chunk-passthrough-sender" }; }; var _default = exports.default = sendChunk;