UNPKG

@masvio/uploader

Version:

A simple, lightweight library to easily share files using MASV

734 lines (733 loc) 34.2 kB
var o = /* @__PURE__ */ ((i) => (i.Created = "uploader:create", i.Start = "upload:start", i.Progress = "upload:progress", i.Chunk = "upload:chunk", i.File = "upload:file", i.Error = "upload:error", i.Finished = "upload:finish", i.Finalize = "upload:finalize", i.FileQueued = "upload:file_queued", i.Abort = "upload:abort", i.Retry = "upload:retry", i.Stalled = "upload:stalled", i.FileUnreadable = "upload:file_unreadable", i))(o || {}), u = /* @__PURE__ */ ((i) => (i.Created = "worker:create", i.Execute = "worker:execute", i.Finish = "worker:finish", i.Error = "worker:error", i.Retry = "worker:retry", i.Progress = "worker:progress", i.Terminate = "worker:terminate", i.Abort = "worker:abort", i))(u || {}); class I { constructor() { this.handlers = {}; } on(e, t) { this.handlers[e] || (this.handlers[e] = []), this.handlers[e].push(t); } off(e, t) { if (t == null) { this.handlers[e] = []; return; } this.handlers[e] && (this.handlers[e] = this.handlers[e].filter((s) => s !== t)); } clearHandlers() { this.handlers = {}; } emit(e, t) { const s = { time: Date.now(), event: e, target: this, data: {}, ...t }; this.handlers[e] && this.handlers[e].forEach((r) => { r(s); }), this.handlers.emit != null && this.handlers.emit.forEach((r) => { r(s); }); } bubbleEmit(e) { "event" in e && this.emit(e.event, { ...e }); } } const f = "c2VsZi5hcGlCYXNlVXJsID0gIiI7CnNlbGYucGFja2FnZVRva2VuID0gIiI7CnNlbGYucGFja2FnZUlEID0gIiI7CnNlbGYubWFzdlVzZXJBZ2VudCA9ICIiOwpzZWxmLmNodW5rU2l6ZSA9IDEwMCA8PCAyMDsKc2VsZi5jdXJyZW50UHJvbWlzZSA9IG51bGw7CnNlbGYucHJvbWlzZVBvb2wgPSBbXTsKc2VsZi5vbm1lc3NhZ2UgPSBhc3luYyBmdW5jdGlvbihlKSB7CiAgY29uc3QgeyBuYW1lOiBhLCBpbnB1dDogcywgc3BlYzogbiB9ID0gZS5kYXRhOwogIGEgPT09ICJJbml0IiAmJiAoc2VsZi5wYWNrYWdlVG9rZW4gPSBzLnBhY2thZ2VUb2tlbiwgc2VsZi5hcGlCYXNlVXJsID0gcy5hcGlCYXNlVXJsLCBzZWxmLm1hc3ZVc2VyQWdlbnQgPSBzLm1hc3ZVc2VyQWdlbnQsIHNlbGYucGFja2FnZUlEID0gcy5wYWNrYWdlSUQsIHNlbGYuY2h1bmtTaXplID0gcy5jaHVua1NpemUpLCBhID09PSAiQ2h1bmsiICYmIChzZWxmLnNwZWMgPSBuIHx8IHt9LCB3KHMpKTsKfTsKYXN5bmMgZnVuY3Rpb24gcCgpIHsKICBzZWxmLmN1cnJlbnRQcm9taXNlICE9IG51bGwgfHwgc2VsZi5wcm9taXNlUG9vbC5sZW5ndGggPT09IDAgfHwgKHNlbGYuY3VycmVudFByb21pc2UgPSBzZWxmLnByb21pc2VQb29sLnNoaWZ0KCksIGF3YWl0IHkoc2VsZi5jdXJyZW50UHJvbWlzZSksIHNlbGYuY3VycmVudFByb21pc2UgPSBudWxsLCBwKCkpOwp9CmZ1bmN0aW9uIHcoZSkgewogIHNlbGYucHJvbWlzZVBvb2wucHVzaChlKSwgcCgpOwp9CmFzeW5jIGZ1bmN0aW9uIHkoZSkgewogIHRyeSB7CiAgICBjb25zdCB7IG1heF9jaHVua19jb3VudDogYSwgbWF4X2NodW5rX3NpemU6IHMsIG1pbl9jaHVua19zaXplOiBuIH0gPSBzZWxmLnNwZWM7CiAgICBsZXQgbCA9IDUgKiAyICoqIDIwLCB0ID0gNSAqIDIgKiogMzAsIGkgPSAxZTQ7CiAgICBuICE9IG51bGwgJiYgKGwgPSBuKSwgcyAhPSBudWxsICYmICh0ID0gcyksIGEgIT0gbnVsbCAmJiAoaSA9IGEpOwogICAgbGV0IHIgPSBNYXRoLm1heChsLCBNYXRoLm1pbih0LCBzZWxmLmNodW5rU2l6ZSkpLCBjID0gTWF0aC5jZWlsKGUuZmlsZS5zaXplIC8gcik7CiAgICBjID4gaSAmJiAoYyA9IGksIHIgPSBNYXRoLmNlaWwoZS5maWxlLnNpemUgLyBjKSk7CiAgICBsZXQgbzsKICAgIHIgIT0gc2VsZi5jaHVua1NpemUgJiYgKG8gPSByKTsKICAgIGNvbnN0IHsgZmlsZTogdSwgc3RvcmFnZVR5cGU6IG0sIGNyZWF0ZUJsdWVwcmludDogZyB9ID0gYXdhaXQgTShlLCBvKSwgaCA9IHsgdXBsb2FkSWQ6IGF3YWl0IFAoZykgfSwgeiA9IGF3YWl0IEkodS5pZCwgYywgaCksIFMgPSBhd2FpdCBVKHsKICAgICAgZmlsZTogZS5maWxlLAogICAgICBjaHVua1NpemU6IHIsCiAgICAgIGJsdWVwcmludHM6IHoKICAgIH0pLCBrID0gewogICAgICBmaWxlOiBlLAogICAgICBmaWxlSWQ6IHUuaWQsCiAgICAgIHN0b3JhZ2VUeXBlOiBtLAogICAgICBmaWxlRXh0cmFzOiBoLAogICAgICAuLi5TLAogICAgICBjaHVua1NpemU6IHIKICAgIH07CiAgICByZXR1cm4gc2VsZi5wb3N0TWVzc2FnZSh7IG5hbWU6ICJ3b3JrZXI6ZmluaXNoIiwgZGF0YTogayB9KSwgazsKICB9IGNhdGNoIChhKSB7CiAgICByZXR1cm4gc2VsZi5wb3N0TWVzc2FnZSh7IG5hbWU6ICJ3b3JrZXI6ZXJyb3IiLCBkYXRhOiB7IGlucHV0OiBlLCBlcnJvcjogYSB9IH0pLCBhOwogIH0KfQphc3luYyBmdW5jdGlvbiBmKGUgPSAiIiwgYSwgcyA9IHt9LCBuID0gIlBPU1QiLCBsID0gITEsIHQgPSAwKSB7CiAgbGV0IGk7CiAgdHJ5IHsKICAgIGkgPSBhd2FpdCBmZXRjaChlLCB7CiAgICAgIG1ldGhvZDogbiwKICAgICAgaGVhZGVyczogewogICAgICAgICJDb250ZW50LVR5cGUiOiAiYXBwbGljYXRpb24vanNvbiIsCiAgICAgICAgIlgtUGFja2FnZS1Ub2tlbiI6IHNlbGYucGFja2FnZVRva2VuLAogICAgICAgICJNYXN2LVVzZXItQWdlbnQiOiBzZWxmLm1hc3ZVc2VyQWdlbnQsCiAgICAgICAgLi4ucwogICAgICB9LAogICAgICBib2R5OiBhCiAgICB9KTsKICB9IGNhdGNoIHsKICAgIHJldHVybiBkKGUsIGEsIHMsIG4sIGwsIHQpOwogIH0KICBjb25zdCByID0gbCA/IGF3YWl0IGkudGV4dCgpIDogYXdhaXQgaS5qc29uKCk7CiAgaWYgKGkub2spCiAgICByZXR1cm4gcjsKICBpZiAoaS5zdGF0dXMgPj0gNTAwKQogICAgcmV0dXJuIGQoZSwgYSwgcywgbiwgbCwgdCk7CiAgdGhyb3cgbmV3IEVycm9yKHIpOwp9CmFzeW5jIGZ1bmN0aW9uIGQoZSA9ICIiLCBhLCBzID0ge30sIG4gPSAiUE9TVCIsIGwgPSAhMSwgdCA9IDApIHsKICByZXR1cm4gdCArPSAxLCBhd2FpdCBuZXcgUHJvbWlzZSgoaSkgPT4gewogICAgc2V0VGltZW91dCgoKSA9PiB7CiAgICAgIGkoKTsKICAgIH0sIE1hdGgubWluKHQsIDUpICogMWUzKTsKICB9KSwgZihlLCBhLCBzLCBuLCBsLCB0KTsKfQphc3luYyBmdW5jdGlvbiBNKGUsIGEpIHsKICBsZXQgczsKICByZXR1cm4gZS5maWxlLmxhc3RNb2RpZmllZCA/IHMgPSBuZXcgRGF0ZShlLmZpbGUubGFzdE1vZGlmaWVkKSA6IGUuZmlsZS5sYXN0TW9kaWZpZWREYXRlICYmIChzID0gZS5maWxlLmxhc3RNb2RpZmllZERhdGUpLCBmKAogICAgYCR7c2VsZi5hcGlCYXNlVXJsfS92MS9wYWNrYWdlcy8ke3NlbGYucGFja2FnZUlEfS9maWxlc2AsCiAgICBKU09OLnN0cmluZ2lmeSh7CiAgICAgIG5hbWU6IGUuZmlsZS5uYW1lLAogICAgICBsYXN0X21vZGlmaWVkOiBzLAogICAgICBwYXRoOiBlLnBhdGgsCiAgICAgIHNpemU6IGUuZmlsZS5zaXplLAogICAgICBjaHVua19zaXplOiBhCiAgICB9KQogICk7Cn0KYXN5bmMgZnVuY3Rpb24gUCh7IHVybDogZSwgYm9keTogYSwgaGVhZGVyczogcywgbWV0aG9kOiBuIH0pIHsKICBjb25zdCB0ID0gKGF3YWl0IGYoZSwgYSwgcywgbiwgITApKS5zcGxpdCgiVXBsb2FkSWQiKVsxXTsKICByZXR1cm4gdC5zdWJzdHJpbmcoMSwgdC5sZW5ndGggLSAyKTsKfQphc3luYyBmdW5jdGlvbiBJKGUsIGEsIHMpIHsKICByZXR1cm4gZigKICAgIGAke3NlbGYuYXBpQmFzZVVybH0vdjEvcGFja2FnZXMvJHtzZWxmLnBhY2thZ2VJRH0vZmlsZXMvJHtlfT9zdGFydD0wJmNvdW50PSR7YX1gLAogICAgSlNPTi5zdHJpbmdpZnkocykKICApOwp9CmFzeW5jIGZ1bmN0aW9uIFUoZSkgewogIGNvbnN0IGEgPSB7IHJlcTogZSwgY2h1bmtzOiBbXSB9LCBzID0gZS5jaHVua1NpemUsIG4gPSBlLmZpbGUuc2l6ZTsKICBsZXQgbCA9IDAsIHQgPSBuOwogIGZvciAoOyB0ID4gMDsgKSB7CiAgICBjb25zdCBpID0gbiAtIHQsIHIgPSBNYXRoLm1pbihuLCBuIC0gdCArIHMpLCBjID0gZS5maWxlLnNsaWNlKGksIHIpLCBvID0gZS5ibHVlcHJpbnRzW2xdOwogICAgYS5jaHVua3MucHVzaCh7CiAgICAgIHVybDogby51cmwsCiAgICAgIG1ldGhvZDogby5tZXRob2QsCiAgICAgIGhlYWRlcnM6IG8uaGVhZGVycywKICAgICAgYm9keTogYwogICAgfSksIHQgLT0gcywgbCsrOwogIH0KICByZXR1cm4gYTsKfQo=", W = (i) => Uint8Array.from(atob(i), (e) => e.charCodeAt(0)), A = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", W(f)], { type: "text/javascript;charset=utf-8" }); function F(i) { let e; try { if (e = A && (self.URL || self.webkitURL).createObjectURL(A), !e) throw ""; const t = new Worker(e, { type: "module", name: i?.name }); return t.addEventListener("error", () => { (self.URL || self.webkitURL).revokeObjectURL(e); }), t; } catch { return new Worker( "data:text/javascript;base64," + f, { type: "module", name: i?.name } ); } } class y extends I { constructor(e, t, s, r, n) { super(), this.apiBaseUrl = e, this.chunkSize = t, this.packageID = s, this.packageToken = r, this.masvUserAgent = n, this.terminated = !1, this.onNativeWorkerMessage = (h) => { const { name: a, data: g } = h.data; this.emit(a, { data: g }); }, this.emit(u.Created), this.startWorker(); } startWorker() { this.nativeWorker = new F(), this.nativeWorker.onmessage = this.onNativeWorkerMessage, this.nativeWorker.postMessage({ name: "Init", input: { packageToken: this.packageToken, apiBaseUrl: this.apiBaseUrl, packageID: this.packageID, masvUserAgent: this.masvUserAgent, chunkSize: this.chunkSize } }); } stopWorker() { this.nativeWorker.onmessage = null, this.nativeWorker.terminate(); } createFile(e, t) { if (this.terminated) throw new Error("Can't use a terminated worker"); this.nativeWorker.postMessage({ name: "Chunk", input: e, spec: t }); } abort() { this.stopWorker(), this.startWorker(); } terminate() { this.terminated = !0, this.emit(u.Terminate), this.clearHandlers(), this.nativeWorker.terminate(); } } class V extends I { constructor(e, t, s, r, n = 6, h) { super(), this.workers = new Array(), this.counter = 0, this.terminated = !1; let a; for (let g = 0; g < n; g++) a = new y( e, t, s, r, h ), a.on("emit", this.bubbleEmit.bind(this)), this.workers.push(a); } createFile(e, t) { const s = this.workers[this.counter % this.workers.length]; if (this.terminated) throw new m(); this.counter++, s.createFile(e, t); } abort() { this.workers.forEach((e) => e.abort()); } terminate() { this.terminated = !0, this.workers.forEach((e) => e.terminate()), this.clearHandlers(); } } const k = "Y29uc3QgZCA9ICgpID0+ICh7CiAgcmV0cmllczogMTAsCiAgZGVsYXk6IDFlMwp9KTsKc2VsZi5jdXJyZW50UmVxdWVzdCA9IG51bGw7CnNlbGYuY3VycmVudFJlcXVlc3RzID0gW107CnNlbGYucmV0cnk0MDAgPSAhMTsKc2VsZi5yZXRyeVRpbWVvdXQgPSBudWxsOwpmdW5jdGlvbiB1KCkgewogIGxldCBlOwogIGlmIChzZWxmLmN1cnJlbnRSZXF1ZXN0cy5sZW5ndGggPT09IDAgfHwgc2VsZi5jdXJyZW50UmVxdWVzdCAhPSBudWxsKQogICAgcmV0dXJuOwogIGUgPSBzZWxmLmN1cnJlbnRSZXF1ZXN0cy5zaGlmdCgpLCBlLmlucHV0LnJldHJ5Q29uZmlnID09IG51bGwgJiYgKGUuaW5wdXQucmV0cnlDb25maWcgPSBkKCkpOwogIGNvbnN0IHQgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTsKICBzZWxmLmN1cnJlbnRSZXF1ZXN0ID0gewogICAgaW5wdXQ6IGUuaW5wdXQsCiAgICB4aHI6IHQKICB9OwogIGxldCBzID0gMDsKICBpZiAodC5vcGVuKGUuaW5wdXQubWV0aG9kLCBlLmlucHV0LnVybCwgITApLCBlLmlucHV0LmhlYWRlcnMpIHsKICAgIGNvbnN0IHIgPSBlLmlucHV0LmhlYWRlcnM7CiAgICBmb3IgKGxldCBuIGluIHIpCiAgICAgIHIuaGFzT3duUHJvcGVydHkobikgJiYgdC5zZXRSZXF1ZXN0SGVhZGVyKG4sIHJbbl0pOwogIH0KICB0Lm9ubG9hZCA9IChyKSA9PiB7CiAgICBsZXQgbCA9IHQuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkudHJpbSgpLnNwbGl0KC9bXHJcbl0rLyksIGEgPSB7fTsKICAgIGwuZm9yRWFjaCgocCkgPT4gewogICAgICBsZXQgZiA9IHAuc3BsaXQoIjogIiksIGMgPSBmLnNoaWZ0KCk7CiAgICAgIGFbY10gPSBmLmpvaW4oIjogIik7CiAgICB9KTsKICAgIGNvbnN0IGkgPSB0LnN0YXR1czsKICAgIFIoaSkgPyBvKGUpIDogKHNlbGYucG9zdE1lc3NhZ2UoewogICAgICBuYW1lOiAid29ya2VyOmZpbmlzaCIsCiAgICAgIHBheWxvYWQ6IHsKICAgICAgICByZXE6IGUuaW5wdXQsCiAgICAgICAgYm9keTogdC5yZXNwb25zZVRleHQsCiAgICAgICAgc3RhdHVzQ29kZTogaSwKICAgICAgICBoZWFkZXJzOiBhLAogICAgICAgIHRyYW5zZmVycmVkOiBzCiAgICAgIH0KICAgIH0pLCBzZWxmLmN1cnJlbnRSZXF1ZXN0ID0gbnVsbCwgdSgpKTsKICB9LCB0Lm9uZXJyb3IgPSBhc3luYyAoKSA9PiB7CiAgICBpZiAoZS5pbnB1dD8uYm9keSAhPSBudWxsICYmIGUuaW5wdXQudHlwZSA9PT0gInVwbG9hZF9maWxlIikgewogICAgICBjb25zdCBuID0gZS5pbnB1dC5ib2R5LnN0cmVhbSgpLmdldFJlYWRlcigpOwogICAgICB0cnkgewogICAgICAgIGF3YWl0IG4ucmVhZCgpLCBvKGUpOwogICAgICB9IGNhdGNoIChsKSB7CiAgICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7CiAgICAgICAgICBuYW1lOiAid29ya2VyOmVycm9yIiwKICAgICAgICAgIHBheWxvYWQ6IHsKICAgICAgICAgICAgZXJyb3I6IGwsCiAgICAgICAgICAgIGlucHV0OiBlLmlucHV0CiAgICAgICAgICB9CiAgICAgICAgfSksIHNlbGYuY3VycmVudFJlcXVlc3QgPSBudWxsLCB1KCk7CiAgICAgIH0KICAgIH0gZWxzZQogICAgICBvKGUpOwogIH0sIHQub25hYm9ydCA9IChyKSA9PiB7CiAgICBzZWxmLnBvc3RNZXNzYWdlKHsgbmFtZTogIndvcmtlcjphYm9ydCIsIHBheWxvYWQ6IGUuaW5wdXQgfSk7CiAgfSwgdC5vbnRpbWVvdXQgPSAocikgPT4gewogICAgc2VsZi5wb3N0TWVzc2FnZSh7IG5hbWU6ICJ3b3JrZXI6dGltZW91dCIsIHBheWxvYWQ6IGUuaW5wdXQgfSksIG8oZSk7CiAgfSwgdC51cGxvYWQub25wcm9ncmVzcyA9ICh7IGxvYWRlZDogciwgdG90YWw6IG4gfSkgPT4gewogICAgc2VsZi5wb3N0TWVzc2FnZSh7CiAgICAgIG5hbWU6ICJ3b3JrZXI6cHJvZ3Jlc3MiLAogICAgICBwYXlsb2FkOiB7CiAgICAgICAgbG9hZGVkOiByLAogICAgICAgIHRvdGFsOiBuLAogICAgICAgIGlucHV0OiBlLmlucHV0LAogICAgICAgIHRyYW5zZmVycmVkOiByIC0gcwogICAgICB9CiAgICB9KSwgcyA9IHIsIGUuY291bnQgPiAwICYmIChlLmNvdW50ID0gMCk7CiAgfSwgZS5pbnB1dC50aW1lb3V0ICYmICh0LnRpbWVvdXQgPSBlLmlucHV0LnRpbWVvdXQpLCB0LnNlbmQoZS5pbnB1dD8uYm9keSk7Cn0KZnVuY3Rpb24gbyh7IGlucHV0OiBlLCBjb3VudDogdCB9KSB7CiAgY29uc3QgcyA9IHQgKyAxOwogIHNlbGYuY3VycmVudFJlcXVlc3QgPSBudWxsLCBzZWxmLnBvc3RNZXNzYWdlKHsKICAgIG5hbWU6ICJ3b3JrZXI6cmV0cnkiLAogICAgcGF5bG9hZDogewogICAgICBpbnB1dDogZSwKICAgICAgY291bnQ6IHMKICAgIH0KICB9KSwgc2VsZi5yZXRyeVRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHsKICAgIHNlbGYuY3VycmVudFJlcXVlc3RzLnVuc2hpZnQoeyBpbnB1dDogZSwgY291bnQ6IHMgfSksIHUoKTsKICB9LCBNYXRoLm1pbihzLCA1KSAqIGUucmV0cnlDb25maWcuZGVsYXkpOwp9CmZ1bmN0aW9uIFIoZSkgewogIHJldHVybiBzZWxmLnJldHJ5NDAwICYmIFstMSwgMCwgNDAwLCA0MDFdLmluY2x1ZGVzKGUpID8gITAgOiBlID49IDUwMDsKfQpzZWxmLm9ubWVzc2FnZSA9IGZ1bmN0aW9uKGUpIHsKICBjb25zdCB7IGRhdGE6IHQgfSA9IGUsIHMgPSB7CiAgICByZXF1ZXN0OiAocikgPT4gewogICAgICBzZWxmLmN1cnJlbnRSZXF1ZXN0cy5wdXNoKHsKICAgICAgICBpbnB1dDogciwKICAgICAgICBjb3VudDogMAogICAgICB9KSwgdSgpOwogICAgfSwKICAgIGFib3J0OiAoKSA9PiB7CiAgICAgIGlmIChzZWxmLmN1cnJlbnRSZXF1ZXN0ICE9IG51bGwpIHsKICAgICAgICBjb25zdCB7IGlucHV0OiByLCB4aHI6IG4gfSA9IHNlbGYuY3VycmVudFJlcXVlc3Q7CiAgICAgICAgci50eXBlID09PSAidXBsb2FkX2ZpbGUiICYmIG4uYWJvcnQoKSwgc2VsZi5jdXJyZW50UmVxdWVzdCA9IG51bGw7CiAgICAgIH0KICAgICAgY2xlYXJUaW1lb3V0KHNlbGYucmV0cnlUaW1lb3V0KSwgc2VsZi5jdXJyZW50UmVxdWVzdHMgPSBzZWxmLmN1cnJlbnRSZXF1ZXN0cy5maWx0ZXIoKHIpID0+IHIuaW5wdXQudHlwZSAhPT0gInVwbG9hZF9maWxlIiksIHUoKTsKICAgIH0sCiAgICBjb25maWc6IChyKSA9PiB7CiAgICAgIHNlbGYucmV0cnk0MDAgPSByLnJldHJ5NDAwIHx8ICExOwogICAgfQogIH07CiAgc1t0Lm1lc3NhZ2VdICE9IG51bGwgJiYgc1t0Lm1lc3NhZ2VdKHQpOwp9Owo=", H = (i) => Uint8Array.from(atob(i), (e) => e.charCodeAt(0)), b = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", H(k)], { type: "text/javascript;charset=utf-8" }); function X(i) { let e; try { if (e = b && (self.URL || self.webkitURL).createObjectURL(b), !e) throw ""; const t = new Worker(e, { type: "module", name: i?.name }); return t.addEventListener("error", () => { (self.URL || self.webkitURL).revokeObjectURL(e); }), t; } catch { return new Worker( "data:text/javascript;base64," + k, { type: "module", name: i?.name } ); } } var l = /* @__PURE__ */ ((i) => (i.AddChunk = "add_chunk", i.UploadFile = "upload_file", i.FinalizeFile = "finalize_file", i.FinalizePackage = "finalize_package", i.CancelPackage = "cancel_package", i.Error = "error", i))(l || {}); class z extends I { constructor(e = !1) { super(), this.terminated = !1, this.onNativeWorkerMessage = (t) => { const { name: s, payload: r } = t.data; this.emit(s, { data: r }); }, this.startWorker(e), this.emit(u.Created); } startWorker(e = !1) { this.nativeWorker = new X(), this.nativeWorker.onmessage = this.onNativeWorkerMessage, this.nativeWorker.postMessage({ message: "config", retry400: e }); } execute(e) { if (this.terminated) throw new Error("Can't run a terminated worker"); this.emit(u.Execute, { data: e }), this.nativeWorker.postMessage({ message: "request", ...e }); } abort() { this.nativeWorker.postMessage({ message: "abort" /* Abort */ }); } terminate() { this.terminated = !0, this.emit(u.Terminate), this.clearHandlers(), this.nativeWorker.terminate(); } } const v = 1600 * 1e3; class K extends I { constructor(e, t, s, r, n, h = 6, a) { super(), this.apiBaseUrl = e, this.packageID = r, this.packageToken = n, this.poolSize = h, this.masvUserAgent = a, this.apiXhrExecutor = t, this.storageXhrExecutor = s, this.emit(o.Created), this.storageXhrExecutor.on(u.Progress, (g) => this.onStorageProgress(g)), this.storageXhrExecutor.on(u.Abort, (g) => this.onStorageAbort(g)), this.storageXhrExecutor.on(u.Retry, (g) => this.onStorageRetry(g)), this.storageXhrExecutor.on(u.Finish, (g) => this.onStorageFinish(g)), this.storageXhrExecutor.on(u.Error, (g) => this.onStorageError(g)); } upload(e) { const t = e.chunks.filter((s) => !s.isFinished).map((s) => ({ fileId: e.id, sequence: s.index, timeout: v, ...s.chunk, type: l.UploadFile })); return this.emit(o.Start, { data: e }), e.running = !0, this.storageXhrExecutor.execute(...t), e; } abort() { this.storageXhrExecutor.abort(), this.apiXhrExecutor.abort(); } onStorageProgress(e) { const t = e.data; e.data.input.type === l.UploadFile && this.bubbleEmit({ event: o.Progress, target: e.target, data: t }); } onStorageFinish(e) { const t = e.data; t.req.type === l.UploadFile && this.bubbleEmit({ event: o.Chunk, target: e.target, data: t }); } onStorageAbort(e) { const t = e.data; t.type === l.UploadFile && this.bubbleEmit({ event: o.Abort, target: e.target, data: t }); } onStorageRetry(e) { const t = e.data; t.input.type === l.UploadFile && this.bubbleEmit({ event: o.Retry, target: e.target, data: t }); } onStorageError(e) { const t = e.data; this.bubbleEmit({ event: o.Error, target: e.target, data: t }); } } class B extends I { constructor(e = 6, t = !1) { super(), this.workers = new Array(), this.counter = 0, this.retry400Errors = !1, this.terminated = !1, this.retry400Errors = t, this.initWorkerPool(e); } initWorkerPool(e = 6) { for (let t = 0; t < e; t++) { let s = new z(this.retry400Errors); s.on("emit", this.bubbleEmit.bind(this)), this.workers.push(s); } } stopWorkerPool() { this.workers.forEach((e) => { e.terminate(); }); } abort() { this.workers.forEach((e) => e.abort()); } execute(...e) { if (this.terminated) throw new m(); for (let t of e) this.workers[this.counter++ % this.workers.length].execute(t); } terminate() { this.terminated = !0, this.clearHandlers(), this.stopWorkerPool(); } } let L = 0; const N = Date.now(); function x() { return "randomUUID" in crypto ? crypto.randomUUID() : `${N}_${L++}`; } class U { constructor() { this.queue = {}; } getFile(e) { return this.queue[e]; } addFile(e) { const t = new Y(e); return this.queue[e.fileId] = t, t; } removeFile(e) { delete this.queue[e]; } setProgress(e, t, s) { const r = this.getFile(e); if (!r) return; const n = r.getChunk(t); if (n) return n.setProgress(s), n; } get length() { return Object.keys(this.queue).length; } get totalChunks() { return Object.values(this.queue).reduce((e, t) => e + t.chunks.length, 0); } get totalChunksInProgress() { return Object.values(this.queue).reduce((e, t) => e + t.chunksInProgress, 0); } } class Y { constructor({ fileId: e, req: t, file: s, chunks: r, storageType: n, fileExtras: h }) { this.chunks = [], this.running = !1, this.finalized = !1, this.id = e, this.req = t, this.file = s, this.chunks = r.map((a, g) => new P(a, g)), this.chunkSize = t.chunkSize > s.file.size ? s.file.size : t.chunkSize, this.storageType = n, this.fileExtras = h; } setChunkExtras({ headers: e, req: t }) { const s = t.sequence || 0, r = this.chunks.find((h) => h.index === s); if (!r) return; const n = e.etag || e.ETag || e.Etag; r.setExtras({ // partNumber should be a number but it is converted to string here // https://masvio.atlassian.net/browse/MASV-11004 partNumber: String(s + 1), etag: n }); } getChunk(e) { return this.chunks[e]; } validateMissingEtags() { return this.chunks.filter((e) => e.extras == null || e.extras.etag == null); } get isFinished() { return this.chunks.every((e) => e.isFinished); } get inProgress() { return this.chunks.some((e) => e.currentBytes > 0) && !this.isFinished; } get currentBytes() { return this.chunks.reduce((e, t) => e + t.currentBytes, 0); } get totalBytes() { return this.chunks.reduce((e, t) => e + t.totalBytes, 0); } get chunksInProgress() { return this.chunks.filter((e) => !e.isFinished).length; } } class P { constructor(e, t) { this._currentBytes = 0, this.extras = null, this.index = t, this.chunk = e; } setProgress(e) { this._currentBytes = e; } setExtras(e) { this.extras = e; } get etag() { return this.extras?.etag; } get currentBytes() { return this._currentBytes; } get totalBytes() { return this.chunk.body.size; } get inProgress() { return this.currentBytes > 0 && !this.isFinished; } get isFinished() { return this.currentBytes >= this.totalBytes && this.extras != null; } } class T { constructor(e) { if (this.ma = 0, this.v = 0, this.d = 0, this.f = 0, this.previousTime = 0, e <= 0) throw new Error("must provide a timespan > 0 to the moving average constructor"); this.timespan = e; } alpha(e, t) { return 1 - Math.exp(-(e - t) / this.timespan); } push(e, t) { if (this.previousTime > 0) { const s = this.alpha(e, this.previousTime), r = t - this.ma, n = s * r; this.ma = s * t + (1 - s) * this.ma, this.v = (1 - s) * (this.v + r * n), this.d = Math.sqrt(this.v), this.f = this.ma + s * r; } else this.ma = t; this.previousTime = e; } // Exponential Moving Average movingAverage() { return this.ma; } // Variance variance() { return this.v; } deviation() { return this.d; } forecast() { return this.f; } } var c = /* @__PURE__ */ ((i) => (i.Start = "upload_start", i.Stop = "upload_stop", i.Pause = "upload_pause", i.Finish = "upload_finish", i.Continue = "upload_continue", i))(c || {}); const p = 500; class R { constructor() { this.transferred = 0, this.received = 0, this.finalized = 0, this.finalizedFiles = 0, this.total = 0, this.totalFiles = 0, this.marks = { upload_start: [], upload_pause: [], upload_continue: [], upload_finish: [], upload_stop: [] }, this.moving = new T(p), this.debounceAverage = !1, this.lastSampleAmount = 0, this.progress = 0, this.instantSpeed = 0, this.movingSpeed = 0, this.duration = 0, this.timer = -1; } mark(e) { this.marks[e] && (e === "upload_start" || e === "upload_continue" ? this.record(performance.now()) : this.stopTimer(), this.marks[e].push(Date.now())); } record(e) { this.timer = requestAnimationFrame((t) => { this.duration += t - e, this.record(t); }); } stopTimer() { cancelAnimationFrame(this.timer); } clear(e) { this.marks[e] = []; } setTotal(e) { this.total = e; } setTotalFiles(e) { this.totalFiles = e; } addData(e = 0) { const t = Date.now(); if (this.transferred += e, this.progress += e, this.debounceAverage) return; this.debounceAverage = !0; const s = this.transferred - this.lastSampleAmount; this.instantSpeed = s / (p / 1e3), this.lastSampleAmount = this.transferred, this.moving.push(t, this.instantSpeed), this.movingSpeed = this.moving.movingAverage(), setTimeout(() => { this.debounceAverage = !1; }, p); } addReceived(e = 0) { this.received += e; } addFinalizedFile(e = 0) { this.finalized += e, this.finalizedFiles++; } subtractProgress(e = 0) { this.progress -= e; } getStats() { return { duration: this.duration, speed: this.averageSpeed, instant: this.instantSpeed, moving: this.movingSpeed, transferred: this.transferred, total: this.total, totalFiles: this.totalFiles, progress: this.progress, received: this.received, finalized: this.finalized, finalizedFiles: this.finalizedFiles }; } get averageSpeed() { return this.transferred / (this.duration / 1e3); } } const d = 6, E = "masv-web", Q = "masv-web-uploader", D = "dev"; var Z = /* @__PURE__ */ ((i) => (i.Idle = "idle", i.Uploading = "uploading", i.Processing = "processing", i.Ready = "ready", i.Paused = "paused", i.Finished = "finished", i.Terminated = "terminated", i.Cancelled = "cancelled", i))(Z || {}); const C = class C extends I { constructor(e, t, s = "https://api.massive.app", r = 100 << 20, n = `${E}/${D}`, h = 6e4) { super(), this.packageID = e, this.packageToken = t, this.apiBaseUrl = s, this.stallTimeout = h, this.stallTimer = -1, this.performanceStats = new R(), this.version = "2.2.5", this.uploadState = new U(), this.fileQueue = [], this.createQueue = /* @__PURE__ */ new Set(), this.unreadableFiles = /* @__PURE__ */ new Set(), this.status = "idle", this.spec = { max_chunk_count: 1e4, max_chunk_size: 5 * 2 ** 30, // 5 GiB min_chunk_size: 5 * 2 ** 20 // 5 MiB }, this.masvUserAgent = `${n}+${Q}/${this.version}`, this.apiXhrExecutor = new B(d), this.storageXhrExecutor = new B(d, !0), this.fchunker = new V( s, r, e, t, d, this.masvUserAgent ), this.fuploader = new K( s, this.apiXhrExecutor, this.storageXhrExecutor, e, t, d, this.masvUserAgent ), this.fchunker.on(u.Finish, (a) => this.onChunkFinish(a)), this.fuploader.on(o.Progress, (a) => { this.onUploadProgress(a); }), this.fuploader.on(o.Chunk, (a) => this.onChunkUploadFinish(a)), this.fuploader.on(o.Abort, (a) => this.onUploadAbort(a)), this.fuploader.on(o.Retry, (a) => this.onUploadRetry(a)), this.fuploader.on(o.Error, (a) => this.onUploadError(a)), this.fchunker.on("emit", this.bubbleEmit.bind(this)), this.fuploader.on("emit", this.bubbleEmit.bind(this)), this.apiXhrExecutor.on(u.Finish, (a) => this.onAPIFinish(a)); } resetStallTimer() { clearTimeout(this.stallTimer), this.stallTimer = setTimeout(() => { this.emit(o.Stalled); }, this.stallTimeout); } popNextFile() { return this.fileQueue.pop(); } get nextFile() { return this.fileQueue[this.fileQueue.length - 1]; } get canUploadFile() { return this.nextFile == null || this.uploadState.totalChunksInProgress + this.createQueue.size >= d ? !1 : this.status === "ready" || this.status === "uploading"; } get hasFinished() { return this.nextFile === void 0 && this.uploadState.length === 0 && this.fileQueue.length === 0 && this.createQueue.size === 0; } onUploadProgress({ data: e }) { this.resetStallTimer(), e.input.fileId && this.uploadState.setProgress(e.input.fileId, e.input.sequence || 0, e.loaded), this.performanceStats.addData(e.transferred); } onChunkFinish({ data: e }) { this.emit(o.FileQueued, { data: e }); const t = this.uploadState.addFile(e); this.resetStallTimer(), this.createQueue.delete(e.file.id), t.totalBytes === 0 ? t.file.file.stream().getReader().read().then(() => { t.running = !0, this.finalizeFile(t); }).catch((n) => { this.setUnreadableFile(t, n.message); }) : this.fuploader.upload(t), this.uploadNext(); } onUploadAbort({ data: e }) { const { fileId: t = "", sequence: s = 0 } = e, r = this.uploadState.getFile(t)?.getChunk(s).currentBytes ?? 0; this.performanceStats.subtractProgress(r), this.uploadState.setProgress(t, s, 0); } onUploadRetry({ data: e }) { const { fileId: t = "", sequence: s = 0 } = e.input, r = this.uploadState.getFile(t)?.getChunk(s).currentBytes ?? 0; this.performanceStats.subtractProgress(r), this.uploadState.setProgress(t, s, 0); } onUploadError({ data: e }) { const { fileId: t = "" } = e.input; let { message: s = "generic upload error" } = e.error; const r = this.uploadState.getFile(t); r != null && this.setUnreadableFile(r, s); } onChunkUploadFinish({ data: e }) { const { fileId: t = "", sequence: s = 0 } = e.req, r = this.uploadState.getFile(t); if (r) { const n = r.getChunk(s); this.performanceStats.addReceived(n.totalBytes), r.setChunkExtras(e), r.isFinished && (this.emit(o.File, { data: r }), this.finalizeFile(r)); } this.uploadNext(); } onAPIFinish({ data: e }) { const t = [200, 201, 204]; if (e.req.type === l.FinalizeFile) { const s = this.uploadState.getFile(e.req.fileId); if (s) if (t.includes(e.statusCode)) s.finalized = !0, s.running = !1, this.performanceStats.addFinalizedFile(s.file.file.size), this.uploadState.removeFile(s.id), this.emit(o.Finalize, { data: s }); else { this.setUnreadableFile(s, `unexpected status code for finalize file request: ${e.statusCode}`), this.hasFinished && this.stop(); return; } this.uploadNext(), this.hasFinished && (this.stop(), this.unreadableFiles.size > 0 ? this.markAsStalled() : this.finalize()); } e.req.type === l.FinalizePackage && (t.includes(e.statusCode) ? (this.performanceStats.mark(c.Finish), this.emit(o.Finished, { data: this.getPerformanceStats() }), this.status = "finished", this.terminate()) : (this.markAsStalled(`unexpected status code for finalize package request: ${e.statusCode}`), this.stop())), e.req.type === l.CancelPackage && this.terminate(); } setUnreadableFile(e, t) { this.emit(o.FileUnreadable, { data: e }), t === "network error" && (t = "file is unreadable (network error)"), this.unreadableFiles.add({ id: e.id, name: e.file?.file?.name, path: e.file?.path, size: e.file?.file?.size, errorMessage: t, errorTimestamp: (/* @__PURE__ */ new Date()).toISOString() }), this.uploadState.removeFile(e.id), this.hasFinished && this.markAsStalled(), this.uploadNext(); } markAsStalled(e = "Upload has become stalled due to unreadable files") { this.unreadableFiles.size > 0 && (e = [...this.unreadableFiles.values()][0].errorMessage); const t = { error_code: "upload_stalled", error_message: e, event_time: (/* @__PURE__ */ new Date()).toISOString(), extras: this.getProgressSummary() }; this.apiXhrExecutor.execute({ url: `${this.apiBaseUrl}/v1/packages/${this.packageID}/error`, method: "POST", headers: { "Content-Type": "application/json", "X-Package-Token": this.packageToken, "Masv-User-Agent": this.masvUserAgent }, body: JSON.stringify(t), timeout: 1e4, type: l.Error }), this.emit(o.Stalled), clearTimeout(this.stallTimer); } async addFiles(...e) { this.status = "processing", this.performanceStats.setTotalFiles(e.length), this.performanceStats.setTotal(e.reduce((t, s) => t + s.file.size, 0)), this.status = "ready", this.fileQueue = e, this.spec = await this.getSpec(), this.start(); } start() { if (this.status === "uploading") return; this.resetStallTimer(), this.status = "uploading"; const { transferred: e } = this.performanceStats.getStats(); if (e > 0 ? this.performanceStats.mark(c.Continue) : this.performanceStats.mark(c.Start), this.uploadState.totalChunksInProgress > 0) { const t = Object.values(this.uploadState.queue); for (let s of t) this.fuploader.upload(s); } else this.uploadNext(); } async getSpec(e = 0) { let t; try { t = await fetch(`${this.apiBaseUrl}/v1/system/packages/spec`, { method: "GET", headers: { "Content-Type": "application/json", "Masv-User-Agent": this.masvUserAgent } }); } catch { } if (t) { const s = await t.json(); if (t.ok) return s; if (t.status >= 500 && e < 5) return this.getSpec(e++); } return { max_chunk_count: 1e4, max_chunk_size: 5 * 2 ** 30, // 5 GiB min_chunk_size: 5 * 2 ** 20 // 5 MiB }; } uploadNext() { if (!this.canUploadFile) return; const e = this.popNextFile(); e && (e.id == null && (e.id = x()), this.createQueue.add(e.id), this.fchunker.createFile(e, this.spec)); } stop() { this.status = "idle", this.performanceStats.mark(c.Stop); } pause() { this.status !== "paused" && (clearTimeout(this.stallTimer), this.status = "paused", this.performanceStats.mark(c.Pause), this.fuploader.abort()); } terminate() { this.status !== "terminated" && (this.status = "terminated", this.clearHandlers(), this.storageXhrExecutor.terminate(), this.apiXhrExecutor.terminate(), this.fchunker.terminate()); } cancel() { this.pause(), this.status = "cancelled", this.apiXhrExecutor.execute({ url: `${this.apiBaseUrl}/v1/packages/${this.packageID}`, method: "DELETE", headers: { "X-Package-Token": this.packageToken, "Masv-User-Agent": this.masvUserAgent }, timeout: 1e4, type: l.CancelPackage }); } finalizeFile(e) { if (e.validateMissingEtags().length > 0) { this.fuploader.upload(e); return; } const { id: s, fileExtras: r, chunkSize: n, file: h, chunks: a } = e, g = a.map((G) => G.extras); this.apiXhrExecutor.execute({ url: `${this.apiBaseUrl}/v1/packages/${this.packageID}/files/${s}/finalize`, method: "POST", headers: { "Content-Type": "application/json", "X-Package-Token": this.packageToken, "Masv-User-Agent": this.masvUserAgent }, body: JSON.stringify({ fileExtras: r, chunk_size: n, size: h.file.size, chunkExtras: g }), timeout: 6e4, fileId: s, type: l.FinalizeFile }); } getIncompleteFiles() { return { queued: this.fileQueue, creating: [...this.createQueue], uploading: Object.values(this.uploadState.queue), unreadable: [...this.unreadableFiles] }; } finalize() { clearTimeout(this.stallTimer), this.apiXhrExecutor.execute({ url: `${this.apiBaseUrl}/v1/packages/${this.packageID}/finalize`, method: "POST", headers: { "Content-Type": "application/json", "X-Package-Token": this.packageToken, "Masv-User-Agent": this.masvUserAgent }, timeout: 6e4, type: l.FinalizePackage }); } getPerformanceStats() { return this.performanceStats.getStats(); } getProgressSummary() { const e = this.performanceStats.getStats(); return { finalizedBytes: String(e.finalized), finalizedFiles: String(e.finalizedFiles), totalBytes: String(e.total), totalFiles: String(e.totalFiles), unreadableFiles: String(this.unreadableFiles.size) }; } }; C.UploaderEvents = o, C.States = Z; let S = C; class w extends Error { constructor(e, t) { super("HTTP error " + e), this.statusCode = e, this.bytesTransferred = t, Object.setPrototypeOf(this, w.prototype); } getStatusCode() { return this.statusCode; } getBytesTransferred() { return this.bytesTransferred; } } class m extends Error { constructor() { super("Terminated"), Object.setPrototypeOf(this, m.prototype); } } export { w as HttpError, m as TerminatedError, S as Uploader };