UNPKG

tus-js-client-stall-detection

Version:

A pure JavaScript client for the tus resumable upload protocol (fork with stall detection)

2 lines 35.8 kB
((e,t)=>{"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).tus={})})(this,function(e){class n extends Error{constructor(e,t,r,o){super(e),this.originalRequest=r,this.originalResponse=o,null!=(this.causingError=t)&&(e+=", caused by "+t.toString()),null!=r&&(t=r.getHeader("X-Request-ID")||"n/a",e+=`, originated from request (method: ${r.getMethod()}, url: ${r.getURL()}, response code: ${o?o.getStatus():"n/a"}, response text: ${o?o.getBody()||"":"n/a"}, request id: ${t})`),this.message=e}}let t=!1;function h(e){t&&console.log(e)}var r="3.7.7",o="function"==typeof Buffer;let s="function"==typeof TextDecoder?new TextDecoder:void 0,O="function"==typeof TextEncoder?new TextEncoder:void 0;let a=Array.prototype.slice.call("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="),l=(e=>{let r={};return e.forEach((e,t)=>r[e]=t),r})(a),q=/^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/,u=String.fromCharCode.bind(String),L="function"==typeof Uint8Array.from?Uint8Array.from.bind(Uint8Array):e=>new Uint8Array(Array.prototype.slice.call(e,0)),k=e=>e.replace(/=/g,"").replace(/[+\/]/g,e=>"+"==e?"-":"_"),F=e=>e.replace(/[^A-Za-z0-9\+\/]/g,"");var N=t=>{let r,o,s,i,n="";var e=t.length%3;for(let e=0;e<t.length;){if(255<(o=t.charCodeAt(e++))||255<(s=t.charCodeAt(e++))||255<(i=t.charCodeAt(e++)))throw new TypeError("invalid character found");r=o<<16|s<<8|i,n+=a[r>>18&63]+a[r>>12&63]+a[r>>6&63]+a[63&r]}return e?n.slice(0,e-3)+"===".substring(e):n};let i="function"==typeof btoa?e=>btoa(e):o?e=>Buffer.from(e,"binary").toString("base64"):N,d=o?e=>Buffer.from(e).toString("base64"):r=>{var o=[];for(let e=0,t=r.length;e<t;e+=4096)o.push(u.apply(null,r.subarray(e,e+4096)));return i(o.join(""))},p=(e,t=!1)=>t?k(d(e)):d(e),j=e=>{var t;return e.length<2?(t=e.charCodeAt(0))<128?e:t<2048?u(192|t>>>6)+u(128|63&t):u(224|t>>>12&15)+u(128|t>>>6&63)+u(128|63&t):(t=65536+1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320),u(240|t>>>18&7)+u(128|t>>>12&63)+u(128|t>>>6&63)+u(128|63&t))},M=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,$=e=>e.replace(M,j),V=o?e=>Buffer.from(e,"utf8").toString("base64"):O?e=>d(O.encode(e)):e=>i($(e)),f=(e,t=!1)=>t?k(V(e)):V(e);var X=e=>f(e,!0);let K=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g,Z=e=>{switch(e.length){case 4:var t=((7&e.charCodeAt(0))<<18|(63&e.charCodeAt(1))<<12|(63&e.charCodeAt(2))<<6|63&e.charCodeAt(3))-65536;return u(55296+(t>>>10))+u(56320+(1023&t));case 3:return u((15&e.charCodeAt(0))<<12|(63&e.charCodeAt(1))<<6|63&e.charCodeAt(2));default:return u((31&e.charCodeAt(0))<<6|63&e.charCodeAt(1))}},J=e=>e.replace(K,Z);var c=t=>{if(t=t.replace(/\s+/g,""),!q.test(t))throw new TypeError("malformed base64.");t+="==".slice(2-(3&t.length));let r,o="",s,i;for(let e=0;e<t.length;)r=l[t.charAt(e++)]<<18|l[t.charAt(e++)]<<12|(s=l[t.charAt(e++)])<<6|(i=l[t.charAt(e++)]),o+=64===s?u(r>>16&255):64===i?u(r>>16&255,r>>8&255):u(r>>16&255,r>>8&255,255&r);return o};let g="function"==typeof atob?e=>atob(F(e)):o?e=>Buffer.from(e,"base64").toString("binary"):c,Y=o?e=>L(Buffer.from(e,"base64")):e=>L(g(e).split("").map(e=>e.charCodeAt(0))),G=e=>Y(W(e)),Q=o?e=>Buffer.from(e,"base64").toString("utf8"):s?e=>s.decode(Y(e)):e=>J(g(e)),W=e=>F(e.replace(/[-_]/g,e=>"-"==e?"+":"/")),w=e=>Q(W(e));function ee(){var e=(e,t)=>Object.defineProperty(String.prototype,e,re(t));e("fromBase64",function(){return w(this)}),e("toBase64",function(e){return f(this,e)}),e("toBase64URI",function(){return f(this,!0)}),e("toBase64URL",function(){return f(this,!0)}),e("toUint8Array",function(){return G(this)})}function te(){var e=(e,t)=>Object.defineProperty(Uint8Array.prototype,e,re(t));e("toBase64",function(e){return p(this,e)}),e("toBase64URI",function(){return p(this,!0)}),e("toBase64URL",function(){return p(this,!0)})}let re=e=>({value:e,enumerable:!1,writable:!0,configurable:!0});let oe={version:r,VERSION:"3.7.7",atob:g,atobPolyfill:c,btoa:i,btoaPolyfill:N,fromBase64:w,toBase64:f,encode:f,encodeURI:X,encodeURL:X,utob:$,btou:J,decode:w,isValid:e=>"string"==typeof e&&(e=e.replace(/\s+/g,"").replace(/={0,2}$/,""),!/[^\s0-9a-zA-Z\+/]/.test(e)||!/[^\s0-9a-zA-Z\-_]/.test(e)),fromUint8Array:p,toUint8Array:G,extendString:ee,extendUint8Array:te,extendBuiltins:()=>{ee(),te()}};var se,ie,ne="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function ae(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var le,ue,he,_,m,de,v,pe,y,fe,ce,b,U,S={};function ge(){var i;return le||(le=1,i=Object.prototype.hasOwnProperty,S.stringify=function(e,t){var r,o,s=[];for(o in"string"!=typeof(t=t||"")&&(t="?"),e)i.call(e,o)&&((r=e[o])||null!=r&&!isNaN(r)||(r=""),o=a(o),r=a(r),null!==o)&&null!==r&&s.push(o+"="+r);return s.length?t+s.join("&"):""},S.parse=function(e){for(var t=/([^=?#&]+)=?([^&]*)/g,r={};s=t.exec(e);){var o=n(s[1]),s=n(s[2]);null===o||null===s||o in r||(r[o]=s)}return r}),S;function n(e){try{return decodeURIComponent(e.replace(/\+/g," "))}catch(e){return null}}function a(e){try{return encodeURIComponent(e)}catch(e){return null}}}function E(e){return(e||"").toString().replace(de,"")}function we(e){var t,r="undefined"!=typeof window?window:void 0!==ne?ne:"undefined"!=typeof self?self:{},r=r.location||{},o={},r=typeof(e=e||r);if("blob:"===e.protocol)o=new x(unescape(e.pathname),{});else if("string"==r)for(t in o=new x(e,{}),U)delete o[t];else if("object"==r){for(t in e)t in U||(o[t]=e[t]);void 0===o.slashes&&(o.slashes=pe.test(e.href))}return o}function R(e){return"file:"===e||"ftp:"===e||"http:"===e||"https:"===e||"ws:"===e||"wss:"===e}function _e(e,t){e=(e=E(e)).replace(v,""),t=t||{};var r,e=fe.exec(e),o=e[1]?e[1].toLowerCase():"",s=!!e[2],i=!!e[3],n=0;return s?n=i?(r=e[2]+e[3]+e[4],e[2].length+e[3].length):(r=e[2]+e[4],e[2].length):i?(r=e[3]+e[4],n=e[3].length):r=e[4],"file:"===o?2<=n&&(r=r.slice(2)):R(o)?r=e[4]:o?s&&(r=r.slice(2)):2<=n&&R(t.protocol)&&(r=e[4]),{protocol:o,slashes:s||R(o),slashesCount:n,rest:r}}function x(e,t,r){if(e=(e=E(e)).replace(v,""),!(this instanceof x))return new x(e,t,r);var o,s,i,n,a,l=b.slice(),u=typeof t,h=this,d=0;for("object"!=u&&"string"!=u&&(r=t,t=null),r&&"function"!=typeof r&&(r=m.parse),o=!(u=_e(e||"",t=we(t))).protocol&&!u.slashes,h.slashes=u.slashes||o&&t.slashes,h.protocol=u.protocol||t.protocol||"",e=u.rest,("file:"===u.protocol&&(2!==u.slashesCount||ce.test(e))||!u.slashes&&(u.protocol||u.slashesCount<2||!R(h.protocol)))&&(l[3]=[/(.*)/,"pathname"]);d<l.length;d++)"function"==typeof(i=l[d])?e=i(e,h):(s=i[0],a=i[1],s!=s?h[a]=e:"string"==typeof s?~(n="@"===s?e.lastIndexOf(s):e.indexOf(s))&&(e="number"==typeof i[2]?(h[a]=e.slice(0,n),e.slice(n+i[2])):(h[a]=e.slice(n),e.slice(0,n))):(n=s.exec(e))&&(h[a]=n[1],e=e.slice(0,n.index)),h[a]=h[a]||o&&i[3]&&t[a]||"",i[4]&&(h[a]=h[a].toLowerCase()));r&&(h.query=r(h.query)),o&&t.slashes&&"/"!==h.pathname.charAt(0)&&(""!==h.pathname||""!==t.pathname)&&(h.pathname=((e,t)=>{if(""===e)return t;for(var r=(t||"/").split("/").slice(0,-1).concat(e.split("/")),o=r.length,t=r[o-1],s=!1,i=0;o--;)"."===r[o]?r.splice(o,1):".."===r[o]?(r.splice(o,1),i++):i&&(0===o&&(s=!0),r.splice(o,1),i--);return s&&r.unshift(""),"."!==t&&".."!==t||r.push(""),r.join("/")})(h.pathname,t.pathname)),"/"!==h.pathname.charAt(0)&&R(h.protocol)&&(h.pathname="/"+h.pathname),_(h.port,h.protocol)||(h.host=h.hostname,h.port=""),h.username=h.password="",h.auth&&(~(n=h.auth.indexOf(":"))?(h.username=h.auth.slice(0,n),h.username=encodeURIComponent(decodeURIComponent(h.username)),h.password=h.auth.slice(n+1),h.password=encodeURIComponent(decodeURIComponent(h.password))):h.username=encodeURIComponent(decodeURIComponent(h.auth)),h.auth=h.password?h.username+":"+h.password:h.username),h.origin="file:"!==h.protocol&&R(h.protocol)&&h.host?h.protocol+"//"+h.host:"null",h.href=h.toString()}he||(he=1,ie||(ie=1,se=function(e,t){if(t=t.split(":")[0],!(e=+e))return!1;switch(t){case"http":case"ws":return 80!==e;case"https":case"wss":return 443!==e;case"ftp":return 21!==e;case"gopher":return 70!==e;case"file":return!1}return 0!==e}),_=se,m=ge(),de=/^[\x00-\x20\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/,v=/[\n\r\t]/g,pe=/^[A-Za-z][A-Za-z0-9+-.]*:\/\//,y=/:\d+$/,fe=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\\/]+)?([\S\s]*)/i,ce=/^[a-zA-Z]:/,b=[["#","hash"],["?","query"],function(e,t){return R(t.protocol)?e.replace(/\\/g,"/"):e},["/","pathname"],["@","auth",1],[NaN,"host",void 0,1,1],[/:(\d*)$/,"port",void 0,1],[NaN,"hostname",void 0,1,1]],U={hash:1,query:1},x.prototype={set:function(e,t,r){var o=this;switch(e){case"query":"string"==typeof t&&t.length&&(t=(r||m.parse)(t)),o[e]=t;break;case"port":o[e]=t,_(t,o.protocol)?t&&(o.host=o.hostname+":"+t):(o.host=o.hostname,o[e]="");break;case"hostname":o[e]=t,o.port&&(t+=":"+o.port),o.host=t;break;case"host":o[e]=t,y.test(t)?(t=t.split(":"),o.port=t.pop(),o.hostname=t.join(":")):(o.hostname=t,o.port="");break;case"protocol":o.protocol=t.toLowerCase(),o.slashes=!r;break;case"pathname":case"hash":t?(s="pathname"===e?"/":"#",o[e]=t.charAt(0)!==s?s+t:t):o[e]=t;break;case"username":case"password":o[e]=encodeURIComponent(t);break;case"auth":var s=t.indexOf(":");~s?(o.username=t.slice(0,s),o.username=encodeURIComponent(decodeURIComponent(o.username)),o.password=t.slice(s+1),o.password=encodeURIComponent(decodeURIComponent(o.password))):o.username=encodeURIComponent(decodeURIComponent(t))}for(var i=0;i<b.length;i++){var n=b[i];n[4]&&(o[n[1]]=o[n[1]].toLowerCase())}return o.auth=o.password?o.username+":"+o.password:o.username,o.origin="file:"!==o.protocol&&R(o.protocol)&&o.host?o.protocol+"//"+o.host:"null",o.href=o.toString(),o},toString:function(e){e&&"function"==typeof e||(e=m.stringify);var t=this,r=t.host,o=((o=t.protocol)&&":"!==o.charAt(o.length-1)&&(o+=":"),o+(t.protocol&&t.slashes||R(t.protocol)?"//":""));return t.username?(o+=t.username,t.password&&(o+=":"+t.password),o+="@"):t.password?o=o+(":"+t.password)+"@":"file:"!==t.protocol&&R(t.protocol)&&!r&&"/"!==t.pathname&&(o+="@"),(":"===r[r.length-1]||y.test(t.hostname)&&!t.port)&&(r+=":"),o+=r+t.pathname,(r="object"==typeof t.query?e(t.query):t.query)&&(o+="?"!==r.charAt(0)?"?"+r:r),t.hash&&(o+=t.hash),o}},x.extractProtocol=_e,x.location=we,x.trimLeft=E,x.qs=m,ue=x);var me=ae(ue);class ve{constructor(e,t){this.intervalId=null,this.lastProgressTime=0,this.lastProgressValue=0,this.isActive=!1,this.options=e,this.onStallDetected=t}start(e){this.intervalId||(this.lastProgressTime=Date.now(),this.lastProgressValue=null!=e?e:0,this.isActive=!0,h(`tus: starting stall detection with checkInterval: ${this.options.checkInterval}ms, stallTimeout: ${this.options.stallTimeout}ms`),this.intervalId=setInterval(()=>{var e;this.isActive&&(e=Date.now(),this._isProgressStalled(e))&&this._handleStall("no progress")},this.options.checkInterval))}stop(){this.isActive=!1,this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null)}updateProgress(e){e!==this.lastProgressValue&&(this.lastProgressTime=Date.now(),this.lastProgressValue=e)}_isProgressStalled(e){var e=e-this.lastProgressTime,t=this.options.stallTimeout,r=t<e;return r&&h(`tus: no progress for ${e}ms (limit: ${t}ms)`),r}_handleStall(e){h("tus: upload stalled: "+e),this.stop(),this.onStallDetected(e)}}let A="tus-v1",D="ietf-draft-03",P="ietf-draft-05";var ye,be,o={endpoint:void 0,uploadUrl:void 0,metadata:{},metadataForPartialUploads:{},fingerprint:void 0,uploadSize:void 0,onProgress:void 0,onChunkComplete:void 0,onSuccess:void 0,onError:void 0,onUploadUrlAvailable:void 0,overridePatchMethod:!1,headers:{},addRequestId:!1,onBeforeRequest:void 0,onAfterResponse:void 0,onShouldRetry:Ae,chunkSize:Number.POSITIVE_INFINITY,retryDelays:[0,1e3,3e3,5e3],parallelUploads:1,parallelUploadBoundaries:void 0,storeFingerprintForResuming:!0,removeFingerprintOnSuccess:!1,uploadLengthDeferred:!1,uploadDataDuringCreation:!1,urlStorage:void 0,fileReader:void 0,httpStack:void 0,protocol:A,stallDetection:{enabled:!1,stallTimeout:3e4,checkInterval:5e3}};class Ue{constructor(e,t){this.url=null,this._fingerprint=null,this._offset=0,this._aborted=!1,this._size=null,this._retryAttempt=0,this._offsetBeforeRetry=0,"resume"in t&&console.log("tus: The `resume` option has been removed in tus-js-client v2. Please use the URL storage API instead."),this.options=t,this.options.chunkSize=Number(this.options.chunkSize),this._uploadLengthDeferred=this.options.uploadLengthDeferred,this.file=e}async findPreviousUploads(){var e=await this.options.fingerprint(this.file,this.options);if(e)return this.options.urlStorage.findUploadsByFingerprint(e);throw new Error("tus: unable to calculate fingerprint for this input file")}resumeFromPreviousUpload(e){this.url=e.uploadUrl||null,this._parallelUploadUrls=e.parallelUploadUrls,this._urlStorageKey=e.urlStorageKey}start(){if(this.file)if([A,D,P].includes(this.options.protocol))if(this.options.endpoint||this.options.uploadUrl||this.url){var e=this.options.retryDelays;if(null!=e&&"[object Array]"!==Object.prototype.toString.call(e))this._emitError(new Error("tus: the `retryDelays` option must either be an array or null"));else{if(1<this.options.parallelUploads){if(null!=this.options.uploadUrl)return void this._emitError(new Error("tus: cannot use the `uploadUrl` option when parallelUploads is enabled"));if(null!=this.options.uploadSize)return void this._emitError(new Error("tus: cannot use the `uploadSize` option when parallelUploads is enabled"));if(this._uploadLengthDeferred)return void this._emitError(new Error("tus: cannot use the `uploadLengthDeferred` option when parallelUploads is enabled"))}if(this.options.parallelUploadBoundaries){if(this.options.parallelUploads<=1)return void this._emitError(new Error("tus: cannot use the `parallelUploadBoundaries` option when `parallelUploads` is disabled"));if(this.options.parallelUploads!==this.options.parallelUploadBoundaries.length)return void this._emitError(new Error("tus: the `parallelUploadBoundaries` must have the same length as the value of `parallelUploads`"))}this._prepareAndStartUpload().catch(e=>{if(!(e instanceof Error))throw new Error("tus: value thrown that is not an error: "+e);this._retryOrEmitError(e)})}}else this._emitError(new Error("tus: neither an endpoint or an upload URL is provided"));else this._emitError(new Error("tus: unsupported protocol "+this.options.protocol));else this._emitError(new Error("tus: no file or stream to upload provided"))}async _prepareAndStartUpload(){if(this._fingerprint=await this.options.fingerprint(this.file,this.options),null==this._fingerprint?h("No fingerprint was calculated meaning that the upload cannot be stored in the URL storage."):h("Calculated fingerprint: "+this._fingerprint),null==this._source&&(this._source=await this.options.fileReader.openFile(this.file,this.options.chunkSize)),this._uploadLengthDeferred)this._size=null;else if(null!=this.options.uploadSize){if(this._size=Number(this.options.uploadSize),Number.isNaN(this._size))throw new Error("tus: cannot convert `uploadSize` option into a number")}else if(this._size=this._source.size,null==this._size)throw new Error("tus: cannot automatically derive upload's size from input. Specify it manually using the `uploadSize` option or use the `uploadLengthDeferred` option");1<this.options.parallelUploads||null!=this._parallelUploadUrls?await this._startParallelUpload():await this._startSingleUpload()}async _startParallelUpload(){let e,a=this._size,l=0;this._parallelUploads=[];var t=null!=this._parallelUploadUrls?this._parallelUploadUrls.length:this.options.parallelUploads;if(null==this._size)throw new Error("tus: Expected _size to be set");let u=(null!=(e=this.options.parallelUploadBoundaries)?e:((e,t)=>{var r=Math.floor(e/t),o=[];for(let e=0;e<t;e++)o.push({start:r*e,end:r*(e+1)});return o[t-1].end=e,o})(this._size,t)).map((e,t)=>({...e,uploadUrl:(null==(e=this._parallelUploadUrls)?void 0:e[t])||null}));this._parallelUploadUrls=new Array(u.length);t=u.map(async(o,s)=>{let i=0,n=(await this._source.slice(o.start,o.end)).value;return new Promise((e,t)=>{e={...this.options,uploadUrl:o.uploadUrl||null,storeFingerprintForResuming:!1,removeFingerprintOnSuccess:!1,parallelUploads:1,parallelUploadBoundaries:null,metadata:this.options.metadataForPartialUploads,headers:{...this.options.headers,"Upload-Concat":"partial"},onSuccess:e,onError:t,onProgress:e=>{if(l=l-i+e,i=e,null==a)throw new Error("tus: Expected totalSize to be set");this._emitProgress(l,a)},onUploadUrlAvailable:async()=>{this._parallelUploadUrls[s]=r.url,this._parallelUploadUrls.filter(e=>Boolean(e)).length===u.length&&await this._saveUploadInUrlStorage()}};if(null==n)return void t(new Error("tus: no value returned while slicing file for parallel uploads"));let r=new Ue(n,e);r.start(),this._parallelUploads.push(r)})});if(await Promise.all(t),null==this.options.endpoint)throw new Error("tus: Expected options.endpoint to be set");var t=this._openRequest("POST",this.options.endpoint),r=(t.setHeader("Upload-Concat","final;"+this._parallelUploadUrls.join(" ")),Se(this.options.metadata));""!==r&&t.setHeader("Upload-Metadata",r);let o;try{o=await this._sendRequest(t)}catch(e){if(e instanceof Error)throw new n("tus: failed to concatenate parallel uploads",e,t,void 0);throw new Error("tus: value thrown that is not an error: "+e)}if(!C(o.getStatus(),200))throw new n("tus: unexpected response while creating upload",void 0,t,o);r=o.getHeader("Location");if(null==r)throw new n("tus: invalid or missing Location header",void 0,t,o);if(null==this.options.endpoint)throw new Error("tus: Expeced endpoint to be defined.");this.url=De(this.options.endpoint,r),h("Created upload at "+this.url),await this._emitSuccess(o)}async _startSingleUpload(){return this._aborted=!1,null!=this.url?(h("Resuming upload from previous URL: "+this.url),this._resumeUpload()):null!=this.options.uploadUrl?(h("Resuming upload from provided URL: "+this.options.uploadUrl),this.url=this.options.uploadUrl,this._resumeUpload()):(h("Creating a new upload"),this._createUpload())}async abort(e=!1){if(this._aborted=!0,null!=this._parallelUploads)for(var t of this._parallelUploads)await t.abort(e);null!=this._req&&await this._req.abort(),null!=this._retryTimeout&&(clearTimeout(this._retryTimeout),this._retryTimeout=void 0),e&&null!=this.url&&(await z(this.url,this.options),await this._removeFromUrlStorage())}_emitError(e){if(!this._aborted){if("function"!=typeof this.options.onError)throw e;this.options.onError(e)}}_retryOrEmitError(e){if(!this._aborted){var t;if(null!=this.options.retryDelays)if(null!=this._offset&&this._offset>this._offsetBeforeRetry&&(this._retryAttempt=0),xe(e,this._retryAttempt,this.options))return t=this.options.retryDelays[this._retryAttempt++],this._offsetBeforeRetry=this._offset,void(this._retryTimeout=setTimeout(()=>{this.start()},t));this._emitError(e)}}async _emitSuccess(e){this.options.removeFingerprintOnSuccess&&await this._removeFromUrlStorage(),"function"==typeof this.options.onSuccess&&this.options.onSuccess({lastResponse:e})}_emitProgress(e,t){"function"==typeof this.options.onProgress&&this.options.onProgress(e,t)}_emitChunkComplete(e,t,r){"function"==typeof this.options.onChunkComplete&&this.options.onChunkComplete(e,t,r)}async _createUpload(){if(!this.options.endpoint)throw new Error("tus: unable to create upload because no endpoint is provided");var t=this._openRequest("POST",this.options.endpoint);if(this._uploadLengthDeferred)t.setHeader("Upload-Defer-Length","1");else{if(null==this._size)throw new Error("tus: expected _size to be set");t.setHeader("Upload-Length",""+this._size)}var e=Se(this.options.metadata);""!==e&&t.setHeader("Upload-Metadata",e);let r;try{r=this.options.uploadDataDuringCreation&&!this._uploadLengthDeferred?(this._offset=0,await this._addChunkToRequest(t)):(this.options.protocol!==D&&this.options.protocol!==P||t.setHeader("Upload-Complete","?0"),await this._sendRequest(t))}catch(e){if(e instanceof Error)throw new n("tus: failed to create upload",e,t,void 0);throw new Error("tus: value thrown that is not an error: "+e)}if(!C(r.getStatus(),200))throw new n("tus: unexpected response while creating upload",void 0,t,r);e=r.getHeader("Location");if(null==e)throw new n("tus: invalid or missing Location header",void 0,t,r);if(null==this.options.endpoint)throw new Error("tus: Expected options.endpoint to be set");this.url=De(this.options.endpoint,e),h("Created upload at "+this.url),"function"==typeof this.options.onUploadUrlAvailable&&await this.options.onUploadUrlAvailable(),0===this._size?(await this._emitSuccess(r),this._source&&this._source.close()):(await this._saveUploadInUrlStorage(),this.options.uploadDataDuringCreation?await this._handleUploadResponse(t,r):(this._offset=0,await this._performUpload()))}async _resumeUpload(){if(null==this.url)throw new Error("tus: Expected url to be set");var t=this._openRequest("HEAD",this.url);let e;try{e=await this._sendRequest(t)}catch(e){if(e instanceof Error)throw new n("tus: failed to resume upload",e,t,void 0);throw new Error("tus: value thrown that is not an error: "+e)}var r=e.getStatus();if(!C(r,200)){if(423===r)throw new n("tus: upload is currently locked; retry later",void 0,t,e);if(C(r,400)&&await this._removeFromUrlStorage(),!this.options.endpoint)throw new n("tus: unable to resume upload (new upload cannot be created without an endpoint)",void 0,t,e);this.url=null,await this._createUpload()}r=e.getHeader("Upload-Offset");if(void 0===r)throw new n("tus: missing Upload-Offset header",void 0,t,e);r=Number.parseInt(r,10);if(Number.isNaN(r))throw new n("tus: invalid Upload-Offset header",void 0,t,e);var o=e.getHeader("Upload-Defer-Length"),o=(this._uploadLengthDeferred="1"===o,Number.parseInt(e.getHeader("Upload-Length"),10));if(Number.isNaN(o)&&!this._uploadLengthDeferred&&this.options.protocol===A)throw new n("tus: invalid or missing length value",void 0,t,e);"function"==typeof this.options.onUploadUrlAvailable&&await this.options.onUploadUrlAvailable(),await this._saveUploadInUrlStorage(),r===o?(this._emitProgress(o,o),await this._emitSuccess(e)):(this._offset=r,await this._performUpload())}async _performUpload(){if(!this._aborted){let t;if(null==this.url)throw new Error("tus: Expected url to be set");this.options.overridePatchMethod?(t=this._openRequest("POST",this.url)).setHeader("X-HTTP-Method-Override","PATCH"):t=this._openRequest("PATCH",this.url),t.setHeader("Upload-Offset",""+this._offset);let e;try{e=await this._addChunkToRequest(t)}catch(e){if(this._aborted)return;var r;if(e instanceof Error)throw r=this._stallReason?`tus: failed to upload chunk at offset ${this._offset} (stalled: ${this._stallReason})`:"tus: failed to upload chunk at offset "+this._offset,this._stallReason=void 0,new n(r,e,t,void 0);throw new Error("tus: value thrown that is not an error: "+e)}if(!C(e.getStatus(),200))throw new n("tus: unexpected response while uploading chunk",void 0,t,e);await this._handleUploadResponse(t,e)}}async _addChunkToRequest(e){let t,r=this._offset,o=this._offset+this.options.chunkSize,s;null!=(t=this.options.stallDetection)&&t.enabled&&(this.options.httpStack.supportsProgressEvents()?s=new ve(this.options.stallDetection,e=>{this._req&&(this._stallReason=e,this._req.abort())}):h("tus: stall detection is enabled but the HTTP stack does not support progress events, it will be disabled for this upload")),e.setProgressHandler(e=>{s&&s.updateProgress(r+e),this._emitProgress(r+e,this._size)}),this.options.protocol===A?e.setHeader("Content-Type","application/offset+octet-stream"):this.options.protocol===P&&e.setHeader("Content-Type","application/partial-upload"),(o===Number.POSITIVE_INFINITY||o>this._size)&&!this._uploadLengthDeferred&&(o=this._size);var{value:i,size:n,done:a}=await this._source.slice(r,o),n=null!=n?n:0,n=(this._uploadLengthDeferred&&a&&(this._size=this._offset+n,e.setHeader("Upload-Length",""+this._size),this._uploadLengthDeferred=!1),this._offset+n);if(!this._uploadLengthDeferred&&a&&n!==this._size)throw new Error(`upload was configured with a size of ${this._size} bytes, but the source is done after ${n} bytes`);return null==i?this._sendRequest(e,void 0,s):(this.options.protocol!==D&&this.options.protocol!==P||e.setHeader("Upload-Complete",a?"?1":"?0"),this._sendRequest(e,i,s))}async _handleUploadResponse(e,t){var r=Number.parseInt(t.getHeader("Upload-Offset")||"",10);if(Number.isNaN(r))throw new n("tus: invalid or missing offset value",void 0,e,t);this._emitProgress(r,this._size),this._emitChunkComplete(r-this._offset,r,this._size),(this._offset=r)===this._size?(await this._emitSuccess(t),this._source&&this._source.close()):await this._performUpload()}_openRequest(e,t){e=Ee(e,t,this.options);return this._req=e}async _removeFromUrlStorage(){this._urlStorageKey&&(await this.options.urlStorage.removeUpload(this._urlStorageKey),this._urlStorageKey=void 0)}async _saveUploadInUrlStorage(){var e;this.options.storeFingerprintForResuming&&this._fingerprint&&null==this._urlStorageKey&&(e={size:this._size,metadata:this.options.metadata,creationTime:(new Date).toString(),urlStorageKey:this._fingerprint},this._parallelUploads?e.parallelUploadUrls=this._parallelUploadUrls:e.uploadUrl=this.url,e=await this.options.urlStorage.addUpload(this._fingerprint,e),this._urlStorageKey=e)}_sendRequest(e,t,r){return Re(e,t,this.options,r,this._offset)}}function Se(e){return Object.entries(e).map(([e,t])=>e+" "+oe.encode(String(t))).join(",")}function C(e,t){return t<=e&&e<t+100}function Ee(e,t,r){var o,s,i=r.httpStack.createRequest(e,t),e=(r.protocol===D?i.setHeader("Upload-Draft-Interop-Version","5"):r.protocol===P?i.setHeader("Upload-Draft-Interop-Version","6"):i.setHeader("Tus-Resumable","1.0.0"),r.headers||{});for([o,s]of Object.entries(e))i.setHeader(o,s);return r.addRequestId&&(t="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{var t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)}),i.setHeader("X-Request-ID",t)),i}async function Re(e,t,r,o,s){"function"==typeof r.onBeforeRequest&&await r.onBeforeRequest(e);var i=await(async()=>{o&&o.start(s);try{return await e.send(t)}finally{o&&o.stop()}})();return"function"==typeof r.onAfterResponse&&await r.onAfterResponse(e,i),i}function xe(e,t,r){var o="originalRequest"in e&&null!=e.originalRequest;return!(null==r.retryDelays||t>=r.retryDelays.length)&&o&&(r&&"function"==typeof r.onShouldRetry?r.onShouldRetry(e,t,r):Ae(e))}function Ae(e){e=e.originalResponse?e.originalResponse.getStatus():0;return(!C(e,400)||409===e||423===e)&&(()=>{let e=!0;return e="undefined"!=typeof navigator&&!1===navigator.onLine?!1:e})()}function De(e,t){return new me(t,e).toString()}async function z(t,r){var o,s=Ee("DELETE",t,r);try{var i=await Re(s,void 0,r);if(204!==i.getStatus())throw new n("tus: unexpected response while terminating upload",void 0,s,i)}catch(e){if(!(e instanceof Error))throw new Error("tus: value thrown that is not an error: "+e);i=e instanceof n?e:new n("tus: failed to terminate upload",e,s);if(!xe(i,0,r))throw i;s=r.retryDelays[0],i=r.retryDelays.slice(1),r={...r,retryDelays:i};o=s,await new Promise(e=>{setTimeout(e,o)}),await z(t,r)}}function Pe(){return"undefined"!=typeof navigator&&"string"==typeof navigator.product&&"reactnative"===navigator.product.toLowerCase()}function Ce(e){return null!=e&&"object"==typeof e&&"uri"in e&&"string"==typeof e.uri}class ze{constructor(e){this._view=e,this.size=e.byteLength}slice(e,t){var r=this._view.buffer,o=this._view.byteOffset+e,e=(t=Math.min(t,this.size))-e,r=new DataView(r,o,e),o=r.byteLength,e=t>=this.size;return Promise.resolve({value:r,size:o,done:e})}close(){}}class Be{constructor(e){this._file=e,this.size=e.size}async slice(o,s){if("undefined"!=typeof window&&("PhoneGap"in window||"Cordova"in window||"cordova"in window)){i=this._file.slice(o,s);let e=await new Promise((t,r)=>{let o=new FileReader;o.onload=()=>{var e;o.result instanceof ArrayBuffer?(e=new Uint8Array(o.result),t(e)):r(new Error("invalid result types for readAsArrayBuffer: "+typeof o.result))},o.onerror=e=>{r(e)},o.readAsArrayBuffer(i)}),t=e.length,r=s>=this.size;return{value:e,size:t,done:r}}var i;let e=this._file.slice(o,s),t=e.size,r=s>=this.size;return{value:e,size:t,done:r}}close(){}}function B(e){return void 0===e?0:e instanceof Blob?e.size:e.length}class Ie{constructor(e){if(this._bufferOffset=0,this._done=!1,this.size=null,e.locked)throw new Error("Readable stream is already locked to reader. tus-js-client cannot obtain a new reader.");this._reader=e.getReader()}async slice(e,t){if(e<this._bufferOffset)throw new Error("Requested data is before the reader's current offset");return this._readUntilEnoughDataOrDone(e,t)}async _readUntilEnoughDataOrDone(r,o){var s=o<=this._bufferOffset+B(this._buffer);if(this._done||s){let e=this._getDataFromBuffer(r,o);if(null===e)return{value:null,size:null,done:!0};var s=e instanceof Blob?e.size:e.length;let t=this._done;return{value:e,size:s,done:t}}let{value:e,done:t}=await this._reader.read();return t?this._done=!0:(s=B(e),this._bufferOffset+B(this._buffer)+s<r?(this._buffer=void 0,this._bufferOffset+=s):void 0===this._buffer?this._buffer=e:this._buffer=((e,t)=>{if(e instanceof Blob&&t instanceof Blob)return new Blob([e,t],{type:e.type});var r;if(e instanceof Uint8Array&&t instanceof Uint8Array)return(r=new Uint8Array(e.length+t.length)).set(e),r.set(t,e.length),r;throw new Error("Unknown data type")})(this._buffer,e)),this._readUntilEnoughDataOrDone(r,o)}_getDataFromBuffer(e,t){if(void 0===this._buffer)throw new Error("cannot _getDataFromBuffer because _buffer is unset");e>this._bufferOffset&&(this._buffer=this._buffer.slice(e-this._bufferOffset),this._bufferOffset=e);var r=0===B(this._buffer);return this._done&&r?null:this._buffer.slice(0,t-e)}close(){this._reader.cancel()}}let Te=["File","Blob","ArrayBuffer","SharedArrayBuffer","ArrayBufferView","ReadableStream (Web Streams)"];class He{async openFile(e,t){if(Ce(e)){if(!Pe())throw new Error("tus: file objects with `uri` property is only supported in React Native");try{s=e.uri;var r=await new Promise((t,r)=>{let o=new XMLHttpRequest;o.responseType="blob",o.onload=()=>{var e=o.response;t(e)},o.onerror=e=>{r(e)},o.open("GET",s),o.send()});return new Be(r)}catch(e){throw new Error("tus: cannot fetch `file.uri` as Blob, make sure the uri is correct and accessible. "+e)}}var s,r=((e,t)=>{if(e instanceof Blob)return new Be(e);if(ArrayBuffer.isView(e))return new ze(e);var r;if(e instanceof ArrayBuffer||"undefined"!=typeof SharedArrayBuffer&&e instanceof SharedArrayBuffer)return r=new DataView(e),new ze(r);if(e instanceof ReadableStream){if(t=Number(t),Number.isFinite(t))return new Ie(e);throw new Error("cannot create source for stream without a finite value for the `chunkSize` option")}return null})(e,t);if(r)return r;throw new Error("in this environment the source object may only be an instance of: "+Te.join(", "))}}var Oe=(()=>{if(!be){be=1;let t=e=>null!==e&&"object"==typeof e&&"function"==typeof e.pipe;t.writable=e=>t(e)&&!1!==e.writable&&"function"==typeof e._write&&"object"==typeof e._writableState,t.readable=e=>t(e)&&!1!==e.readable&&"function"==typeof e._read&&"object"==typeof e._readableState,t.duplex=e=>t.writable(e)&&t.readable(e),t.transform=e=>t.duplex(e)&&"function"==typeof e._transform&&"object"==typeof e._transformState,ye=t}return ye})();class qe{createRequest(e,t){return new Le(e,t)}getName(){return"XHRHttpStack"}supportsProgressEvents(){return!0}}class Le{constructor(e,t){this._xhr=new XMLHttpRequest,this._headers={},this._xhr.open(e,t,!0),this._method=e,this._url=t}getMethod(){return this._method}getURL(){return this._url}setHeader(e,t){this._xhr.setRequestHeader(e,t),this._headers[e]=t}getHeader(e){return this._headers[e]}setProgressHandler(t){"upload"in this._xhr&&(this._xhr.upload.onprogress=e=>{e.lengthComputable&&t(e.loaded)})}send(r){if(Oe.readable(r))throw new Error("Using a Node.js readable stream as HTTP request body is not supported using the XMLHttpRequest HTTP stack.");return new Promise((e,t)=>{this._xhr.onload=()=>{e(new ke(this._xhr))},this._xhr.onerror=e=>{t(e)},this._xhr.send(r)})}abort(){return this._xhr.abort(),Promise.resolve()}getUnderlyingObject(){return this._xhr}}class ke{constructor(e){this._xhr=e}getStatus(){return this._xhr.status}getHeader(e){return this._xhr.getResponseHeader(e)||void 0}getBody(){return this._xhr.responseText}getUnderlyingObject(){return this._xhr}}let I=!1;try{I="localStorage"in window;var T="tusSupport",Fe=localStorage.getItem(T);localStorage.setItem(T,String(Fe)),null==Fe&&localStorage.removeItem(T)}catch(e){if(!(e instanceof DOMException)||e.code!==e.SECURITY_ERR&&e.code!==e.QUOTA_EXCEEDED_ERR)throw e;I=!1}r=I;class Ne{constructor(e,t){this._headers={},this._controller=new AbortController,this._method=e,this._url=t}getMethod(){return this._method}getURL(){return this._url}setHeader(e,t){this._headers[e]=t}getHeader(e){return this._headers[e]}setProgressHandler(e){}async send(e){if(Oe.readable(e))throw new Error("Using a Node.js readable stream as HTTP request body is not supported using the Fetch API HTTP stack.");var e=await fetch(this._url,{method:this._method,headers:this._headers,body:e,signal:this._controller.signal}),t=await e.text();return new je(e,t)}abort(){return this._controller.abort(),Promise.resolve()}getUnderlyingObject(){}}class je{constructor(e,t){this._res=e,this._body=t}getStatus(){return this._res.status}getHeader(e){return this._res.headers.get(e)||void 0}getBody(){return this._body}getUnderlyingObject(){return this._res}}let H={...o,httpStack:new qe,fileReader:new He,urlStorage:new(r?class{findAllUploads(){var e=this._findEntries("tus::");return Promise.resolve(e)}findUploadsByFingerprint(e){e=this._findEntries(`tus::${e}::`);return Promise.resolve(e)}removeUpload(e){return localStorage.removeItem(e),Promise.resolve()}addUpload(e,t){e=`tus::${e}::`+Math.round(1e12*Math.random());return localStorage.setItem(e,JSON.stringify(t)),Promise.resolve(e)}_findEntries(t){var r=[];for(let e=0;e<localStorage.length;e++){var o=localStorage.key(e);if(null==o)throw new Error("didn't find key for item "+e);if(0===o.indexOf(t)){var s=localStorage.getItem(o);if(null==s)throw new Error("didn't find item for key "+o);try{var i=JSON.parse(s);i.urlStorageKey=o,r.push(i)}catch(e){}}}return r}}:class{findAllUploads(){return Promise.resolve([])}findUploadsByFingerprint(e){return Promise.resolve([])}removeUpload(e){return Promise.resolve()}addUpload(e,t){return Promise.resolve(void 0)}}),fingerprint:function(e,t){var r,o,s;return Pe()&&Ce(e)?Promise.resolve((o=t,s=(r=e).exif?(t=>{let r=0;if(0!==t.length)for(let e=0;e<t.length;e++){var o=t.charCodeAt(e);r=(r<<5)-r+o,r&=r}return r})(JSON.stringify(r.exif)):"noexif",["tus-rn",r.name||"noname",r.size||"nosize",s,o.endpoint].join("/"))):e instanceof Blob?Promise.resolve(["tus-br",e.name,e.type,e.size,e.lastModified,t.endpoint].join("-")):Promise.resolve(null)}};class Me extends Ue{constructor(e,t={}){super(e,{...H,...t,...t.stallDetection&&{stallDetection:{...H.stallDetection,...t.stallDetection}}})}static terminate(e,t={}){return z(e,{...H,...t,...t.stallDetection&&{stallDetection:{...H.stallDetection,...t.stallDetection}}})}}c="function"==typeof XMLHttpRequest&&"function"==typeof Blob&&"function"==typeof Blob.prototype.slice;e.DetailedError=n,e.FetchHttpStack=class{createRequest(e,t){return new Ne(e,t)}getName(){return"FetchHttpStack"}supportsProgressEvents(){return!1}},e.Upload=Me,e.XHRHttpStack=qe,e.canStoreURLs=r,e.defaultOptions=H,e.enableDebugLog=function(){t=!0},e.isSupported=c}); //# sourceMappingURL=tus.min.js.map