@firebase/storage 0.9.10 → 0.9.11-20221010190246

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -41,7 +41,11 @@ var DEFAULT_MAX_OPERATION_RETRY_TIME = 2 * 60 * 1000;
41
41
  *
42
42
  * The timeout for upload.
43
43
  */
44
- var DEFAULT_MAX_UPLOAD_RETRY_TIME = 10 * 60 * 1000;
44
+ var DEFAULT_MAX_UPLOAD_RETRY_TIME = 10 * 60 * 1000;
45
+ /**
46
+ * 1 second
47
+ */
48
+ var DEFAULT_MIN_SLEEP_TIME_MILLIS = 1000;
45
49
 
46
50
  /**
47
51
  * @license
@@ -69,9 +73,12 @@ var StorageError = /** @class */ (function (_super) {
69
73
  * @param code - A StorageErrorCode string to be prefixed with 'storage/' and
70
74
  * added to the end of the message.
71
75
  * @param message - Error message.
76
+ * @param status_ - Corresponding HTTP Status Code
72
77
  */
73
- function StorageError(code, message) {
78
+ function StorageError(code, message, status_) {
79
+ if (status_ === void 0) { status_ = 0; }
74
80
  var _this = _super.call(this, prependCode(code), "Firebase Storage: " + message + " (" + prependCode(code) + ")") || this;
81
+ _this.status_ = status_;
75
82
  /**
76
83
  * Stores custom error data unque to StorageError.
77
84
  */
@@ -82,6 +89,16 @@ var StorageError = /** @class */ (function (_super) {
82
89
  Object.setPrototypeOf(_this, StorageError.prototype);
83
90
  return _this;
84
91
  }
92
+ Object.defineProperty(StorageError.prototype, "status", {
93
+ get: function () {
94
+ return this.status_;
95
+ },
96
+ set: function (status) {
97
+ this.status_ = status;
98
+ },
99
+ enumerable: false,
100
+ configurable: true
101
+ });
85
102
  /**
86
103
  * Compares a StorageErrorCode against this error's code, filtering out the prefix.
87
104
  */
@@ -357,14 +374,20 @@ var FailRequest = /** @class */ (function () {
357
374
  * limitations under the License.
358
375
  */
359
376
  /**
360
- * @param f May be invoked
361
- * before the function returns.
362
- * @param callback Get all the arguments passed to the function
363
- * passed to f, including the initial boolean.
377
+ * Accepts a callback for an action to perform (`doRequest`),
378
+ * and then a callback for when the backoff has completed (`backoffCompleteCb`).
379
+ * The callback sent to start requires an argument to call (`onRequestComplete`).
380
+ * When `start` calls `doRequest`, it passes a callback for when the request has
381
+ * completed, `onRequestComplete`. Based on this, the backoff continues, with
382
+ * another call to `doRequest` and the above loop continues until the timeout
383
+ * is hit, or a successful response occurs.
384
+ * @description
385
+ * @param doRequest Callback to perform request
386
+ * @param backoffCompleteCb Callback to call when backoff has been completed
364
387
  */
365
- function start(f,
388
+ function start(doRequest,
366
389
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
367
- callback, timeout) {
390
+ backoffCompleteCb, timeout) {
368
391
  // TODO(andysoto): make this code cleaner (probably refactor into an actual
369
392
  // type instead of a bunch of functions with state shared in the closure)
370
393
  var waitSeconds = 1;
@@ -387,13 +410,13 @@ callback, timeout) {
387
410
  }
388
411
  if (!triggeredCallback) {
389
412
  triggeredCallback = true;
390
- callback.apply(null, args);
413
+ backoffCompleteCb.apply(null, args);
391
414
  }
392
415
  }
393
416
  function callWithDelay(millis) {
394
417
  retryTimeoutId = setTimeout(function () {
395
418
  retryTimeoutId = null;
396
- f(handler, canceled());
419
+ doRequest(responseHandler, canceled());
397
420
  }, millis);
398
421
  }
399
422
  function clearGlobalTimeout() {
@@ -401,7 +424,7 @@ callback, timeout) {
401
424
  clearTimeout(globalTimeoutId);
402
425
  }
403
426
  }
404
- function handler(success) {
427
+ function responseHandler(success) {
405
428
  var args = [];
406
429
  for (var _i = 1; _i < arguments.length; _i++) {
407
430
  args[_i - 1] = arguments[_i];
@@ -583,6 +606,43 @@ var ErrorCode;
583
606
  ErrorCode[ErrorCode["ABORT"] = 2] = "ABORT";
584
607
  })(ErrorCode || (ErrorCode = {}));
585
608
 
609
+ /**
610
+ * @license
611
+ * Copyright 2022 Google LLC
612
+ *
613
+ * Licensed under the Apache License, Version 2.0 (the "License");
614
+ * you may not use this file except in compliance with the License.
615
+ * You may obtain a copy of the License at
616
+ *
617
+ * http://www.apache.org/licenses/LICENSE-2.0
618
+ *
619
+ * Unless required by applicable law or agreed to in writing, software
620
+ * distributed under the License is distributed on an "AS IS" BASIS,
621
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
622
+ * See the License for the specific language governing permissions and
623
+ * limitations under the License.
624
+ */
625
+ /**
626
+ * Checks the status code to see if the action should be retried.
627
+ *
628
+ * @param status Current HTTP status code returned by server.
629
+ * @param additionalRetryCodes additional retry codes to check against
630
+ */
631
+ function isRetryStatusCode(status, additionalRetryCodes) {
632
+ // The codes for which to retry came from this page:
633
+ // https://cloud.google.com/storage/docs/exponential-backoff
634
+ var isFiveHundredCode = status >= 500 && status < 600;
635
+ var extraRetryCodes = [
636
+ // Request Timeout: web server didn't receive full request in time.
637
+ 408,
638
+ // Too Many Requests: you're getting rate-limited, basically.
639
+ 429
640
+ ];
641
+ var isExtraRetryCode = extraRetryCodes.indexOf(status) !== -1;
642
+ var isAdditionalRetryCode = additionalRetryCodes.indexOf(status) !== -1;
643
+ return isFiveHundredCode || isExtraRetryCode || isAdditionalRetryCode;
644
+ }
645
+
586
646
  /**
587
647
  * @license
588
648
  * Copyright 2017 Google LLC
@@ -608,8 +668,9 @@ var ErrorCode;
608
668
  * happens in the specified `callback_`.
609
669
  */
610
670
  var NetworkRequest = /** @class */ (function () {
611
- function NetworkRequest(url_, method_, headers_, body_, successCodes_, additionalRetryCodes_, callback_, errorCallback_, timeout_, progressCallback_, connectionFactory_) {
671
+ function NetworkRequest(url_, method_, headers_, body_, successCodes_, additionalRetryCodes_, callback_, errorCallback_, timeout_, progressCallback_, connectionFactory_, retry) {
612
672
  var _this = this;
673
+ if (retry === void 0) { retry = true; }
613
674
  this.url_ = url_;
614
675
  this.method_ = method_;
615
676
  this.headers_ = headers_;
@@ -621,6 +682,7 @@ var NetworkRequest = /** @class */ (function () {
621
682
  this.timeout_ = timeout_;
622
683
  this.progressCallback_ = progressCallback_;
623
684
  this.connectionFactory_ = connectionFactory_;
685
+ this.retry = retry;
624
686
  this.pendingConnection_ = null;
625
687
  this.backoffId_ = null;
626
688
  this.canceled_ = false;
@@ -645,9 +707,7 @@ var NetworkRequest = /** @class */ (function () {
645
707
  _this.pendingConnection_ = connection;
646
708
  var progressListener = function (progressEvent) {
647
709
  var loaded = progressEvent.loaded;
648
- var total = progressEvent.lengthComputable
649
- ? progressEvent.total
650
- : -1;
710
+ var total = progressEvent.lengthComputable ? progressEvent.total : -1;
651
711
  if (_this.progressCallback_ !== null) {
652
712
  _this.progressCallback_(loaded, total);
653
713
  }
@@ -666,7 +726,9 @@ var NetworkRequest = /** @class */ (function () {
666
726
  _this.pendingConnection_ = null;
667
727
  var hitServer = connection.getErrorCode() === ErrorCode.NO_ERROR;
668
728
  var status = connection.getStatus();
669
- if (!hitServer || _this.isRetryStatusCode_(status)) {
729
+ if ((!hitServer ||
730
+ isRetryStatusCode(status, _this.additionalRetryCodes_)) &&
731
+ _this.retry) {
670
732
  var wasCanceled = connection.getErrorCode() === ErrorCode.ABORT;
671
733
  backoffCallback(false, new RequestEndStatus(false, null, wasCanceled));
672
734
  return;
@@ -742,20 +804,6 @@ var NetworkRequest = /** @class */ (function () {
742
804
  this.pendingConnection_.abort();
743
805
  }
744
806
  };
745
- NetworkRequest.prototype.isRetryStatusCode_ = function (status) {
746
- // The codes for which to retry came from this page:
747
- // https://cloud.google.com/storage/docs/exponential-backoff
748
- var isFiveHundredCode = status >= 500 && status < 600;
749
- var extraRetryCodes = [
750
- // Request Timeout: web server didn't receive full request in time.
751
- 408,
752
- // Too Many Requests: you're getting rate-limited, basically.
753
- 429
754
- ];
755
- var isExtraRetryCode = extraRetryCodes.indexOf(status) !== -1;
756
- var isRequestSpecificRetryCode = this.additionalRetryCodes_.indexOf(status) !== -1;
757
- return isFiveHundredCode || isExtraRetryCode || isRequestSpecificRetryCode;
758
- };
759
807
  return NetworkRequest;
760
808
  }());
761
809
  /**
@@ -789,7 +837,8 @@ function addAppCheckHeader_(headers, appCheckToken) {
789
837
  headers['X-Firebase-AppCheck'] = appCheckToken;
790
838
  }
791
839
  }
792
- function makeRequest(requestInfo, appId, authToken, appCheckToken, requestFactory, firebaseVersion) {
840
+ function makeRequest(requestInfo, appId, authToken, appCheckToken, requestFactory, firebaseVersion, retry) {
841
+ if (retry === void 0) { retry = true; }
793
842
  var queryPart = makeQueryString(requestInfo.urlParams);
794
843
  var url = requestInfo.url + queryPart;
795
844
  var headers = Object.assign({}, requestInfo.headers);
@@ -797,7 +846,7 @@ function makeRequest(requestInfo, appId, authToken, appCheckToken, requestFactor
797
846
  addAuthHeader_(headers, authToken);
798
847
  addVersionHeader_(headers, firebaseVersion);
799
848
  addAppCheckHeader_(headers, appCheckToken);
800
- return new NetworkRequest(url, requestInfo.method, headers, requestInfo.body, requestInfo.successCodes, requestInfo.additionalRetryCodes, requestInfo.handler, requestInfo.errorHandler, requestInfo.timeout, requestInfo.progressCallback, requestFactory);
849
+ return new NetworkRequest(url, requestInfo.method, headers, requestInfo.body, requestInfo.successCodes, requestInfo.additionalRetryCodes, requestInfo.handler, requestInfo.errorHandler, requestInfo.timeout, requestInfo.progressCallback, requestFactory, retry);
801
850
  }
802
851
 
803
852
  /**
@@ -1629,6 +1678,7 @@ function sharedErrorHandler(location) {
1629
1678
  }
1630
1679
  }
1631
1680
  }
1681
+ newErr.status = xhr.getStatus();
1632
1682
  newErr.serverResponse = err.serverResponse;
1633
1683
  return newErr;
1634
1684
  }
@@ -1914,7 +1964,16 @@ function continueResumableUpload(location, service, url, blob, chunkSize, mappin
1914
1964
  }
1915
1965
  var startByte = status_.current;
1916
1966
  var endByte = startByte + bytesToUpload;
1917
- var uploadCommand = bytesToUpload === bytesLeft ? 'upload, finalize' : 'upload';
1967
+ var uploadCommand = '';
1968
+ if (bytesToUpload === 0) {
1969
+ uploadCommand = 'finalize';
1970
+ }
1971
+ else if (bytesLeft === bytesToUpload) {
1972
+ uploadCommand = 'upload, finalize';
1973
+ }
1974
+ else {
1975
+ uploadCommand = 'upload';
1976
+ }
1918
1977
  var headers = {
1919
1978
  'X-Goog-Upload-Command': uploadCommand,
1920
1979
  'X-Goog-Upload-Offset': "" + status_.current
@@ -2298,6 +2357,18 @@ var UploadTask = /** @class */ (function () {
2298
2357
  _this.completeTransitions_();
2299
2358
  }
2300
2359
  else {
2360
+ var backoffExpired = _this.isExponentialBackoffExpired();
2361
+ if (isRetryStatusCode(error.status, [])) {
2362
+ if (backoffExpired) {
2363
+ error = retryLimitExceeded();
2364
+ }
2365
+ else {
2366
+ _this.sleepTime = Math.max(_this.sleepTime * 2, DEFAULT_MIN_SLEEP_TIME_MILLIS);
2367
+ _this._needToFetchStatus = true;
2368
+ _this.completeTransitions_();
2369
+ return;
2370
+ }
2371
+ }
2301
2372
  _this._error = error;
2302
2373
  _this._transition("error" /* ERROR */);
2303
2374
  }
@@ -2312,6 +2383,8 @@ var UploadTask = /** @class */ (function () {
2312
2383
  _this._transition("error" /* ERROR */);
2313
2384
  }
2314
2385
  };
2386
+ this.sleepTime = 0;
2387
+ this.maxSleepTime = this._ref.storage.maxUploadRetryTime;
2315
2388
  this._promise = new Promise(function (resolve, reject) {
2316
2389
  _this._resolve = resolve;
2317
2390
  _this._reject = reject;
@@ -2321,6 +2394,9 @@ var UploadTask = /** @class */ (function () {
2321
2394
  // to the top level with a dummy handler.
2322
2395
  this._promise.then(null, function () { });
2323
2396
  }
2397
+ UploadTask.prototype.isExponentialBackoffExpired = function () {
2398
+ return this.sleepTime > this.maxSleepTime;
2399
+ };
2324
2400
  UploadTask.prototype._makeProgressCallback = function () {
2325
2401
  var _this = this;
2326
2402
  var sizeBefore = this._transferred;
@@ -2330,6 +2406,7 @@ var UploadTask = /** @class */ (function () {
2330
2406
  return blob.size() > 256 * 1024;
2331
2407
  };
2332
2408
  UploadTask.prototype._start = function () {
2409
+ var _this = this;
2333
2410
  if (this._state !== "running" /* RUNNING */) {
2334
2411
  // This can happen if someone pauses us in a resume callback, for example.
2335
2412
  return;
@@ -2351,7 +2428,9 @@ var UploadTask = /** @class */ (function () {
2351
2428
  this._fetchMetadata();
2352
2429
  }
2353
2430
  else {
2354
- this._continueUpload();
2431
+ setTimeout(function () {
2432
+ _this._continueUpload();
2433
+ }, this.sleepTime);
2355
2434
  }
2356
2435
  }
2357
2436
  }
@@ -2432,7 +2511,9 @@ var UploadTask = /** @class */ (function () {
2432
2511
  _this._transition("error" /* ERROR */);
2433
2512
  return;
2434
2513
  }
2435
- var uploadRequest = _this._ref.storage._makeRequest(requestInfo, newTextConnection, authToken, appCheckToken);
2514
+ var uploadRequest = _this._ref.storage._makeRequest(requestInfo, newTextConnection, authToken, appCheckToken,
2515
+ /*retry=*/ false // Upload requests should not be retried as each retry should be preceded by another query request. Which is handled in this file.
2516
+ );
2436
2517
  _this._request = uploadRequest;
2437
2518
  uploadRequest.getPromise().then(function (newStatus) {
2438
2519
  _this._increaseMultiplier();
@@ -2451,7 +2532,7 @@ var UploadTask = /** @class */ (function () {
2451
2532
  UploadTask.prototype._increaseMultiplier = function () {
2452
2533
  var currentSize = RESUMABLE_UPLOAD_CHUNK_SIZE * this._chunkMultiplier;
2453
2534
  // Max chunk size is 32M.
2454
- if (currentSize < 32 * 1024 * 1024) {
2535
+ if (currentSize * 2 < 32 * 1024 * 1024) {
2455
2536
  this._chunkMultiplier *= 2;
2456
2537
  }
2457
2538
  };
@@ -2607,6 +2688,7 @@ var UploadTask = /** @class */ (function () {
2607
2688
  */
2608
2689
  UploadTask.prototype.on = function (type, nextOrObserver, error, completed) {
2609
2690
  var _this = this;
2691
+ // Note: `type` isn't being used. Its type is also incorrect. TaskEvent should not be a string.
2610
2692
  var observer = new Observer(nextOrObserver || undefined, error || undefined, completed || undefined);
2611
2693
  this._addObserver(observer);
2612
2694
  return function () {
@@ -3370,10 +3452,11 @@ var FirebaseStorageImpl = /** @class */ (function () {
3370
3452
  * @param requestInfo - HTTP RequestInfo object
3371
3453
  * @param authToken - Firebase auth token
3372
3454
  */
3373
- FirebaseStorageImpl.prototype._makeRequest = function (requestInfo, requestFactory, authToken, appCheckToken) {
3455
+ FirebaseStorageImpl.prototype._makeRequest = function (requestInfo, requestFactory, authToken, appCheckToken, retry) {
3374
3456
  var _this = this;
3457
+ if (retry === void 0) { retry = true; }
3375
3458
  if (!this._deleted) {
3376
- var request_1 = makeRequest(requestInfo, this._appId, authToken, appCheckToken, requestFactory, this._firebaseVersion);
3459
+ var request_1 = makeRequest(requestInfo, this._appId, authToken, appCheckToken, requestFactory, this._firebaseVersion, retry);
3377
3460
  this._requests.add(request_1);
3378
3461
  // Request removes itself from set when complete.
3379
3462
  request_1.getPromise().then(function () { return _this._requests.delete(request_1); }, function () { return _this._requests.delete(request_1); });
@@ -3403,7 +3486,7 @@ var FirebaseStorageImpl = /** @class */ (function () {
3403
3486
  }());
3404
3487
 
3405
3488
  var name = "@firebase/storage";
3406
- var version = "0.9.10";
3489
+ var version = "0.9.11-20221010190246";
3407
3490
 
3408
3491
  /**
3409
3492
  * @license