UNPKG

@mux/upchunk

Version:

Dead simple chunked file uploads using Fetch

1,495 lines (1,487 loc) 48.8 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); // node_modules/global/window.js var require_window = __commonJS({ "node_modules/global/window.js"(exports, module) { var win; if (typeof window !== "undefined") { win = window; } else if (typeof global !== "undefined") { win = global; } else if (typeof self !== "undefined") { win = self; } else { win = {}; } module.exports = win; } }); // node_modules/is-function/index.js var require_is_function = __commonJS({ "node_modules/is-function/index.js"(exports, module) { module.exports = isFunction; var toString = Object.prototype.toString; function isFunction(fn) { if (!fn) { return false; } var string = toString.call(fn); return string === "[object Function]" || typeof fn === "function" && string !== "[object RegExp]" || typeof window !== "undefined" && (fn === window.setTimeout || fn === window.alert || fn === window.confirm || fn === window.prompt); } } }); // node_modules/parse-headers/parse-headers.js var require_parse_headers = __commonJS({ "node_modules/parse-headers/parse-headers.js"(exports, module) { var trim = function(string) { return string.replace(/^\s+|\s+$/g, ""); }; var isArray = function(arg) { return Object.prototype.toString.call(arg) === "[object Array]"; }; module.exports = function(headers) { if (!headers) return {}; var result = {}; var headersArr = trim(headers).split("\n"); for (var i = 0; i < headersArr.length; i++) { var row = headersArr[i]; var index = row.indexOf(":"), key = trim(row.slice(0, index)).toLowerCase(), value = trim(row.slice(index + 1)); if (typeof result[key] === "undefined") { result[key] = value; } else if (isArray(result[key])) { result[key].push(value); } else { result[key] = [result[key], value]; } } return result; }; } }); // node_modules/xtend/immutable.js var require_immutable = __commonJS({ "node_modules/xtend/immutable.js"(exports, module) { module.exports = extend; var hasOwnProperty = Object.prototype.hasOwnProperty; function extend() { var target = {}; for (var i = 0; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; } } }); // node_modules/xhr/index.js var require_xhr = __commonJS({ "node_modules/xhr/index.js"(exports, module) { "use strict"; var window2 = require_window(); var isFunction = require_is_function(); var parseHeaders = require_parse_headers(); var xtend = require_immutable(); module.exports = createXHR; module.exports.default = createXHR; createXHR.XMLHttpRequest = window2.XMLHttpRequest || noop; createXHR.XDomainRequest = "withCredentials" in new createXHR.XMLHttpRequest() ? createXHR.XMLHttpRequest : window2.XDomainRequest; forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) { createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) { options = initParams(uri, options, callback); options.method = method.toUpperCase(); return _createXHR(options); }; }); function forEachArray(array, iterator) { for (var i = 0; i < array.length; i++) { iterator(array[i]); } } function isEmpty(obj) { for (var i in obj) { if (obj.hasOwnProperty(i)) return false; } return true; } function initParams(uri, options, callback) { var params = uri; if (isFunction(options)) { callback = options; if (typeof uri === "string") { params = { uri }; } } else { params = xtend(options, { uri }); } params.callback = callback; return params; } function createXHR(uri, options, callback) { options = initParams(uri, options, callback); return _createXHR(options); } function _createXHR(options) { if (typeof options.callback === "undefined") { throw new Error("callback argument missing"); } var called = false; var callback = function cbOnce(err, response, body2) { if (!called) { called = true; options.callback(err, response, body2); } }; function readystatechange() { if (xhr2.readyState === 4) { setTimeout(loadFunc, 0); } } function getBody() { var body2 = void 0; if (xhr2.response) { body2 = xhr2.response; } else { body2 = xhr2.responseText || getXml(xhr2); } if (isJson) { try { body2 = JSON.parse(body2); } catch (e) { } } return body2; } function errorFunc(evt) { clearTimeout(timeoutTimer); if (!(evt instanceof Error)) { evt = new Error("" + (evt || "Unknown XMLHttpRequest Error")); } evt.statusCode = 0; return callback(evt, failureResponse); } function loadFunc() { if (aborted) return; var status; clearTimeout(timeoutTimer); if (options.useXDR && xhr2.status === void 0) { status = 200; } else { status = xhr2.status === 1223 ? 204 : xhr2.status; } var response = failureResponse; var err = null; if (status !== 0) { response = { body: getBody(), statusCode: status, method, headers: {}, url: uri, rawRequest: xhr2 }; if (xhr2.getAllResponseHeaders) { response.headers = parseHeaders(xhr2.getAllResponseHeaders()); } } else { err = new Error("Internal XMLHttpRequest Error"); } return callback(err, response, response.body); } var xhr2 = options.xhr || null; if (!xhr2) { if (options.cors || options.useXDR) { xhr2 = new createXHR.XDomainRequest(); } else { xhr2 = new createXHR.XMLHttpRequest(); } } var key; var aborted; var uri = xhr2.url = options.uri || options.url; var method = xhr2.method = options.method || "GET"; var body = options.body || options.data; var headers = xhr2.headers = options.headers || {}; var sync = !!options.sync; var isJson = false; var timeoutTimer; var failureResponse = { body: void 0, headers: {}, statusCode: 0, method, url: uri, rawRequest: xhr2 }; if ("json" in options && options.json !== false) { isJson = true; headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json"); if (method !== "GET" && method !== "HEAD") { headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json"); body = JSON.stringify(options.json === true ? body : options.json); } } xhr2.onreadystatechange = readystatechange; xhr2.onload = loadFunc; xhr2.onerror = errorFunc; xhr2.onprogress = function() { }; xhr2.onabort = function() { aborted = true; }; xhr2.ontimeout = errorFunc; xhr2.open(method, uri, !sync, options.username, options.password); if (!sync) { xhr2.withCredentials = !!options.withCredentials; } if (!sync && options.timeout > 0) { timeoutTimer = setTimeout(function() { if (aborted) return; aborted = true; xhr2.abort("timeout"); var e = new Error("XMLHttpRequest timeout"); e.code = "ETIMEDOUT"; errorFunc(e); }, options.timeout); } if (xhr2.setRequestHeader) { for (key in headers) { if (headers.hasOwnProperty(key)) { xhr2.setRequestHeader(key, headers[key]); } } } else if (options.headers && !isEmpty(options.headers)) { throw new Error("Headers cannot be set on an XDomainRequest object"); } if ("responseType" in options) { xhr2.responseType = options.responseType; } if ("beforeSend" in options && typeof options.beforeSend === "function") { options.beforeSend(xhr2); } xhr2.send(body || null); return xhr2; } function getXml(xhr2) { try { if (xhr2.responseType === "document") { return xhr2.responseXML; } var firefoxBugTakenEffect = xhr2.responseXML && xhr2.responseXML.documentElement.nodeName === "parsererror"; if (xhr2.responseType === "" && !firefoxBugTakenEffect) { return xhr2.responseXML; } } catch (e) { } return null; } function noop() { } } }); // node_modules/event-target-shim/index.mjs function assertType(condition, message, ...args) { if (!condition) { throw new TypeError(format(message, args)); } } function format(message, args) { let i = 0; return message.replace(/%[os]/gu, () => anyToString(args[i++])); } function anyToString(x) { if (typeof x !== "object" || x === null) { return String(x); } return Object.prototype.toString.call(x); } var currentErrorHandler; function reportError(maybeError) { try { const error = maybeError instanceof Error ? maybeError : new Error(anyToString(maybeError)); if (currentErrorHandler) { currentErrorHandler(error); return; } if (typeof dispatchEvent === "function" && typeof ErrorEvent === "function") { dispatchEvent(new ErrorEvent("error", { error, message: error.message })); } else if (typeof process !== "undefined" && typeof process.emit === "function") { process.emit("uncaughtException", error); return; } console.error(error); } catch (_a) { } } var Global = typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : typeof globalThis !== "undefined" ? globalThis : void 0; var currentWarnHandler; var Warning = class { constructor(code, message) { this.code = code; this.message = message; } warn(...args) { var _a; try { if (currentWarnHandler) { currentWarnHandler({ ...this, args }); return; } const stack = ((_a = new Error().stack) !== null && _a !== void 0 ? _a : "").replace(/^(?:.+?\n){2}/gu, "\n"); console.warn(this.message, ...args, stack); } catch (_b) { } } }; var InitEventWasCalledWhileDispatching = new Warning("W01", "Unable to initialize event under dispatching."); var FalsyWasAssignedToCancelBubble = new Warning("W02", "Assigning any falsy value to 'cancelBubble' property has no effect."); var TruthyWasAssignedToReturnValue = new Warning("W03", "Assigning any truthy value to 'returnValue' property has no effect."); var NonCancelableEventWasCanceled = new Warning("W04", "Unable to preventDefault on non-cancelable events."); var CanceledInPassiveListener = new Warning("W05", "Unable to preventDefault inside passive event listener invocation."); var EventListenerWasDuplicated = new Warning("W06", "An event listener wasn't added because it has been added already: %o, %o"); var OptionWasIgnored = new Warning("W07", "The %o option value was abandoned because the event listener wasn't added as duplicated."); var InvalidEventListener = new Warning("W08", "The 'callback' argument must be a function or an object that has 'handleEvent' method: %o"); var InvalidAttributeHandler = new Warning("W09", "Event attribute handler must be a function: %o"); var Event = class { static get NONE() { return NONE; } static get CAPTURING_PHASE() { return CAPTURING_PHASE; } static get AT_TARGET() { return AT_TARGET; } static get BUBBLING_PHASE() { return BUBBLING_PHASE; } constructor(type, eventInitDict) { Object.defineProperty(this, "isTrusted", { value: false, enumerable: true }); const opts = eventInitDict !== null && eventInitDict !== void 0 ? eventInitDict : {}; internalDataMap.set(this, { type: String(type), bubbles: Boolean(opts.bubbles), cancelable: Boolean(opts.cancelable), composed: Boolean(opts.composed), target: null, currentTarget: null, stopPropagationFlag: false, stopImmediatePropagationFlag: false, canceledFlag: false, inPassiveListenerFlag: false, dispatchFlag: false, timeStamp: Date.now() }); } get type() { return $(this).type; } get target() { return $(this).target; } get srcElement() { return $(this).target; } get currentTarget() { return $(this).currentTarget; } composedPath() { const currentTarget = $(this).currentTarget; if (currentTarget) { return [currentTarget]; } return []; } get NONE() { return NONE; } get CAPTURING_PHASE() { return CAPTURING_PHASE; } get AT_TARGET() { return AT_TARGET; } get BUBBLING_PHASE() { return BUBBLING_PHASE; } get eventPhase() { return $(this).dispatchFlag ? 2 : 0; } stopPropagation() { $(this).stopPropagationFlag = true; } get cancelBubble() { return $(this).stopPropagationFlag; } set cancelBubble(value) { if (value) { $(this).stopPropagationFlag = true; } else { FalsyWasAssignedToCancelBubble.warn(); } } stopImmediatePropagation() { const data = $(this); data.stopPropagationFlag = data.stopImmediatePropagationFlag = true; } get bubbles() { return $(this).bubbles; } get cancelable() { return $(this).cancelable; } get returnValue() { return !$(this).canceledFlag; } set returnValue(value) { if (!value) { setCancelFlag($(this)); } else { TruthyWasAssignedToReturnValue.warn(); } } preventDefault() { setCancelFlag($(this)); } get defaultPrevented() { return $(this).canceledFlag; } get composed() { return $(this).composed; } get isTrusted() { return false; } get timeStamp() { return $(this).timeStamp; } initEvent(type, bubbles = false, cancelable = false) { const data = $(this); if (data.dispatchFlag) { InitEventWasCalledWhileDispatching.warn(); return; } internalDataMap.set(this, { ...data, type: String(type), bubbles: Boolean(bubbles), cancelable: Boolean(cancelable), target: null, currentTarget: null, stopPropagationFlag: false, stopImmediatePropagationFlag: false, canceledFlag: false }); } }; var NONE = 0; var CAPTURING_PHASE = 1; var AT_TARGET = 2; var BUBBLING_PHASE = 3; var internalDataMap = /* @__PURE__ */ new WeakMap(); function $(event, name = "this") { const retv = internalDataMap.get(event); assertType(retv != null, "'%s' must be an object that Event constructor created, but got another one: %o", name, event); return retv; } function setCancelFlag(data) { if (data.inPassiveListenerFlag) { CanceledInPassiveListener.warn(); return; } if (!data.cancelable) { NonCancelableEventWasCanceled.warn(); return; } data.canceledFlag = true; } Object.defineProperty(Event, "NONE", { enumerable: true }); Object.defineProperty(Event, "CAPTURING_PHASE", { enumerable: true }); Object.defineProperty(Event, "AT_TARGET", { enumerable: true }); Object.defineProperty(Event, "BUBBLING_PHASE", { enumerable: true }); var keys = Object.getOwnPropertyNames(Event.prototype); for (let i = 0; i < keys.length; ++i) { if (keys[i] === "constructor") { continue; } Object.defineProperty(Event.prototype, keys[i], { enumerable: true }); } if (typeof Global !== "undefined" && typeof Global.Event !== "undefined") { Object.setPrototypeOf(Event.prototype, Global.Event.prototype); } function createInvalidStateError(message) { if (Global.DOMException) { return new Global.DOMException(message, "InvalidStateError"); } if (DOMException == null) { DOMException = class DOMException2 extends Error { constructor(msg) { super(msg); if (Error.captureStackTrace) { Error.captureStackTrace(this, DOMException2); } } get code() { return 11; } get name() { return "InvalidStateError"; } }; Object.defineProperties(DOMException.prototype, { code: { enumerable: true }, name: { enumerable: true } }); defineErrorCodeProperties(DOMException); defineErrorCodeProperties(DOMException.prototype); } return new DOMException(message); } var DOMException; var ErrorCodeMap = { INDEX_SIZE_ERR: 1, DOMSTRING_SIZE_ERR: 2, HIERARCHY_REQUEST_ERR: 3, WRONG_DOCUMENT_ERR: 4, INVALID_CHARACTER_ERR: 5, NO_DATA_ALLOWED_ERR: 6, NO_MODIFICATION_ALLOWED_ERR: 7, NOT_FOUND_ERR: 8, NOT_SUPPORTED_ERR: 9, INUSE_ATTRIBUTE_ERR: 10, INVALID_STATE_ERR: 11, SYNTAX_ERR: 12, INVALID_MODIFICATION_ERR: 13, NAMESPACE_ERR: 14, INVALID_ACCESS_ERR: 15, VALIDATION_ERR: 16, TYPE_MISMATCH_ERR: 17, SECURITY_ERR: 18, NETWORK_ERR: 19, ABORT_ERR: 20, URL_MISMATCH_ERR: 21, QUOTA_EXCEEDED_ERR: 22, TIMEOUT_ERR: 23, INVALID_NODE_TYPE_ERR: 24, DATA_CLONE_ERR: 25 }; function defineErrorCodeProperties(obj) { const keys2 = Object.keys(ErrorCodeMap); for (let i = 0; i < keys2.length; ++i) { const key = keys2[i]; const value = ErrorCodeMap[key]; Object.defineProperty(obj, key, { get() { return value; }, configurable: true, enumerable: true }); } } var EventWrapper = class extends Event { static wrap(event) { return new (getWrapperClassOf(event))(event); } constructor(event) { super(event.type, { bubbles: event.bubbles, cancelable: event.cancelable, composed: event.composed }); if (event.cancelBubble) { super.stopPropagation(); } if (event.defaultPrevented) { super.preventDefault(); } internalDataMap$1.set(this, { original: event }); const keys2 = Object.keys(event); for (let i = 0; i < keys2.length; ++i) { const key = keys2[i]; if (!(key in this)) { Object.defineProperty(this, key, defineRedirectDescriptor(event, key)); } } } stopPropagation() { super.stopPropagation(); const { original } = $$1(this); if ("stopPropagation" in original) { original.stopPropagation(); } } get cancelBubble() { return super.cancelBubble; } set cancelBubble(value) { super.cancelBubble = value; const { original } = $$1(this); if ("cancelBubble" in original) { original.cancelBubble = value; } } stopImmediatePropagation() { super.stopImmediatePropagation(); const { original } = $$1(this); if ("stopImmediatePropagation" in original) { original.stopImmediatePropagation(); } } get returnValue() { return super.returnValue; } set returnValue(value) { super.returnValue = value; const { original } = $$1(this); if ("returnValue" in original) { original.returnValue = value; } } preventDefault() { super.preventDefault(); const { original } = $$1(this); if ("preventDefault" in original) { original.preventDefault(); } } get timeStamp() { const { original } = $$1(this); if ("timeStamp" in original) { return original.timeStamp; } return super.timeStamp; } }; var internalDataMap$1 = /* @__PURE__ */ new WeakMap(); function $$1(event) { const retv = internalDataMap$1.get(event); assertType(retv != null, "'this' is expected an Event object, but got", event); return retv; } var wrapperClassCache = /* @__PURE__ */ new WeakMap(); wrapperClassCache.set(Object.prototype, EventWrapper); if (typeof Global !== "undefined" && typeof Global.Event !== "undefined") { wrapperClassCache.set(Global.Event.prototype, EventWrapper); } function getWrapperClassOf(originalEvent) { const prototype = Object.getPrototypeOf(originalEvent); if (prototype == null) { return EventWrapper; } let wrapper = wrapperClassCache.get(prototype); if (wrapper == null) { wrapper = defineWrapper(getWrapperClassOf(prototype), prototype); wrapperClassCache.set(prototype, wrapper); } return wrapper; } function defineWrapper(BaseEventWrapper, originalPrototype) { class CustomEventWrapper extends BaseEventWrapper { } const keys2 = Object.keys(originalPrototype); for (let i = 0; i < keys2.length; ++i) { Object.defineProperty(CustomEventWrapper.prototype, keys2[i], defineRedirectDescriptor(originalPrototype, keys2[i])); } return CustomEventWrapper; } function defineRedirectDescriptor(obj, key) { const d = Object.getOwnPropertyDescriptor(obj, key); return { get() { const original = $$1(this).original; const value = original[key]; if (typeof value === "function") { return value.bind(original); } return value; }, set(value) { const original = $$1(this).original; original[key] = value; }, configurable: d.configurable, enumerable: d.enumerable }; } function createListener(callback, capture, passive, once, signal, signalListener) { return { callback, flags: (capture ? 1 : 0) | (passive ? 2 : 0) | (once ? 4 : 0), signal, signalListener }; } function setRemoved(listener) { listener.flags |= 8; } function isCapture(listener) { return (listener.flags & 1) === 1; } function isPassive(listener) { return (listener.flags & 2) === 2; } function isOnce(listener) { return (listener.flags & 4) === 4; } function isRemoved(listener) { return (listener.flags & 8) === 8; } function invokeCallback({ callback }, target, event) { try { if (typeof callback === "function") { callback.call(target, event); } else if (typeof callback.handleEvent === "function") { callback.handleEvent(event); } } catch (thrownError) { reportError(thrownError); } } function findIndexOfListener({ listeners }, callback, capture) { for (let i = 0; i < listeners.length; ++i) { if (listeners[i].callback === callback && isCapture(listeners[i]) === capture) { return i; } } return -1; } function addListener(list, callback, capture, passive, once, signal) { let signalListener; if (signal) { signalListener = removeListener.bind(null, list, callback, capture); signal.addEventListener("abort", signalListener); } const listener = createListener(callback, capture, passive, once, signal, signalListener); if (list.cow) { list.cow = false; list.listeners = [...list.listeners, listener]; } else { list.listeners.push(listener); } return listener; } function removeListener(list, callback, capture) { const index = findIndexOfListener(list, callback, capture); if (index !== -1) { return removeListenerAt(list, index); } return false; } function removeListenerAt(list, index, disableCow = false) { const listener = list.listeners[index]; setRemoved(listener); if (listener.signal) { listener.signal.removeEventListener("abort", listener.signalListener); } if (list.cow && !disableCow) { list.cow = false; list.listeners = list.listeners.filter((_, i) => i !== index); return false; } list.listeners.splice(index, 1); return true; } function createListenerListMap() { return /* @__PURE__ */ Object.create(null); } function ensureListenerList(listenerMap, type) { var _a; return (_a = listenerMap[type]) !== null && _a !== void 0 ? _a : listenerMap[type] = { attrCallback: void 0, attrListener: void 0, cow: false, listeners: [] }; } var EventTarget = class { constructor() { internalDataMap$2.set(this, createListenerListMap()); } addEventListener(type0, callback0, options0) { const listenerMap = $$2(this); const { callback, capture, once, passive, signal, type } = normalizeAddOptions(type0, callback0, options0); if (callback == null || (signal === null || signal === void 0 ? void 0 : signal.aborted)) { return; } const list = ensureListenerList(listenerMap, type); const i = findIndexOfListener(list, callback, capture); if (i !== -1) { warnDuplicate(list.listeners[i], passive, once, signal); return; } addListener(list, callback, capture, passive, once, signal); } removeEventListener(type0, callback0, options0) { const listenerMap = $$2(this); const { callback, capture, type } = normalizeOptions(type0, callback0, options0); const list = listenerMap[type]; if (callback != null && list) { removeListener(list, callback, capture); } } dispatchEvent(e) { const list = $$2(this)[String(e.type)]; if (list == null) { return true; } const event = e instanceof Event ? e : EventWrapper.wrap(e); const eventData = $(event, "event"); if (eventData.dispatchFlag) { throw createInvalidStateError("This event has been in dispatching."); } eventData.dispatchFlag = true; eventData.target = eventData.currentTarget = this; if (!eventData.stopPropagationFlag) { const { cow, listeners } = list; list.cow = true; for (let i = 0; i < listeners.length; ++i) { const listener = listeners[i]; if (isRemoved(listener)) { continue; } if (isOnce(listener) && removeListenerAt(list, i, !cow)) { i -= 1; } eventData.inPassiveListenerFlag = isPassive(listener); invokeCallback(listener, this, event); eventData.inPassiveListenerFlag = false; if (eventData.stopImmediatePropagationFlag) { break; } } if (!cow) { list.cow = false; } } eventData.target = null; eventData.currentTarget = null; eventData.stopImmediatePropagationFlag = false; eventData.stopPropagationFlag = false; eventData.dispatchFlag = false; return !eventData.canceledFlag; } }; var internalDataMap$2 = /* @__PURE__ */ new WeakMap(); function $$2(target, name = "this") { const retv = internalDataMap$2.get(target); assertType(retv != null, "'%s' must be an object that EventTarget constructor created, but got another one: %o", name, target); return retv; } function normalizeAddOptions(type, callback, options) { var _a; assertCallback(callback); if (typeof options === "object" && options !== null) { return { type: String(type), callback: callback !== null && callback !== void 0 ? callback : void 0, capture: Boolean(options.capture), passive: Boolean(options.passive), once: Boolean(options.once), signal: (_a = options.signal) !== null && _a !== void 0 ? _a : void 0 }; } return { type: String(type), callback: callback !== null && callback !== void 0 ? callback : void 0, capture: Boolean(options), passive: false, once: false, signal: void 0 }; } function normalizeOptions(type, callback, options) { assertCallback(callback); if (typeof options === "object" && options !== null) { return { type: String(type), callback: callback !== null && callback !== void 0 ? callback : void 0, capture: Boolean(options.capture) }; } return { type: String(type), callback: callback !== null && callback !== void 0 ? callback : void 0, capture: Boolean(options) }; } function assertCallback(callback) { if (typeof callback === "function" || typeof callback === "object" && callback !== null && typeof callback.handleEvent === "function") { return; } if (callback == null || typeof callback === "object") { InvalidEventListener.warn(callback); return; } throw new TypeError(format(InvalidEventListener.message, [callback])); } function warnDuplicate(listener, passive, once, signal) { EventListenerWasDuplicated.warn(isCapture(listener) ? "capture" : "bubble", listener.callback); if (isPassive(listener) !== passive) { OptionWasIgnored.warn("passive"); } if (isOnce(listener) !== once) { OptionWasIgnored.warn("once"); } if (listener.signal !== signal) { OptionWasIgnored.warn("signal"); } } var keys$1 = Object.getOwnPropertyNames(EventTarget.prototype); for (let i = 0; i < keys$1.length; ++i) { if (keys$1[i] === "constructor") { continue; } Object.defineProperty(EventTarget.prototype, keys$1[i], { enumerable: true }); } if (typeof Global !== "undefined" && typeof Global.EventTarget !== "undefined") { Object.setPrototypeOf(EventTarget.prototype, Global.EventTarget.prototype); } // src/upchunk.ts var import_xhr = __toESM(require_xhr()); var DEFAULT_CHUNK_SIZE = 30720; var DEFAULT_MAX_CHUNK_SIZE = 512e3; var DEFAULT_MIN_CHUNK_SIZE = 256; var isValidChunkSize = (chunkSize, { minChunkSize = DEFAULT_MIN_CHUNK_SIZE, maxChunkSize = DEFAULT_MAX_CHUNK_SIZE } = {}) => { return chunkSize == null || typeof chunkSize === "number" && chunkSize >= 256 && chunkSize % 256 === 0 && chunkSize >= minChunkSize && chunkSize <= maxChunkSize; }; var getChunkSizeError = (chunkSize, { minChunkSize = DEFAULT_MIN_CHUNK_SIZE, maxChunkSize = DEFAULT_MAX_CHUNK_SIZE } = {}) => { return new TypeError(`chunkSize ${chunkSize} must be a positive number in multiples of 256, between ${minChunkSize} and ${maxChunkSize}`); }; var ChunkedStreamIterable = class { constructor(readableStream, options = {}) { this.readableStream = readableStream; var _a, _b, _c; if (!isValidChunkSize(options.defaultChunkSize, options)) { throw getChunkSizeError(options.defaultChunkSize, options); } this.defaultChunkSize = (_a = options.defaultChunkSize) != null ? _a : DEFAULT_CHUNK_SIZE; this.minChunkSize = (_b = options.minChunkSize) != null ? _b : DEFAULT_MIN_CHUNK_SIZE; this.maxChunkSize = (_c = options.maxChunkSize) != null ? _c : DEFAULT_MAX_CHUNK_SIZE; } get chunkSize() { var _a; return (_a = this._chunkSize) != null ? _a : this.defaultChunkSize; } set chunkSize(value) { if (!isValidChunkSize(value, this)) { throw getChunkSizeError(value, this); } this._chunkSize = value; } get chunkByteSize() { return this.chunkSize * 1024; } get error() { return this._error; } async *[Symbol.asyncIterator]() { let chunk; const reader = this.readableStream.getReader(); try { while (true) { const { done, value } = await reader.read(); if (done) { if (chunk) { const outgoingChunk = chunk; chunk = void 0; yield outgoingChunk; } break; } const normalizedBlobChunk = value instanceof Uint8Array ? new Blob([value], { type: "application/octet-stream" }) : value; chunk = chunk ? new Blob([chunk, normalizedBlobChunk]) : normalizedBlobChunk; while (chunk) { if (chunk.size === this.chunkByteSize) { const outgoingChunk = chunk; chunk = void 0; yield outgoingChunk; break; } else if (chunk.size < this.chunkByteSize) { break; } else { const outgoingChunk = chunk.slice(0, this.chunkByteSize); chunk = chunk.slice(this.chunkByteSize); yield outgoingChunk; } } } } catch (e) { this._error = e; } finally { if (chunk) { const outgoingChunk = chunk; chunk = void 0; yield outgoingChunk; } reader.releaseLock(); return; } } }; var ChunkedFileIterable = class { constructor(file, options = {}) { this.file = file; var _a, _b, _c; if (!isValidChunkSize(options.defaultChunkSize, options)) { throw getChunkSizeError(options.defaultChunkSize, options); } this.defaultChunkSize = (_a = options.defaultChunkSize) != null ? _a : DEFAULT_CHUNK_SIZE; this.minChunkSize = (_b = options.minChunkSize) != null ? _b : DEFAULT_MIN_CHUNK_SIZE; this.maxChunkSize = (_c = options.maxChunkSize) != null ? _c : DEFAULT_MAX_CHUNK_SIZE; } get chunkSize() { var _a; return (_a = this._chunkSize) != null ? _a : this.defaultChunkSize; } set chunkSize(value) { if (!isValidChunkSize(value, this)) { throw getChunkSizeError(value, this); } this._chunkSize = value; } get chunkByteSize() { return this.chunkSize * 1024; } get error() { return this._error; } async *[Symbol.asyncIterator]() { const reader = new FileReader(); let nextChunkRangeStart = 0; const getChunk = () => { return new Promise((resolve) => { if (nextChunkRangeStart >= this.file.size) { resolve(void 0); return; } const length = Math.min(this.chunkByteSize, this.file.size - nextChunkRangeStart); reader.onload = () => { if (reader.result !== null) { resolve(new Blob([reader.result], { type: "application/octet-stream" })); } else { resolve(void 0); } }; reader.readAsArrayBuffer(this.file.slice(nextChunkRangeStart, nextChunkRangeStart + length)); }); }; try { while (true) { const nextChunk = await getChunk(); if (!!nextChunk) { nextChunkRangeStart += nextChunk.size; yield nextChunk; } else { break; } } } catch (e) { this._error = e; } } }; var SUCCESSFUL_CHUNK_UPLOAD_CODES = [200, 201, 202, 204, 308]; var TEMPORARY_ERROR_CODES = [408, 502, 503, 504]; var RESUME_INCOMPLETE_CODES = [308]; var isSuccessfulChunkUpload = (res, _options) => !!res && SUCCESSFUL_CHUNK_UPLOAD_CODES.includes(res.statusCode); var isRetriableChunkUpload = (res, { retryCodes = TEMPORARY_ERROR_CODES }) => !res || retryCodes.includes(res.statusCode); var isFailedChunkUpload = (res, options) => { return options.attemptCount >= options.attempts || !(isSuccessfulChunkUpload(res) || isRetriableChunkUpload(res, options)); }; var isIncompleteChunkUploadNeedingRetry = (res, _options) => { var _a; if (!res || !RESUME_INCOMPLETE_CODES.includes(res.statusCode) || !((_a = res.headers) == null ? void 0 : _a["range"])) { return false; } const range = res.headers["range"].match(/bytes=(\d+)-(\d+)/); if (!range) { return false; } const endByte = parseInt(range[2], 10); return endByte < _options.currentChunkEndByte; }; var UpChunk = class { static createUpload(options) { return new UpChunk(options); } constructor(options) { this.eventTarget = new EventTarget(); this.endpoint = options.endpoint; this.file = options.file; this.headers = options.headers || {}; this.method = options.method || "PUT"; this.attempts = options.attempts || 5; this.delayBeforeAttempt = options.delayBeforeAttempt || 1; this.retryCodes = options.retryCodes || TEMPORARY_ERROR_CODES; this.dynamicChunkSize = options.dynamicChunkSize || false; this.maxFileBytes = (options.maxFileSize || 0) * 1024; this.chunkCount = 0; this.attemptCount = 0; this._offline = typeof window !== "undefined" && !window.navigator.onLine; this._paused = false; this.success = false; this.nextChunkRangeStart = 0; if (options.useLargeFileWorkaround) { const readableStreamErrorCallback = (event) => { if (this.chunkedIterable.error) { console.warn(`Unable to read file of size ${this.file.size} bytes via a ReadableStream. Falling back to in-memory FileReader!`); event.stopImmediatePropagation(); this.chunkedIterable = new ChunkedFileIterable(this.file, { ...options, defaultChunkSize: options.chunkSize }); this.chunkedIterator = this.chunkedIterable[Symbol.asyncIterator](); this.getEndpoint().then(() => { this.sendChunks(); }).catch((e) => { const message = (e == null ? void 0 : e.message) ? `: ${e.message}` : ""; this.dispatch("error", { message: `Failed to get endpoint${message}` }); }); this.off("error", readableStreamErrorCallback); } }; this.on("error", readableStreamErrorCallback); } this.chunkedIterable = new ChunkedStreamIterable(this.file.stream(), { ...options, defaultChunkSize: options.chunkSize }); this.chunkedIterator = this.chunkedIterable[Symbol.asyncIterator](); this.totalChunks = Math.ceil(this.file.size / this.chunkByteSize); this.validateOptions(); this.getEndpoint().then(() => this.sendChunks()).catch((e) => { const message = (e == null ? void 0 : e.message) ? `: ${e.message}` : ""; this.dispatch("error", { message: `Failed to get endpoint${message}` }); }); if (typeof window !== "undefined") { window.addEventListener("online", () => { if (!this.offline) return; this._offline = false; this.dispatch("online"); this.sendChunks(); }); window.addEventListener("offline", () => { if (this.offline) return; this._offline = true; this.dispatch("offline"); }); } } get maxChunkSize() { var _a, _b; return (_b = (_a = this.chunkedIterable) == null ? void 0 : _a.maxChunkSize) != null ? _b : DEFAULT_MAX_CHUNK_SIZE; } get minChunkSize() { var _a, _b; return (_b = (_a = this.chunkedIterable) == null ? void 0 : _a.minChunkSize) != null ? _b : DEFAULT_MIN_CHUNK_SIZE; } get chunkSize() { var _a, _b; return (_b = (_a = this.chunkedIterable) == null ? void 0 : _a.chunkSize) != null ? _b : DEFAULT_CHUNK_SIZE; } set chunkSize(value) { this.chunkedIterable.chunkSize = value; } get chunkByteSize() { return this.chunkedIterable.chunkByteSize; } get totalChunkSize() { return Math.ceil(this.file.size / this.chunkByteSize); } on(eventName, fn) { this.eventTarget.addEventListener(eventName, fn); } once(eventName, fn) { this.eventTarget.addEventListener(eventName, fn, { once: true }); } off(eventName, fn) { this.eventTarget.removeEventListener(eventName, fn); } get offline() { return this._offline; } get paused() { return this._paused; } abort() { var _a; this.pause(); (_a = this.currentXhr) == null ? void 0 : _a.abort(); } pause() { this._paused = true; } resume() { if (this._paused) { this._paused = false; this.sendChunks(); } } get successfulPercentage() { return this.nextChunkRangeStart / this.file.size; } dispatch(eventName, detail) { const event = new CustomEvent(eventName, { detail }); this.eventTarget.dispatchEvent(event); } validateOptions() { if (!this.endpoint || typeof this.endpoint !== "function" && typeof this.endpoint !== "string") { throw new TypeError("endpoint must be defined as a string or a function that returns a promise"); } if (!(this.file instanceof File)) { throw new TypeError("file must be a File object"); } if (this.headers && typeof this.headers !== "function" && typeof this.headers !== "object") { throw new TypeError("headers must be null, an object, or a function that returns an object or a promise"); } if (!isValidChunkSize(this.chunkSize, { maxChunkSize: this.maxChunkSize, minChunkSize: this.minChunkSize })) { throw getChunkSizeError(this.chunkSize, { maxChunkSize: this.maxChunkSize, minChunkSize: this.minChunkSize }); } if (this.maxChunkSize && (typeof this.maxChunkSize !== "number" || this.maxChunkSize < 256 || this.maxChunkSize % 256 !== 0 || this.maxChunkSize < this.chunkSize || this.maxChunkSize < this.minChunkSize)) { throw new TypeError(`maxChunkSize must be a positive number in multiples of 256, and larger than or equal to both ${this.minChunkSize} and ${this.chunkSize}`); } if (this.minChunkSize && (typeof this.minChunkSize !== "number" || this.minChunkSize < 256 || this.minChunkSize % 256 !== 0 || this.minChunkSize > this.chunkSize || this.minChunkSize > this.maxChunkSize)) { throw new TypeError(`minChunkSize must be a positive number in multiples of 256, and smaller than ${this.chunkSize} and ${this.maxChunkSize}`); } if (this.maxFileBytes > 0 && this.maxFileBytes < this.file.size) { throw new Error(`file size exceeds maximum (${this.file.size} > ${this.maxFileBytes})`); } if (this.attempts && (typeof this.attempts !== "number" || this.attempts <= 0)) { throw new TypeError("retries must be a positive number"); } if (this.delayBeforeAttempt && (typeof this.delayBeforeAttempt !== "number" || this.delayBeforeAttempt < 0)) { throw new TypeError("delayBeforeAttempt must be a positive number"); } } getEndpoint() { if (typeof this.endpoint === "string") { this.endpointValue = this.endpoint; return Promise.resolve(this.endpoint); } return this.endpoint(this.file).then((value) => { this.endpointValue = value; if (typeof value !== "string") { throw new TypeError("endpoint must return a string"); } return this.endpointValue; }); } xhrPromise(options) { const beforeSend = (xhrObject) => { xhrObject.upload.onprogress = (event) => { var _a; const remainingChunks = this.totalChunks - this.chunkCount; const percentagePerChunk = (this.file.size - this.nextChunkRangeStart) / this.file.size / remainingChunks; const currentChunkProgress = event.loaded / ((_a = event.total) != null ? _a : this.chunkByteSize); const chunkPercentage = currentChunkProgress * percentagePerChunk; this.dispatch("progress", Math.min((this.successfulPercentage + chunkPercentage) * 100, 100)); }; }; return new Promise((resolve, reject) => { this.currentXhr = (0, import_xhr.default)({ ...options, beforeSend }, (err, resp) => { this.currentXhr = void 0; if (err) { return reject(err); } return resolve(resp); }); }); } async sendChunk(chunk) { const rangeStart = this.nextChunkRangeStart; const rangeEnd = rangeStart + chunk.size - 1; const extraHeaders = await (typeof this.headers === "function" ? this.headers() : this.headers); const headers = { ...extraHeaders, "Content-Type": this.file.type, "Content-Range": `bytes ${rangeStart}-${rangeEnd}/${this.file.size}` }; this.dispatch("attempt", { chunkNumber: this.chunkCount, totalChunks: this.totalChunks, chunkSize: this.chunkSize }); return this.xhrPromise({ headers, url: this.endpointValue, method: this.method, body: chunk }); } async sendChunkWithRetries(chunk) { const successfulChunkUploadCb = async (res2, _chunk) => { var _a; const lastChunkEnd = new Date(); const lastChunkInterval = (lastChunkEnd.getTime() - this.lastChunkStart.getTime()) / 1e3; this.dispatch("chunkSuccess", { chunk: this.chunkCount, chunkSize: this.chunkSize, attempts: this.attemptCount, timeInterval: lastChunkInterval, response: res2 }); this.attemptCount = 0; this.chunkCount = ((_a = this.chunkCount) != null ? _a : 0) + 1; this.nextChunkRangeStart = this.nextChunkRangeStart + this.chunkByteSize; if (this.dynamicChunkSize) { let unevenChunkSize = this.chunkSize; if (lastChunkInterval < 10) { unevenChunkSize = Math.min(this.chunkSize * 2, this.maxChunkSize); } else if (lastChunkInterval > 30) { unevenChunkSize = Math.max(this.chunkSize / 2, this.minChunkSize); } this.chunkSize = Math.ceil(unevenChunkSize / 256) * 256; const remainingChunks = (this.file.size - this.nextChunkRangeStart) / this.chunkByteSize; this.totalChunks = Math.ceil(this.chunkCount + remainingChunks); } return true; }; const failedChunkUploadCb = async (res2, _chunk) => { this.dispatch("progress", Math.min(this.successfulPercentage * 100, 100)); this.dispatch("error", { message: `Server responded with ${res2.statusCode}. Stopping upload.`, chunk: this.chunkCount, attempts: this.attemptCount, response: res2 }); return false; }; const retriableChunkUploadCb = async (res2, _chunk) => { this.dispatch("attemptFailure", { message: `An error occured uploading chunk ${this.chunkCount}. ${this.attempts - this.attemptCount} retries left.`, chunkNumber: this.chunkCount, attemptsLeft: this.attempts - this.attemptCount, response: res2 }); return new Promise((resolve) => { setTimeout(async () => { if (this._paused || this.offline) { this.pendingChunk = chunk; resolve(false); return; } const chunkUploadSuccess = await this.sendChunkWithRetries(chunk); resolve(chunkUploadSuccess); }, this.delayBeforeAttempt * 1e3); }); }; let res; try { this.attemptCount = this.attemptCount + 1; this.lastChunkStart = new Date(); res = await this.sendChunk(chunk); } catch (err) { if (typeof (err == null ? void 0 : err.statusCode) === "number") { res = err; } } const options = { retryCodes: this.retryCodes, attemptCount: this.attemptCount, attempts: this.attempts, currentChunkEndByte: this.nextChunkRangeStart + chunk.size - 1 }; if (isIncompleteChunkUploadNeedingRetry(res, options)) { return retriableChunkUploadCb(res, chunk); } if (isSuccessfulChunkUpload(res, options)) { return successfulChunkUploadCb(res, chunk); } if (isFailedChunkUpload(res, options)) { return failedChunkUploadCb(res, chunk); } return retriableChunkUploadCb(res, chunk); } async sendChunks() { if (this.pendingChunk && !(this._paused || this.offline)) { const chunk = this.pendingChunk; this.pendingChunk = void 0; const chunkUploadSuccess = await this.sendChunkWithRetries(chunk); if (this.success && chunkUploadSuccess) { this.dispatch("success"); } } while (!(this.success || this._paused || this.offline)) { const { value: chunk, done } = await this.chunkedIterator.next(); let chunkUploadSuccess = !chunk && done; if (chunk) { chunkUploadSuccess = await this.sendChunkWithRetries(chunk); } if (this.chunkedIterable.error) { chunkUploadSuccess = false; this.dispatch("error", { message: `Unable to read file of size ${this.file.size} bytes. Try loading from another browser.` }); return; } this.success = !!done; if (this.success && chunkUploadSuccess) { this.dispatch("success"); } if (!chunkUploadSuccess) { return; } } } }; function createUpload(options) { return UpChunk.createUpload(options); } export { ChunkedFileIterable, ChunkedStreamIterable, UpChunk, createUpload, getChunkSizeError, isIncompleteChunkUploadNeedingRetry, isValidChunkSize }; //# sourceMappingURL=upchunk.mjs.map