upload-js
Version:
File Upload Library — Upload.js gives developers AJAX multipart file uploading via XHR 🚀 Comes with Cloud Storage 🌐
1,192 lines (969 loc) • 42.2 kB
JavaScript
module.exports =
/******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./src/index.ts":
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
"Upload": function() { return /* reexport */ Upload; },
"UploadApiError": function() { return /* reexport */ UploadApiError; }
});
;// CONCATENATED MODULE: external "@upload-io/upload-api-client-upload-js"
var upload_api_client_upload_js_namespaceObject = require("@upload-io/upload-api-client-upload-js");;
;// CONCATENATED MODULE: ./src/Mutex.ts
/**
* A lightweight mutex. (Other libraries contain too many features and we want to keep the size upload-js down).
*
* Characteristics:
* - Non-reentrant.
* - Unfair. (Multiple callers awaiting 'acquire' will be granted the mutex in no order.)
* - When calling `safe` consecutively with no 'awaits' in-between, the current context will synchronously acquire
* the mutex every time.
*/
function _call(body, then, direct) {
if (direct) {
return then ? then(body()) : body();
}
try {
var result = Promise.resolve(body());
return then ? result.then(then) : result;
} catch (e) {
return Promise.reject(e);
}
}
function _rethrow(thrown, value) {
if (thrown) throw value;
return value;
}
function _finallyRethrows(body, finalizer) {
try {
var result = body();
} catch (e) {
return finalizer(true, e);
}
if (result && result.then) {
return result.then(finalizer.bind(null, false), finalizer.bind(null, true));
}
return finalizer(false, result);
}
function _empty() {}
function _awaitIgnored(value, direct) {
if (!direct) {
return value && value.then ? value.then(_empty) : Promise.resolve();
}
}
function _settle(pact, state, value) {
if (!pact.s) {
if (value instanceof _Pact) {
if (value.s) {
if (state & 1) {
state = value.s;
}
value = value.v;
} else {
value.o = _settle.bind(null, pact, state);
return;
}
}
if (value && value.then) {
value.then(_settle.bind(null, pact, state), _settle.bind(null, pact, 2));
return;
}
pact.s = state;
pact.v = value;
var observer = pact.o;
if (observer) {
observer(pact);
}
}
}
var _Pact = /*#__PURE__*/function () {
function _Pact() {}
_Pact.prototype.then = function (onFulfilled, onRejected) {
var result = new _Pact();
var state = this.s;
if (state) {
var callback = state & 1 ? onFulfilled : onRejected;
if (callback) {
try {
_settle(result, 1, callback(this.v));
} catch (e) {
_settle(result, 2, e);
}
return result;
} else {
return this;
}
}
this.o = function (_this) {
try {
var value = _this.v;
if (_this.s & 1) {
_settle(result, 1, onFulfilled ? onFulfilled(value) : value);
} else if (onRejected) {
_settle(result, 1, onRejected(value));
} else {
_settle(result, 2, value);
}
} catch (e) {
_settle(result, 2, e);
}
};
return result;
};
return _Pact;
}();
function _isSettledPact(thenable) {
return thenable instanceof _Pact && thenable.s & 1;
}
function _for(test, update, body) {
var stage;
for (;;) {
var shouldContinue = test();
if (_isSettledPact(shouldContinue)) {
shouldContinue = shouldContinue.v;
}
if (!shouldContinue) {
return result;
}
if (shouldContinue.then) {
stage = 0;
break;
}
var result = body();
if (result && result.then) {
if (_isSettledPact(result)) {
result = result.s;
} else {
stage = 1;
break;
}
}
if (update) {
var updateValue = update();
if (updateValue && updateValue.then && !_isSettledPact(updateValue)) {
stage = 2;
break;
}
}
}
var pact = new _Pact();
var reject = _settle.bind(null, pact, 2);
(stage === 0 ? shouldContinue.then(_resumeAfterTest) : stage === 1 ? result.then(_resumeAfterBody) : updateValue.then(_resumeAfterUpdate)).then(void 0, reject);
return pact;
function _resumeAfterBody(value) {
result = value;
do {
if (update) {
updateValue = update();
if (updateValue && updateValue.then && !_isSettledPact(updateValue)) {
updateValue.then(_resumeAfterUpdate).then(void 0, reject);
return;
}
}
shouldContinue = test();
if (!shouldContinue || _isSettledPact(shouldContinue) && !shouldContinue.v) {
_settle(pact, 1, result);
return;
}
if (shouldContinue.then) {
shouldContinue.then(_resumeAfterTest).then(void 0, reject);
return;
}
result = body();
if (_isSettledPact(result)) {
result = result.v;
}
} while (!result || !result.then);
result.then(_resumeAfterBody).then(void 0, reject);
}
function _resumeAfterTest(shouldContinue) {
if (shouldContinue) {
result = body();
if (result && result.then) {
result.then(_resumeAfterBody).then(void 0, reject);
} else {
_resumeAfterBody(result);
}
} else {
_settle(pact, 1, result);
}
}
function _resumeAfterUpdate() {
if (shouldContinue = test()) {
if (shouldContinue.then) {
shouldContinue.then(_resumeAfterTest).then(void 0, reject);
} else {
_resumeAfterTest(shouldContinue);
}
} else {
_settle(pact, 1, result);
}
}
}
function _continue(value, then) {
return value && value.then ? value.then(then) : then(value);
}
function _async(f) {
return function () {
for (var args = [], i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
try {
return Promise.resolve(f.apply(this, args));
} catch (e) {
return Promise.reject(e);
}
};
}
function Mutex() {
var mutex;
var resolver;
var safe = function safe(callback) {
return _call(acquire, function () {
return _finallyRethrows(callback, function (_wasThrown, _result) {
release();
return _rethrow(_wasThrown, _result);
});
});
};
var acquire = _async(function () {
// Loop necessary for when multiple calls are made to 'acquire' before a 'release' is called, else the call to
// 'release' will resume every caller currently waiting on 'acquire'.
// eslint-disable-next-line no-unmodified-loop-condition
return _continue(_for(function () {
return mutex !== undefined;
}, void 0, function () {
return _awaitIgnored(mutex);
}), function () {
mutex = new Promise(function (resolve) {
resolver = resolve;
});
});
});
var release = function release() {
if (resolver === undefined) {
throw new Error("Unable to release mutex: already released.");
}
resolver();
resolver = undefined;
mutex = undefined;
};
return {
safe: safe
};
}
;// CONCATENATED MODULE: external "progress-smoother"
var external_progress_smoother_namespaceObject = require("progress-smoother");;
;// CONCATENATED MODULE: ./src/UploadApiError.ts
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }
function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
var UploadApiError = /*#__PURE__*/function (_Error) {
_inherits(UploadApiError, _Error);
var _super = _createSuper(UploadApiError);
function UploadApiError(response) {
var _this;
_classCallCheck(this, UploadApiError);
_this = _super.call(this, response.error.message);
_this.errorCode = response.error.code;
_this.details = response.error.details;
return _this;
}
return _createClass(UploadApiError);
}( /*#__PURE__*/_wrapNativeSuper(Error));
;// CONCATENATED MODULE: ./src/Upload.ts
function Upload_rethrow(thrown, value) {
if (thrown) throw value;
return value;
}
function Upload_finallyRethrows(body, finalizer) {
try {
var result = body();
} catch (e) {
return finalizer(true, e);
}
if (result && result.then) {
return result.then(finalizer.bind(null, false), finalizer.bind(null, true));
}
return finalizer(false, result);
}
function _continueIgnored(value) {
if (value && value.then) {
return value.then(Upload_empty);
}
}
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function Upload_empty() {}
var accountIdLength = 7; // Sync with: upload/shared/**/AccountIdUtils
function Upload_awaitIgnored(value, direct) {
if (!direct) {
return value && value.then ? value.then(Upload_empty) : Promise.resolve();
}
}
var specialApiKeyAccountId = "W142hJk";
function Upload_async(f) {
return function () {
for (var args = [], i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
try {
return Promise.resolve(f.apply(this, args));
} catch (e) {
return Promise.reject(e);
}
};
}
var specialApiKeys = ["free", "demo"];
function _await(value, then, direct) {
if (direct) {
return then ? then(value) : value;
}
if (!value || !value.then) {
value = Promise.resolve(value);
}
return then ? value.then(then) : value;
}
var apiKeyPrefix = "public_";
function Upload_call(body, then, direct) {
if (direct) {
return then ? then(body()) : body();
}
try {
var result = Promise.resolve(body());
return then ? result.then(then) : result;
} catch (e) {
return Promise.reject(e);
}
}
var maxUploadConcurrency = 5;
function _callIgnored(body, direct) {
return Upload_call(body, Upload_empty, direct);
}
var refreshBeforeExpirySeconds = 20;
function _catch(body, recover) {
try {
var result = body();
} catch (e) {
return recover(e);
}
if (result && result.then) {
return result.then(void 0, recover);
}
return result;
}
var onProgressInterval = 100;
function _invokeIgnored(body) {
var result = body();
if (result && result.then) {
return result.then(Upload_empty);
}
}
var retryAuthAfterErrorSeconds = 5;
var minJwtTtlSeconds = 10;
var maxJwtTtlSeconds = 2147483; // Max value for window.setTimeout is 2147483647ms -- if we go over this, the timeout fires immediately.
var accessTokenPathBase = "/api/v1/access_tokens/";
var logPrefix = "[upload-js] ";
/**
* You should instantiate one instance of this class in your web app.
*
* Try using:
*
* Upload({apiKey: "free"})
*
* If multiple instances exist, then all '*AuthSession' calls will be forwarded to the first instance that had an
* '*AuthSession' call invoked on it.
*/
function Upload(config) {
// ----------------
// READONLY MEMBERS
// ----------------
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
var accountId;
var authMutex = Mutex();
var apiUrl = (_b = (_a = config.internal) === null || _a === void 0 ? void 0 : _a.apiUrl) !== null && _b !== void 0 ? _b : "https://api.bytescale.com";
var cdnUrl = (_d = (_c = config.internal) === null || _c === void 0 ? void 0 : _c.cdnUrl) !== null && _d !== void 0 ? _d : "https://upcdn.io";
var authenticateWithApiKey = (_f = (_e = config.internal) === null || _e === void 0 ? void 0 : _e.authenticateWithApiKey) !== null && _f !== void 0 ? _f : true;
var headers = (_g = config.internal) === null || _g === void 0 ? void 0 : _g.headers;
var debugMode = config.debug === true;
var wasCalled = " was called."; // ------------------
// READ/WRITE MEMBERS
// ------------------
var lastAuthSession; // ----------------
// CONSTRUCTOR
// ----------------
if ((config !== null && config !== void 0 ? config : undefined) === undefined) {
throw new Error("".concat(logPrefix, "Config parameter required."));
}
if (config.debug === true) {
console.log("".concat(logPrefix, "Initialized with API key '").concat(config.apiKey, "'"));
}
if (((_h = config.apiKey) !== null && _h !== void 0 ? _h : undefined) === undefined) {
throw new Error("".concat(logPrefix, "Please provide an API key via the 'apiKey' config parameter."));
}
if (config.apiKey.trim() !== config.apiKey) {
// We do not support API keys with whitespace (by trimming ourselves) because otherwise we'd need to support this
// everywhere in perpetuity (since removing the trimming would be a breaking change).
throw new Error("".concat(logPrefix, "API key needs trimming (whitespace detected)."));
} // Non-api-key authentication is required by Bytescale Dashboard, which uses bearer tokens instead of API keys because
// the user may not have any active API keys, but might still want to upload files via the Bytescale Dashboard.
if (((_j = config.internal) === null || _j === void 0 ? void 0 : _j.authenticateWithApiKey) === false) {
accountId = config.internal.accountId;
} else {
if (specialApiKeys.includes(config.apiKey)) {
accountId = specialApiKeyAccountId;
} else {
if (!config.apiKey.startsWith(apiKeyPrefix)) {
throw new Error("".concat(logPrefix, "API key must begin with \"").concat(apiKeyPrefix, "\"."));
}
accountId = config.apiKey.substr(apiKeyPrefix.length, accountIdLength);
if (accountId.length !== accountIdLength) {
throw new Error("".concat(logPrefix, "API key is too short!"));
}
}
}
var accessTokenUrl = "".concat(cdnUrl).concat(accessTokenPathBase).concat(accountId); // ----------------
// PUBLIC METHODS
// ----------------
var beginAuthSession = Upload_async(function (authUrl, authHeaders) {
return Upload_awaitIgnored(callAuthMethod(Upload_async(function (x) {
return x.beginAuthSession(authUrl, authHeaders);
}), Upload_async(function () {
debug("'beginAuthSession'".concat(wasCalled)); // Explanation:
// - Prevents restarting the auth session on accidental double-calls to 'beginAuthSession': in some users' code,
// this happens accidentally every second, so we want to bail-out if we detect this is occurring.
// - We only check 'authUrl' to determine if the 'same call' is being made, since 'authHeaders' is a function
// and therefore its body can be switched-out by the user's code if they desire a change to its behaviour, so
// don't need to call 'beginAuthSession' just to update it.
if ((lastAuthSession === null || lastAuthSession === void 0 ? void 0 : lastAuthSession.authUrl) === authUrl) {
error("'beginAuthSession' already called. Ignoring this call. Hint: call 'endAuthSession' and then 'beginAuthSession' if you want to restart the auth session.");
return;
}
return Upload_call(doEndAuthSession, function () {
var authSession = {
accessToken: undefined,
accessTokenRefreshHandle: undefined,
isActive: true,
authUrl: authUrl
}; // Does not need to be inside the mutex since the environment is single-threaded, and we have not async-yielded
// since the mutex from 'endAuthSession' was relinquished (meaning we still have execution,
// so we know a) nothing can interject and b) nothing has interjected since the lock was relinquished).
lastAuthSession = authSession;
return Upload_awaitIgnored(refreshAccessToken(authUrl, authHeaders, authSession));
});
})));
});
var endAuthSession = Upload_async(function () {
return Upload_awaitIgnored(callAuthMethod(Upload_async(function (x) {
return x.endAuthSession();
}), Upload_async(function () {
debug("'endAuthSession'".concat(wasCalled));
return _callIgnored(doEndAuthSession);
})));
});
var uploadFile = Upload_async(function (file) {
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
debug("'uploadFile'".concat(wasCalled)); // Initial progress (raised immediately and synchronously).
var cancellationHandlers = [];
var addCancellationHandler = function addCancellationHandler(ca) {
cancellationHandlers.push(ca);
};
var cancel = function cancel() {
return cancellationHandlers.forEach(function (x) {
return x();
});
};
if (params.onBegin !== undefined) {
params.onBegin({
cancel: cancel
});
}
return _catch(function () {
return _await(beginFileUpload(file, params, addCancellationHandler));
}, function (e) {
cancel();
throw e;
});
});
var url = function url(filePath, transformationOrParams) {
var _a;
var defaultSlug = "raw";
var params = typeof transformationOrParams === "string" ? {
transformation: transformationOrParams
} : transformationOrParams;
return "".concat(cdnUrl, "/").concat(accountId, "/").concat((_a = params === null || params === void 0 ? void 0 : params.transformation) !== null && _a !== void 0 ? _a : defaultSlug).concat(filePath).concat((params === null || params === void 0 ? void 0 : params.auth) === true ? "?_auth=true" : "");
};
var self = {
beginAuthSession: beginAuthSession,
endAuthSession: endAuthSession,
uploadFile: uploadFile,
url: url
}; // ----------------
// PRIVATE METHODS
// ----------------
var doEndAuthSession = Upload_async(function () {
return Upload_awaitIgnored(authMutex.safe(Upload_async(function () {
if (lastAuthSession === undefined) {
return;
}
var authSession = lastAuthSession;
lastAuthSession = undefined;
if (authSession.accessTokenRefreshHandle !== undefined) {
clearTimeout(authSession.accessTokenRefreshHandle);
}
authSession.isActive = false;
return _callIgnored(deleteAccessToken);
})));
});
var beginFileUpload = Upload_async(function (file, params, addCancellationHandler) {
var progressSmoother = (0,external_progress_smoother_namespaceObject.ProgressSmoother)({
maxValue: file.size,
teardownTime: 1000,
minDelayUntilFirstValue: 2000,
valueIncreaseDelta: 200 * 1024,
valueIncreaseRatePerSecond: 50 * 1024,
averageTimeBetweenValues: 1000 // When running, XHR should (hopefully) report at least every second, regardless of connection speed.
});
var reportProgress = function reportProgress(stopReportingProgress) {
if (params.onProgress === undefined) {
stopReportingProgress(); // Important to call this, as outer function awaits this call when the download ends.
} else {
var bytesSent = progressSmoother.smoothedValue();
var bytesTotal = file.size;
if (bytesSent === bytesTotal) {
stopReportingProgress();
}
params.onProgress({
bytesSent: bytesSent,
bytesTotal: bytesTotal,
progress: Math.round(bytesSent / bytesTotal * 100)
});
}
};
return withProgressReporting(onProgressInterval, reportProgress, Upload_async(function () {
var uploadRequest = {
path: params.path,
metadata: params.metadata,
mime: normalizeMimeType(file.type),
originalFileName: file.name,
protocol: "1.1",
size: file.size,
tags: params.tags
};
debug("Initiating file upload. Params = ".concat(JSON.stringify(uploadRequest)));
return _await((0,upload_api_client_upload_js_namespaceObject.beginMultipartUpload)(getConfig(), accountId, uploadRequest), function (_beginMultipartUpload) {
var uploadMetadata = handleApiResult(_beginMultipartUpload);
debug("Initiated file upload. Metadata = ".concat(JSON.stringify(uploadMetadata)));
var incUploadIndex = function () {
var lastUploadIndex = 0;
return function () {
if (lastUploadIndex === uploadMetadata.uploadParts.count - 1) {
return undefined;
}
return ++lastUploadIndex;
};
}();
var nextPartQueue = [uploadMetadata.uploadParts.first];
var getNextPart = Upload_async(function (workerIndex) {
var nextPart = nextPartQueue.pop();
if (nextPart !== undefined) {
debug("Dequeued part ".concat(nextPart.uploadPartIndex, "."), workerIndex);
return nextPart;
}
var uploadPartIndex = incUploadIndex();
if (uploadPartIndex === undefined) {
debug("No parts remaining.", workerIndex);
return undefined;
}
debug("Fetching metadata for part ".concat(uploadPartIndex, "."), workerIndex);
return _await((0,upload_api_client_upload_js_namespaceObject.getUploadPart)(getConfig(), accountId, uploadMetadata.uploadId, uploadPartIndex), handleApiResult);
});
var bytesSentByEachWorker = [];
var uploadNextPart = function uploadNextPart(workerIndex) {
return _await(getNextPart(workerIndex), function (nextPart) {
return _invokeIgnored(function () {
if (nextPart !== undefined) {
var lastBytesSent = 0;
var progress = function progress(_ref) {
var bytesSent = _ref.bytesSent;
if (bytesSentByEachWorker[workerIndex] === undefined) {
bytesSentByEachWorker[workerIndex] = bytesSent;
} else {
bytesSentByEachWorker[workerIndex] -= lastBytesSent;
bytesSentByEachWorker[workerIndex] += bytesSent;
}
lastBytesSent = bytesSent;
var totalBytesSent = bytesSentByEachWorker.reduce(function (a, b) {
return a + b;
});
progressSmoother.setValue(totalBytesSent);
};
return _await(uploadPart(file, nextPart, progress, addCancellationHandler, workerIndex), function () {
return Upload_awaitIgnored(uploadNextPart(workerIndex));
});
}
});
});
};
return _await(Promise.all(_toConsumableArray(Array(maxUploadConcurrency).keys()).map(function (workerIndex) {
return _await(uploadNextPart(workerIndex));
})), function () {
var uploadedFile = Object.assign({
accountId: accountId,
file: file
}, uploadMetadata.file);
debug("File upload completed.");
return uploadedFile;
});
});
}));
});
var putUploadPart = Upload_async(function (url, content, progress, addCancellationHandler) {
var xhr = new XMLHttpRequest();
var pending = true;
addCancellationHandler(function () {
if (pending) {
xhr.abort();
}
});
return Upload_finallyRethrows(function () {
return _await(new Promise(function (resolve, reject) {
xhr.upload.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
progress({
bytesSent: evt.loaded,
bytesTotal: evt.total
});
}
}, false);
xhr.addEventListener("load", function () {
// Ensure we always report the progress of a finished upload as 100%.
progress({
bytesSent: content.size,
bytesTotal: content.size
});
if (Math.floor(xhr.status / 100) === 2) {
var etag = xhr.getResponseHeader("etag");
if (etag === null || etag === undefined) {
reject(new Error("File upload error: no etag header in upload response."));
} else {
resolve({
etag: etag
});
}
} else {
reject(new Error("File upload error: status code ".concat(xhr.status)));
}
});
xhr.onabort = function () {
return reject(new Error("File upload cancelled."));
};
xhr.onerror = function () {
return reject(new Error("File upload error."));
};
xhr.ontimeout = function () {
return reject(new Error("File upload timeout."));
};
xhr.open("PUT", url);
xhr.send(content);
}));
}, function (_wasThrown, _result) {
pending = false;
return Upload_rethrow(_wasThrown, _result);
});
});
var uploadPart = Upload_async(function (file, part, progress, addCancellationHandler, workerIndex) {
var content = part.range.inclusiveEnd === -1 ? new Blob() : file.slice(part.range.inclusiveStart, part.range.inclusiveEnd + 1);
debug("Uploading part ".concat(part.uploadPartIndex, "."), workerIndex);
return _await(putUploadPart(part.uploadUrl, content, progress, addCancellationHandler), function (_ref2) {
var etag = _ref2.etag;
return _await((0,upload_api_client_upload_js_namespaceObject.completeUploadPart)(getConfig(), accountId, part.uploadId, part.uploadPartIndex, {
etag: etag
}), function (_completeUploadPart) {
handleApiResult(_completeUploadPart);
debug("Uploaded part ".concat(part.uploadPartIndex, "."), workerIndex);
});
});
});
var withProgressReporting = Upload_async(function (tickInterval, tick, scope) {
var whileReportingResolved;
var whileReporting = new Promise(function (resolve) {
whileReportingResolved = resolve;
});
var isReporting = true;
var stopReporting = function stopReporting() {
if (isReporting) {
whileReportingResolved();
clearInterval(intervalHandle);
isReporting = false;
}
};
var intervalHandle = setInterval(function () {
return tick(stopReporting);
}, tickInterval);
return Upload_finallyRethrows(function () {
return Upload_call(scope, function (result) {
return _await(whileReporting, function () {
return result;
});
});
}, function (_wasThrown2, _result2) {
stopReporting();
return Upload_rethrow(_wasThrown2, _result2);
});
});
var deleteAccessToken = Upload_async(function () {
return Upload_awaitIgnored(deleteNoResponse(accessTokenUrl, {}, true // Required, else CDN response's `Set-Cookie` header will be silently ignored.
));
});
/**
* Calls the given auth method on the canonical auth instance.
*/
var callAuthMethod = Upload_async(function (other, me) {
var authInstance = getAuthInstance();
return _invokeIgnored(function () {
if (authInstance !== self) {
// Forward call to global auth instance.
return Upload_awaitIgnored(other(authInstance));
} else {
return _callIgnored(me);
}
});
});
/**
* Returns a single global instance of Upload.js for all auth calls.
* If we require multiple instances in the future, we can provide a parameter to disable this behaviour.
*/
var getAuthInstance = function getAuthInstance() {
var globalKey = "uploadJsAuthInstance";
var globalAuthInstance = window[globalKey];
if (globalAuthInstance === undefined) {
globalAuthInstance = self;
window[globalKey] = self;
}
return globalAuthInstance;
};
var refreshAccessToken = Upload_async(function (authUrl, authHeaders, authSession) {
return _continueIgnored(_catch(function () {
return Upload_awaitIgnored(authMutex.safe(Upload_async(function () {
// Session may have been ended while timer was waiting.
if (!authSession.isActive) {
return;
}
return Upload_call(authHeaders, function (_authHeaders) {
return _await(getAccessToken(authUrl, _authHeaders), function (token) {
return _await(putJsonGetJson(accessTokenUrl, {}, {
accessToken: token
}, true // Required, else CDN response's `Set-Cookie` header will be silently ignored.
), function (setTokenResult) {
var desiredTtlSeconds = setTokenResult.ttlSeconds - refreshBeforeExpirySeconds;
if (desiredTtlSeconds < minJwtTtlSeconds) {
warn("JWT expiration is too short: waiting for ".concat(minJwtTtlSeconds, " seconds before refreshing."));
}
authSession.accessToken = setTokenResult.accessToken;
authSession.accessTokenRefreshHandle = window.setTimeout(function () {
refreshAccessToken(authUrl, authHeaders, authSession).then(function () {}, function (e) {
return error("Permanent error when refreshing access token: ".concat(e));
});
}, Math.min(maxJwtTtlSeconds, Math.max(minJwtTtlSeconds, desiredTtlSeconds)) * 1000);
});
});
});
})));
}, function (e) {
// Use 'error' instead of 'debug' so that the user sees error messages.
error("Error when refreshing access token: ".concat(e)); // Perform attempts as part of same promise, rather than via a 'setTimeout' so that the 'beginAuthSession' only
// returns once an auth session has been successfully established.
return _await(new Promise(function (resolve) {
return setTimeout(resolve, retryAuthAfterErrorSeconds * 1000);
}), function () {
// Todo: is this stack safe?
return Upload_awaitIgnored(refreshAccessToken(authUrl, authHeaders, authSession));
});
}));
});
var putJsonGetJson = Upload_async(function (url, headers, requestBody, withCredentials) {
return _await(nonUploadApiRequest({
method: "PUT",
path: url,
headers: headers,
body: requestBody
}, withCredentials), function (_nonUploadApiRequest) {
return _await(handleApiResult(_nonUploadApiRequest));
});
});
var getAccessToken = Upload_async(function (authUrl, headers) {
var endpointName = "Your auth API endpoint";
return _await(nonUploadApiRequest({
method: "GET",
path: authUrl,
headers: headers
}, false), function (result) {
if (!result.ok) {
throw new Error("".concat(logPrefix).concat(endpointName, " returned a failed response. Please ensure the endpoint's status code is 200."));
}
var jwt = result.body;
if (typeof jwt !== "string") {
// We will receive 'null' if there was no content-type response header.
throw new Error("".concat(logPrefix).concat(endpointName, " returned an unsupported response. Please ensure: 1) 'Content-Type: text/plain' is in the HTTP response headers 2) the status code is 200."));
}
if (jwt.length === 0) {
throw new Error("".concat(logPrefix).concat(endpointName, " returned an empty string. Please return a valid JWT instead."));
}
if (jwt.trim().length !== jwt.length) {
// Whitespace can be a nightmare to spot/debug, so we fail early here.
throw new Error("".concat(logPrefix).concat(endpointName, " returned whitespace around the JWT, please remove it."));
}
return jwt;
});
});
var deleteNoResponse = Upload_async(function (url, headers, withCredentials) {
return _await(nonUploadApiRequest({
method: "DELETE",
path: url,
headers: headers
}, withCredentials), function (_nonUploadApiRequest2) {
handleApiResult(_nonUploadApiRequest2);
});
});
var handleApiResult = function handleApiResult(result) {
var _a;
if (result.ok) {
return result.body;
}
var errorResponseMaybe = result.body;
if (typeof ((_a = errorResponseMaybe === null || errorResponseMaybe === void 0 ? void 0 : errorResponseMaybe.error) === null || _a === void 0 ? void 0 : _a.code) === "string") {
throw new UploadApiError(errorResponseMaybe);
}
throw new Error("".concat(logPrefix, "Network error. If problem persists, and your network connectivity is healthy, please contact support@bytescale.com and provide: (a) time of failed request in UTC (b) screenshot of failed network response body (c) screenshot of failed network response header (d) browser + version."));
};
var nonUploadApiRequest = Upload_async(function (options, withCredentials) {
return (0,upload_api_client_upload_js_namespaceObject.request)({
BASE: options.path,
WITH_CREDENTIALS: withCredentials
}, Object.assign(Object.assign({}, options), {
path: "" // We set to "" because we're using "BASE" above instead.
}));
});
var getConfig = function getConfig() {
var apiConfig = {
BASE: apiUrl,
WITH_CREDENTIALS: true
};
if (authenticateWithApiKey) {
apiConfig.USERNAME = "apikey";
apiConfig.PASSWORD = config.apiKey;
}
var accessToken = lastAuthSession === null || lastAuthSession === void 0 ? void 0 : lastAuthSession.accessToken;
if (headers !== undefined || accessToken !== undefined) {
apiConfig.HEADERS = Upload_async(function () {
return _await(headers === undefined ? {} : headers(), function (headersFromConfig) {
var accessToken = lastAuthSession === null || lastAuthSession === void 0 ? void 0 : lastAuthSession.accessToken; // Re-fetch as there's been an async boundary so state may have changed.
return Object.assign(Object.assign({}, headersFromConfig), accessToken === undefined ? {} : {
"authorization-token": accessToken
});
}, headers === undefined);
});
}
return apiConfig;
};
var normalizeMimeType = function normalizeMimeType(mime) {
var normal = mime.toLowerCase();
var regex = /^[a-z0-9]+\/[a-z0-9+\-._]+(?:;[^=]+=[^;]+)*$/; // Sync with 'MimeTypeUnboxed' in 'upload/api'.
return regex.test(normal) ? normal : undefined;
};
var debug = function debug(message, workerIndex) {
if (debugMode) {
console.log("".concat(logPrefix).concat(message).concat(workerIndex !== undefined ? " (Worker ".concat(workerIndex, ")") : ""));
}
};
var error = function error(message) {
console.error("".concat(logPrefix).concat(message));
};
var warn = function warn(message) {
console.warn("".concat(logPrefix).concat(message));
};
return self;
}
;// CONCATENATED MODULE: ./src/index.ts
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(__webpack_module_cache__[moduleId]) {
/******/ return __webpack_module_cache__[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ !function() {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = function(exports, definition) {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ !function() {
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ }();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ !function() {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ }();
/******/
/************************************************************************/
/******/ // module exports must be returned from runtime so entry inlining is disabled
/******/ // startup
/******/ // Load entry module and return exports
/******/ return __webpack_require__("./src/index.ts");
/******/ })()
;