@depup/firebase__storage 0.14.1-depup.0

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.
Files changed (101) hide show
  1. package/README.md +31 -0
  2. package/changes.json +10 -0
  3. package/dist/index.browser.cjs.js +3685 -0
  4. package/dist/index.browser.cjs.js.map +1 -0
  5. package/dist/index.cjs.js +3685 -0
  6. package/dist/index.cjs.js.map +1 -0
  7. package/dist/index.esm.js +3656 -0
  8. package/dist/index.esm.js.map +1 -0
  9. package/dist/index.node.cjs.js +3710 -0
  10. package/dist/index.node.cjs.js.map +1 -0
  11. package/dist/node-esm/index.node.esm.js +3681 -0
  12. package/dist/node-esm/index.node.esm.js.map +1 -0
  13. package/dist/node-esm/package.json +1 -0
  14. package/dist/node-esm/src/api.browser.d.ts +47 -0
  15. package/dist/node-esm/src/api.d.ts +200 -0
  16. package/dist/node-esm/src/api.node.d.ts +47 -0
  17. package/dist/node-esm/src/constants.d.ts +20 -0
  18. package/dist/node-esm/src/implementation/async.d.ts +22 -0
  19. package/dist/node-esm/src/implementation/backoff.d.ts +43 -0
  20. package/dist/node-esm/src/implementation/blob.d.ts +34 -0
  21. package/dist/node-esm/src/implementation/connection.d.ts +56 -0
  22. package/dist/node-esm/src/implementation/constants.d.ts +48 -0
  23. package/dist/node-esm/src/implementation/error.d.ts +126 -0
  24. package/dist/node-esm/src/implementation/failrequest.d.ts +29 -0
  25. package/dist/node-esm/src/implementation/fs.d.ts +17 -0
  26. package/dist/node-esm/src/implementation/json.d.ts +7 -0
  27. package/dist/node-esm/src/implementation/list.d.ts +19 -0
  28. package/dist/node-esm/src/implementation/location.d.ts +32 -0
  29. package/dist/node-esm/src/implementation/metadata.d.ts +40 -0
  30. package/dist/node-esm/src/implementation/observer.d.ts +47 -0
  31. package/dist/node-esm/src/implementation/path.d.ts +31 -0
  32. package/dist/node-esm/src/implementation/request.d.ts +47 -0
  33. package/dist/node-esm/src/implementation/requestinfo.d.ts +73 -0
  34. package/dist/node-esm/src/implementation/requests.d.ts +84 -0
  35. package/dist/node-esm/src/implementation/string.d.ts +73 -0
  36. package/dist/node-esm/src/implementation/taskenums.d.ts +77 -0
  37. package/dist/node-esm/src/implementation/type.d.ts +23 -0
  38. package/dist/node-esm/src/implementation/url.d.ts +22 -0
  39. package/dist/node-esm/src/implementation/utils.d.ts +23 -0
  40. package/dist/node-esm/src/index.d.ts +7 -0
  41. package/dist/node-esm/src/index.node.d.ts +7 -0
  42. package/dist/node-esm/src/list.d.ts +41 -0
  43. package/dist/node-esm/src/metadata.d.ts +27 -0
  44. package/dist/node-esm/src/platform/base64.d.ts +20 -0
  45. package/dist/node-esm/src/platform/browser/base64.d.ts +19 -0
  46. package/dist/node-esm/src/platform/browser/connection.d.ts +55 -0
  47. package/dist/node-esm/src/platform/connection.d.ts +22 -0
  48. package/dist/node-esm/src/platform/node/base64.d.ts +19 -0
  49. package/dist/node-esm/src/platform/node/connection.d.ts +58 -0
  50. package/dist/node-esm/src/public-types.d.ts +424 -0
  51. package/dist/node-esm/src/reference.d.ts +208 -0
  52. package/dist/node-esm/src/service.d.ts +131 -0
  53. package/dist/node-esm/src/task.d.ts +148 -0
  54. package/dist/node-esm/test/unit/connection.d.ts +47 -0
  55. package/dist/node-esm/test/unit/testshared.d.ts +60 -0
  56. package/dist/src/api.browser.d.ts +47 -0
  57. package/dist/src/api.d.ts +200 -0
  58. package/dist/src/api.node.d.ts +47 -0
  59. package/dist/src/constants.d.ts +20 -0
  60. package/dist/src/implementation/async.d.ts +22 -0
  61. package/dist/src/implementation/backoff.d.ts +43 -0
  62. package/dist/src/implementation/blob.d.ts +34 -0
  63. package/dist/src/implementation/connection.d.ts +56 -0
  64. package/dist/src/implementation/constants.d.ts +48 -0
  65. package/dist/src/implementation/error.d.ts +126 -0
  66. package/dist/src/implementation/failrequest.d.ts +29 -0
  67. package/dist/src/implementation/fs.d.ts +17 -0
  68. package/dist/src/implementation/json.d.ts +7 -0
  69. package/dist/src/implementation/list.d.ts +19 -0
  70. package/dist/src/implementation/location.d.ts +32 -0
  71. package/dist/src/implementation/metadata.d.ts +40 -0
  72. package/dist/src/implementation/observer.d.ts +47 -0
  73. package/dist/src/implementation/path.d.ts +31 -0
  74. package/dist/src/implementation/request.d.ts +47 -0
  75. package/dist/src/implementation/requestinfo.d.ts +73 -0
  76. package/dist/src/implementation/requests.d.ts +84 -0
  77. package/dist/src/implementation/string.d.ts +73 -0
  78. package/dist/src/implementation/taskenums.d.ts +77 -0
  79. package/dist/src/implementation/type.d.ts +23 -0
  80. package/dist/src/implementation/url.d.ts +22 -0
  81. package/dist/src/implementation/utils.d.ts +23 -0
  82. package/dist/src/index.d.ts +7 -0
  83. package/dist/src/index.node.d.ts +7 -0
  84. package/dist/src/list.d.ts +41 -0
  85. package/dist/src/metadata.d.ts +27 -0
  86. package/dist/src/platform/base64.d.ts +20 -0
  87. package/dist/src/platform/browser/base64.d.ts +19 -0
  88. package/dist/src/platform/browser/connection.d.ts +55 -0
  89. package/dist/src/platform/connection.d.ts +22 -0
  90. package/dist/src/platform/node/base64.d.ts +19 -0
  91. package/dist/src/platform/node/connection.d.ts +58 -0
  92. package/dist/src/public-types.d.ts +424 -0
  93. package/dist/src/reference.d.ts +208 -0
  94. package/dist/src/service.d.ts +131 -0
  95. package/dist/src/task.d.ts +148 -0
  96. package/dist/src/tsdoc-metadata.json +11 -0
  97. package/dist/storage-public.d.ts +725 -0
  98. package/dist/storage.d.ts +1391 -0
  99. package/dist/test/unit/connection.d.ts +47 -0
  100. package/dist/test/unit/testshared.d.ts +60 -0
  101. package/package.json +98 -0
@@ -0,0 +1,3656 @@
1
+ import { _isFirebaseServerApp, _getProvider, getApp, _registerComponent, registerVersion, SDK_VERSION } from '@firebase/app';
2
+ import { FirebaseError, isCloudWorkstation, pingServer, updateEmulatorBanner, createMockUserToken, getModularInstance, getDefaultEmulatorHostnameAndPort } from '@firebase/util';
3
+ import { Component } from '@firebase/component';
4
+
5
+ /**
6
+ * @license
7
+ * Copyright 2017 Google LLC
8
+ *
9
+ * Licensed under the Apache License, Version 2.0 (the "License");
10
+ * you may not use this file except in compliance with the License.
11
+ * You may obtain a copy of the License at
12
+ *
13
+ * http://www.apache.org/licenses/LICENSE-2.0
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ */
21
+ /**
22
+ * @fileoverview Constants used in the Firebase Storage library.
23
+ */
24
+ /**
25
+ * Domain name for firebase storage.
26
+ */
27
+ const DEFAULT_HOST = 'firebasestorage.googleapis.com';
28
+ /**
29
+ * The key in Firebase config json for the storage bucket.
30
+ */
31
+ const CONFIG_STORAGE_BUCKET_KEY = 'storageBucket';
32
+ /**
33
+ * 2 minutes
34
+ *
35
+ * The timeout for all operations except upload.
36
+ */
37
+ const DEFAULT_MAX_OPERATION_RETRY_TIME = 2 * 60 * 1000;
38
+ /**
39
+ * 10 minutes
40
+ *
41
+ * The timeout for upload.
42
+ */
43
+ const DEFAULT_MAX_UPLOAD_RETRY_TIME = 10 * 60 * 1000;
44
+ /**
45
+ * 1 second
46
+ */
47
+ const DEFAULT_MIN_SLEEP_TIME_MILLIS = 1000;
48
+
49
+ /**
50
+ * @license
51
+ * Copyright 2017 Google LLC
52
+ *
53
+ * Licensed under the Apache License, Version 2.0 (the "License");
54
+ * you may not use this file except in compliance with the License.
55
+ * You may obtain a copy of the License at
56
+ *
57
+ * http://www.apache.org/licenses/LICENSE-2.0
58
+ *
59
+ * Unless required by applicable law or agreed to in writing, software
60
+ * distributed under the License is distributed on an "AS IS" BASIS,
61
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
62
+ * See the License for the specific language governing permissions and
63
+ * limitations under the License.
64
+ */
65
+ /**
66
+ * An error returned by the Firebase Storage SDK.
67
+ * @public
68
+ */
69
+ class StorageError extends FirebaseError {
70
+ /**
71
+ * @param code - A `StorageErrorCode` string to be prefixed with 'storage/' and
72
+ * added to the end of the message.
73
+ * @param message - Error message.
74
+ * @param status_ - Corresponding HTTP Status Code
75
+ */
76
+ constructor(code, message, status_ = 0) {
77
+ super(prependCode(code), `Firebase Storage: ${message} (${prependCode(code)})`);
78
+ this.status_ = status_;
79
+ /**
80
+ * Stores custom error data unique to the `StorageError`.
81
+ */
82
+ this.customData = { serverResponse: null };
83
+ this._baseMessage = this.message;
84
+ // Without this, `instanceof StorageError`, in tests for example,
85
+ // returns false.
86
+ Object.setPrototypeOf(this, StorageError.prototype);
87
+ }
88
+ get status() {
89
+ return this.status_;
90
+ }
91
+ set status(status) {
92
+ this.status_ = status;
93
+ }
94
+ /**
95
+ * Compares a `StorageErrorCode` against this error's code, filtering out the prefix.
96
+ */
97
+ _codeEquals(code) {
98
+ return prependCode(code) === this.code;
99
+ }
100
+ /**
101
+ * Optional response message that was added by the server.
102
+ */
103
+ get serverResponse() {
104
+ return this.customData.serverResponse;
105
+ }
106
+ set serverResponse(serverResponse) {
107
+ this.customData.serverResponse = serverResponse;
108
+ if (this.customData.serverResponse) {
109
+ this.message = `${this._baseMessage}\n${this.customData.serverResponse}`;
110
+ }
111
+ else {
112
+ this.message = this._baseMessage;
113
+ }
114
+ }
115
+ }
116
+ /**
117
+ * @public
118
+ * Error codes that can be attached to `StorageError` objects.
119
+ */
120
+ var StorageErrorCode;
121
+ (function (StorageErrorCode) {
122
+ // Shared between all platforms
123
+ StorageErrorCode["UNKNOWN"] = "unknown";
124
+ StorageErrorCode["OBJECT_NOT_FOUND"] = "object-not-found";
125
+ StorageErrorCode["BUCKET_NOT_FOUND"] = "bucket-not-found";
126
+ StorageErrorCode["PROJECT_NOT_FOUND"] = "project-not-found";
127
+ StorageErrorCode["QUOTA_EXCEEDED"] = "quota-exceeded";
128
+ StorageErrorCode["UNAUTHENTICATED"] = "unauthenticated";
129
+ StorageErrorCode["UNAUTHORIZED"] = "unauthorized";
130
+ StorageErrorCode["UNAUTHORIZED_APP"] = "unauthorized-app";
131
+ StorageErrorCode["RETRY_LIMIT_EXCEEDED"] = "retry-limit-exceeded";
132
+ StorageErrorCode["INVALID_CHECKSUM"] = "invalid-checksum";
133
+ StorageErrorCode["CANCELED"] = "canceled";
134
+ // JS specific
135
+ StorageErrorCode["INVALID_EVENT_NAME"] = "invalid-event-name";
136
+ StorageErrorCode["INVALID_URL"] = "invalid-url";
137
+ StorageErrorCode["INVALID_DEFAULT_BUCKET"] = "invalid-default-bucket";
138
+ StorageErrorCode["NO_DEFAULT_BUCKET"] = "no-default-bucket";
139
+ StorageErrorCode["CANNOT_SLICE_BLOB"] = "cannot-slice-blob";
140
+ StorageErrorCode["SERVER_FILE_WRONG_SIZE"] = "server-file-wrong-size";
141
+ StorageErrorCode["NO_DOWNLOAD_URL"] = "no-download-url";
142
+ StorageErrorCode["INVALID_ARGUMENT"] = "invalid-argument";
143
+ StorageErrorCode["INVALID_ARGUMENT_COUNT"] = "invalid-argument-count";
144
+ StorageErrorCode["APP_DELETED"] = "app-deleted";
145
+ StorageErrorCode["INVALID_ROOT_OPERATION"] = "invalid-root-operation";
146
+ StorageErrorCode["INVALID_FORMAT"] = "invalid-format";
147
+ StorageErrorCode["INTERNAL_ERROR"] = "internal-error";
148
+ StorageErrorCode["UNSUPPORTED_ENVIRONMENT"] = "unsupported-environment";
149
+ })(StorageErrorCode || (StorageErrorCode = {}));
150
+ function prependCode(code) {
151
+ return 'storage/' + code;
152
+ }
153
+ function unknown() {
154
+ const message = 'An unknown error occurred, please check the error payload for ' +
155
+ 'server response.';
156
+ return new StorageError(StorageErrorCode.UNKNOWN, message);
157
+ }
158
+ function objectNotFound(path) {
159
+ return new StorageError(StorageErrorCode.OBJECT_NOT_FOUND, "Object '" + path + "' does not exist.");
160
+ }
161
+ function quotaExceeded(bucket) {
162
+ return new StorageError(StorageErrorCode.QUOTA_EXCEEDED, "Quota for bucket '" +
163
+ bucket +
164
+ "' exceeded, please view quota on " +
165
+ 'https://firebase.google.com/pricing/.');
166
+ }
167
+ function unauthenticated() {
168
+ const message = 'User is not authenticated, please authenticate using Firebase ' +
169
+ 'Authentication and try again.';
170
+ return new StorageError(StorageErrorCode.UNAUTHENTICATED, message);
171
+ }
172
+ function unauthorizedApp() {
173
+ return new StorageError(StorageErrorCode.UNAUTHORIZED_APP, 'This app does not have permission to access Firebase Storage on this project.');
174
+ }
175
+ function unauthorized(path) {
176
+ return new StorageError(StorageErrorCode.UNAUTHORIZED, "User does not have permission to access '" + path + "'.");
177
+ }
178
+ function retryLimitExceeded() {
179
+ return new StorageError(StorageErrorCode.RETRY_LIMIT_EXCEEDED, 'Max retry time for operation exceeded, please try again.');
180
+ }
181
+ function canceled() {
182
+ return new StorageError(StorageErrorCode.CANCELED, 'User canceled the upload/download.');
183
+ }
184
+ function invalidUrl(url) {
185
+ return new StorageError(StorageErrorCode.INVALID_URL, "Invalid URL '" + url + "'.");
186
+ }
187
+ function invalidDefaultBucket(bucket) {
188
+ return new StorageError(StorageErrorCode.INVALID_DEFAULT_BUCKET, "Invalid default bucket '" + bucket + "'.");
189
+ }
190
+ function noDefaultBucket() {
191
+ return new StorageError(StorageErrorCode.NO_DEFAULT_BUCKET, 'No default bucket ' +
192
+ "found. Did you set the '" +
193
+ CONFIG_STORAGE_BUCKET_KEY +
194
+ "' property when initializing the app?");
195
+ }
196
+ function cannotSliceBlob() {
197
+ return new StorageError(StorageErrorCode.CANNOT_SLICE_BLOB, 'Cannot slice blob for upload. Please retry the upload.');
198
+ }
199
+ function serverFileWrongSize() {
200
+ return new StorageError(StorageErrorCode.SERVER_FILE_WRONG_SIZE, 'Server recorded incorrect upload file size, please retry the upload.');
201
+ }
202
+ function noDownloadURL() {
203
+ return new StorageError(StorageErrorCode.NO_DOWNLOAD_URL, 'The given file does not have any download URLs.');
204
+ }
205
+ function missingPolyFill(polyFill) {
206
+ return new StorageError(StorageErrorCode.UNSUPPORTED_ENVIRONMENT, `${polyFill} is missing. Make sure to install the required polyfills. See https://firebase.google.com/docs/web/environments-js-sdk#polyfills for more information.`);
207
+ }
208
+ /**
209
+ * @internal
210
+ */
211
+ function invalidArgument(message) {
212
+ return new StorageError(StorageErrorCode.INVALID_ARGUMENT, message);
213
+ }
214
+ function appDeleted() {
215
+ return new StorageError(StorageErrorCode.APP_DELETED, 'The Firebase app was deleted.');
216
+ }
217
+ /**
218
+ * @param name - The name of the operation that was invalid.
219
+ *
220
+ * @internal
221
+ */
222
+ function invalidRootOperation(name) {
223
+ return new StorageError(StorageErrorCode.INVALID_ROOT_OPERATION, "The operation '" +
224
+ name +
225
+ "' cannot be performed on a root reference, create a non-root " +
226
+ "reference using child, such as .child('file.png').");
227
+ }
228
+ /**
229
+ * @param format - The format that was not valid.
230
+ * @param message - A message describing the format violation.
231
+ */
232
+ function invalidFormat(format, message) {
233
+ return new StorageError(StorageErrorCode.INVALID_FORMAT, "String does not match format '" + format + "': " + message);
234
+ }
235
+ /**
236
+ * @param message - A message describing the internal error.
237
+ */
238
+ function internalError(message) {
239
+ throw new StorageError(StorageErrorCode.INTERNAL_ERROR, 'Internal error: ' + message);
240
+ }
241
+
242
+ /**
243
+ * @license
244
+ * Copyright 2017 Google LLC
245
+ *
246
+ * Licensed under the Apache License, Version 2.0 (the "License");
247
+ * you may not use this file except in compliance with the License.
248
+ * You may obtain a copy of the License at
249
+ *
250
+ * http://www.apache.org/licenses/LICENSE-2.0
251
+ *
252
+ * Unless required by applicable law or agreed to in writing, software
253
+ * distributed under the License is distributed on an "AS IS" BASIS,
254
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
255
+ * See the License for the specific language governing permissions and
256
+ * limitations under the License.
257
+ */
258
+ /**
259
+ * Firebase Storage location data.
260
+ *
261
+ * @internal
262
+ */
263
+ class Location {
264
+ constructor(bucket, path) {
265
+ this.bucket = bucket;
266
+ this.path_ = path;
267
+ }
268
+ get path() {
269
+ return this.path_;
270
+ }
271
+ get isRoot() {
272
+ return this.path.length === 0;
273
+ }
274
+ fullServerUrl() {
275
+ const encode = encodeURIComponent;
276
+ return '/b/' + encode(this.bucket) + '/o/' + encode(this.path);
277
+ }
278
+ bucketOnlyServerUrl() {
279
+ const encode = encodeURIComponent;
280
+ return '/b/' + encode(this.bucket) + '/o';
281
+ }
282
+ static makeFromBucketSpec(bucketString, host) {
283
+ let bucketLocation;
284
+ try {
285
+ bucketLocation = Location.makeFromUrl(bucketString, host);
286
+ }
287
+ catch (e) {
288
+ // Not valid URL, use as-is. This lets you put bare bucket names in
289
+ // config.
290
+ return new Location(bucketString, '');
291
+ }
292
+ if (bucketLocation.path === '') {
293
+ return bucketLocation;
294
+ }
295
+ else {
296
+ throw invalidDefaultBucket(bucketString);
297
+ }
298
+ }
299
+ static makeFromUrl(url, host) {
300
+ let location = null;
301
+ const bucketDomain = '([A-Za-z0-9.\\-_]+)';
302
+ function gsModify(loc) {
303
+ if (loc.path.charAt(loc.path.length - 1) === '/') {
304
+ loc.path_ = loc.path_.slice(0, -1);
305
+ }
306
+ }
307
+ const gsPath = '(/(.*))?$';
308
+ const gsRegex = new RegExp('^gs://' + bucketDomain + gsPath, 'i');
309
+ const gsIndices = { bucket: 1, path: 3 };
310
+ function httpModify(loc) {
311
+ loc.path_ = decodeURIComponent(loc.path);
312
+ }
313
+ const version = 'v[A-Za-z0-9_]+';
314
+ const firebaseStorageHost = host.replace(/[.]/g, '\\.');
315
+ const firebaseStoragePath = '(/([^?#]*).*)?$';
316
+ const firebaseStorageRegExp = new RegExp(`^https?://${firebaseStorageHost}/${version}/b/${bucketDomain}/o${firebaseStoragePath}`, 'i');
317
+ const firebaseStorageIndices = { bucket: 1, path: 3 };
318
+ const cloudStorageHost = host === DEFAULT_HOST
319
+ ? '(?:storage.googleapis.com|storage.cloud.google.com)'
320
+ : host;
321
+ const cloudStoragePath = '([^?#]*)';
322
+ const cloudStorageRegExp = new RegExp(`^https?://${cloudStorageHost}/${bucketDomain}/${cloudStoragePath}`, 'i');
323
+ const cloudStorageIndices = { bucket: 1, path: 2 };
324
+ const groups = [
325
+ { regex: gsRegex, indices: gsIndices, postModify: gsModify },
326
+ {
327
+ regex: firebaseStorageRegExp,
328
+ indices: firebaseStorageIndices,
329
+ postModify: httpModify
330
+ },
331
+ {
332
+ regex: cloudStorageRegExp,
333
+ indices: cloudStorageIndices,
334
+ postModify: httpModify
335
+ }
336
+ ];
337
+ for (let i = 0; i < groups.length; i++) {
338
+ const group = groups[i];
339
+ const captures = group.regex.exec(url);
340
+ if (captures) {
341
+ const bucketValue = captures[group.indices.bucket];
342
+ let pathValue = captures[group.indices.path];
343
+ if (!pathValue) {
344
+ pathValue = '';
345
+ }
346
+ location = new Location(bucketValue, pathValue);
347
+ group.postModify(location);
348
+ break;
349
+ }
350
+ }
351
+ if (location == null) {
352
+ throw invalidUrl(url);
353
+ }
354
+ return location;
355
+ }
356
+ }
357
+
358
+ /**
359
+ * A request whose promise always fails.
360
+ */
361
+ class FailRequest {
362
+ constructor(error) {
363
+ this.promise_ = Promise.reject(error);
364
+ }
365
+ /** @inheritDoc */
366
+ getPromise() {
367
+ return this.promise_;
368
+ }
369
+ /** @inheritDoc */
370
+ cancel(_appDelete = false) { }
371
+ }
372
+
373
+ /**
374
+ * @license
375
+ * Copyright 2017 Google LLC
376
+ *
377
+ * Licensed under the Apache License, Version 2.0 (the "License");
378
+ * you may not use this file except in compliance with the License.
379
+ * You may obtain a copy of the License at
380
+ *
381
+ * http://www.apache.org/licenses/LICENSE-2.0
382
+ *
383
+ * Unless required by applicable law or agreed to in writing, software
384
+ * distributed under the License is distributed on an "AS IS" BASIS,
385
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
386
+ * See the License for the specific language governing permissions and
387
+ * limitations under the License.
388
+ */
389
+ /**
390
+ * Accepts a callback for an action to perform (`doRequest`),
391
+ * and then a callback for when the backoff has completed (`backoffCompleteCb`).
392
+ * The callback sent to start requires an argument to call (`onRequestComplete`).
393
+ * When `start` calls `doRequest`, it passes a callback for when the request has
394
+ * completed, `onRequestComplete`. Based on this, the backoff continues, with
395
+ * another call to `doRequest` and the above loop continues until the timeout
396
+ * is hit, or a successful response occurs.
397
+ * @description
398
+ * @param doRequest Callback to perform request
399
+ * @param backoffCompleteCb Callback to call when backoff has been completed
400
+ */
401
+ function start(doRequest,
402
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
403
+ backoffCompleteCb, timeout) {
404
+ // TODO(andysoto): make this code cleaner (probably refactor into an actual
405
+ // type instead of a bunch of functions with state shared in the closure)
406
+ let waitSeconds = 1;
407
+ // Would type this as "number" but that doesn't work for Node so ¯\_(ツ)_/¯
408
+ // TODO: find a way to exclude Node type definition for storage because storage only works in browser
409
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
410
+ let retryTimeoutId = null;
411
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
412
+ let globalTimeoutId = null;
413
+ let hitTimeout = false;
414
+ let cancelState = 0;
415
+ function canceled() {
416
+ return cancelState === 2;
417
+ }
418
+ let triggeredCallback = false;
419
+ function triggerCallback(...args) {
420
+ if (!triggeredCallback) {
421
+ triggeredCallback = true;
422
+ backoffCompleteCb.apply(null, args);
423
+ }
424
+ }
425
+ function callWithDelay(millis) {
426
+ retryTimeoutId = setTimeout(() => {
427
+ retryTimeoutId = null;
428
+ doRequest(responseHandler, canceled());
429
+ }, millis);
430
+ }
431
+ function clearGlobalTimeout() {
432
+ if (globalTimeoutId) {
433
+ clearTimeout(globalTimeoutId);
434
+ }
435
+ }
436
+ function responseHandler(success, ...args) {
437
+ if (triggeredCallback) {
438
+ clearGlobalTimeout();
439
+ return;
440
+ }
441
+ if (success) {
442
+ clearGlobalTimeout();
443
+ triggerCallback.call(null, success, ...args);
444
+ return;
445
+ }
446
+ const mustStop = canceled() || hitTimeout;
447
+ if (mustStop) {
448
+ clearGlobalTimeout();
449
+ triggerCallback.call(null, success, ...args);
450
+ return;
451
+ }
452
+ if (waitSeconds < 64) {
453
+ /* TODO(andysoto): don't back off so quickly if we know we're offline. */
454
+ waitSeconds *= 2;
455
+ }
456
+ let waitMillis;
457
+ if (cancelState === 1) {
458
+ cancelState = 2;
459
+ waitMillis = 0;
460
+ }
461
+ else {
462
+ waitMillis = (waitSeconds + Math.random()) * 1000;
463
+ }
464
+ callWithDelay(waitMillis);
465
+ }
466
+ let stopped = false;
467
+ function stop(wasTimeout) {
468
+ if (stopped) {
469
+ return;
470
+ }
471
+ stopped = true;
472
+ clearGlobalTimeout();
473
+ if (triggeredCallback) {
474
+ return;
475
+ }
476
+ if (retryTimeoutId !== null) {
477
+ if (!wasTimeout) {
478
+ cancelState = 2;
479
+ }
480
+ clearTimeout(retryTimeoutId);
481
+ callWithDelay(0);
482
+ }
483
+ else {
484
+ if (!wasTimeout) {
485
+ cancelState = 1;
486
+ }
487
+ }
488
+ }
489
+ callWithDelay(0);
490
+ globalTimeoutId = setTimeout(() => {
491
+ hitTimeout = true;
492
+ stop(true);
493
+ }, timeout);
494
+ return stop;
495
+ }
496
+ /**
497
+ * Stops the retry loop from repeating.
498
+ * If the function is currently "in between" retries, it is invoked immediately
499
+ * with the second parameter as "true". Otherwise, it will be invoked once more
500
+ * after the current invocation finishes iff the current invocation would have
501
+ * triggered another retry.
502
+ */
503
+ function stop(id) {
504
+ id(false);
505
+ }
506
+
507
+ /**
508
+ * @license
509
+ * Copyright 2017 Google LLC
510
+ *
511
+ * Licensed under the Apache License, Version 2.0 (the "License");
512
+ * you may not use this file except in compliance with the License.
513
+ * You may obtain a copy of the License at
514
+ *
515
+ * http://www.apache.org/licenses/LICENSE-2.0
516
+ *
517
+ * Unless required by applicable law or agreed to in writing, software
518
+ * distributed under the License is distributed on an "AS IS" BASIS,
519
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
520
+ * See the License for the specific language governing permissions and
521
+ * limitations under the License.
522
+ */
523
+ function isJustDef(p) {
524
+ return p !== void 0;
525
+ }
526
+ // eslint-disable-next-line @typescript-eslint/ban-types
527
+ function isFunction(p) {
528
+ return typeof p === 'function';
529
+ }
530
+ function isNonArrayObject(p) {
531
+ return typeof p === 'object' && !Array.isArray(p);
532
+ }
533
+ function isString(p) {
534
+ return typeof p === 'string' || p instanceof String;
535
+ }
536
+ function isNativeBlob(p) {
537
+ return isNativeBlobDefined() && p instanceof Blob;
538
+ }
539
+ function isNativeBlobDefined() {
540
+ return typeof Blob !== 'undefined';
541
+ }
542
+ function validateNumber(argument, minValue, maxValue, value) {
543
+ if (value < minValue) {
544
+ throw invalidArgument(`Invalid value for '${argument}'. Expected ${minValue} or greater.`);
545
+ }
546
+ if (value > maxValue) {
547
+ throw invalidArgument(`Invalid value for '${argument}'. Expected ${maxValue} or less.`);
548
+ }
549
+ }
550
+
551
+ /**
552
+ * @license
553
+ * Copyright 2017 Google LLC
554
+ *
555
+ * Licensed under the Apache License, Version 2.0 (the "License");
556
+ * you may not use this file except in compliance with the License.
557
+ * You may obtain a copy of the License at
558
+ *
559
+ * http://www.apache.org/licenses/LICENSE-2.0
560
+ *
561
+ * Unless required by applicable law or agreed to in writing, software
562
+ * distributed under the License is distributed on an "AS IS" BASIS,
563
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
564
+ * See the License for the specific language governing permissions and
565
+ * limitations under the License.
566
+ */
567
+ function makeUrl(urlPart, host, protocol) {
568
+ let origin = host;
569
+ if (protocol == null) {
570
+ origin = `https://${host}`;
571
+ }
572
+ return `${protocol}://${origin}/v0${urlPart}`;
573
+ }
574
+ function makeQueryString(params) {
575
+ const encode = encodeURIComponent;
576
+ let queryPart = '?';
577
+ for (const key in params) {
578
+ if (params.hasOwnProperty(key)) {
579
+ const nextPart = encode(key) + '=' + encode(params[key]);
580
+ queryPart = queryPart + nextPart + '&';
581
+ }
582
+ }
583
+ // Chop off the extra '&' or '?' on the end
584
+ queryPart = queryPart.slice(0, -1);
585
+ return queryPart;
586
+ }
587
+
588
+ /**
589
+ * Error codes for requests made by the XhrIo wrapper.
590
+ */
591
+ var ErrorCode;
592
+ (function (ErrorCode) {
593
+ ErrorCode[ErrorCode["NO_ERROR"] = 0] = "NO_ERROR";
594
+ ErrorCode[ErrorCode["NETWORK_ERROR"] = 1] = "NETWORK_ERROR";
595
+ ErrorCode[ErrorCode["ABORT"] = 2] = "ABORT";
596
+ })(ErrorCode || (ErrorCode = {}));
597
+
598
+ /**
599
+ * @license
600
+ * Copyright 2022 Google LLC
601
+ *
602
+ * Licensed under the Apache License, Version 2.0 (the "License");
603
+ * you may not use this file except in compliance with the License.
604
+ * You may obtain a copy of the License at
605
+ *
606
+ * http://www.apache.org/licenses/LICENSE-2.0
607
+ *
608
+ * Unless required by applicable law or agreed to in writing, software
609
+ * distributed under the License is distributed on an "AS IS" BASIS,
610
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
611
+ * See the License for the specific language governing permissions and
612
+ * limitations under the License.
613
+ */
614
+ /**
615
+ * Checks the status code to see if the action should be retried.
616
+ *
617
+ * @param status Current HTTP status code returned by server.
618
+ * @param additionalRetryCodes additional retry codes to check against
619
+ */
620
+ function isRetryStatusCode(status, additionalRetryCodes) {
621
+ // The codes for which to retry came from this page:
622
+ // https://cloud.google.com/storage/docs/exponential-backoff
623
+ const isFiveHundredCode = status >= 500 && status < 600;
624
+ const extraRetryCodes = [
625
+ // Request Timeout: web server didn't receive full request in time.
626
+ 408,
627
+ // Too Many Requests: you're getting rate-limited, basically.
628
+ 429
629
+ ];
630
+ const isExtraRetryCode = extraRetryCodes.indexOf(status) !== -1;
631
+ const isAdditionalRetryCode = additionalRetryCodes.indexOf(status) !== -1;
632
+ return isFiveHundredCode || isExtraRetryCode || isAdditionalRetryCode;
633
+ }
634
+
635
+ /**
636
+ * @license
637
+ * Copyright 2017 Google LLC
638
+ *
639
+ * Licensed under the Apache License, Version 2.0 (the "License");
640
+ * you may not use this file except in compliance with the License.
641
+ * You may obtain a copy of the License at
642
+ *
643
+ * http://www.apache.org/licenses/LICENSE-2.0
644
+ *
645
+ * Unless required by applicable law or agreed to in writing, software
646
+ * distributed under the License is distributed on an "AS IS" BASIS,
647
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
648
+ * See the License for the specific language governing permissions and
649
+ * limitations under the License.
650
+ */
651
+ /**
652
+ * Handles network logic for all Storage Requests, including error reporting and
653
+ * retries with backoff.
654
+ *
655
+ * @param I - the type of the backend's network response.
656
+ * @param - O the output type used by the rest of the SDK. The conversion
657
+ * happens in the specified `callback_`.
658
+ */
659
+ class NetworkRequest {
660
+ constructor(url_, method_, headers_, body_, successCodes_, additionalRetryCodes_, callback_, errorCallback_, timeout_, progressCallback_, connectionFactory_, retry = true, isUsingEmulator = false) {
661
+ this.url_ = url_;
662
+ this.method_ = method_;
663
+ this.headers_ = headers_;
664
+ this.body_ = body_;
665
+ this.successCodes_ = successCodes_;
666
+ this.additionalRetryCodes_ = additionalRetryCodes_;
667
+ this.callback_ = callback_;
668
+ this.errorCallback_ = errorCallback_;
669
+ this.timeout_ = timeout_;
670
+ this.progressCallback_ = progressCallback_;
671
+ this.connectionFactory_ = connectionFactory_;
672
+ this.retry = retry;
673
+ this.isUsingEmulator = isUsingEmulator;
674
+ this.pendingConnection_ = null;
675
+ this.backoffId_ = null;
676
+ this.canceled_ = false;
677
+ this.appDelete_ = false;
678
+ this.promise_ = new Promise((resolve, reject) => {
679
+ this.resolve_ = resolve;
680
+ this.reject_ = reject;
681
+ this.start_();
682
+ });
683
+ }
684
+ /**
685
+ * Actually starts the retry loop.
686
+ */
687
+ start_() {
688
+ const doTheRequest = (backoffCallback, canceled) => {
689
+ if (canceled) {
690
+ backoffCallback(false, new RequestEndStatus(false, null, true));
691
+ return;
692
+ }
693
+ const connection = this.connectionFactory_();
694
+ this.pendingConnection_ = connection;
695
+ const progressListener = progressEvent => {
696
+ const loaded = progressEvent.loaded;
697
+ const total = progressEvent.lengthComputable ? progressEvent.total : -1;
698
+ if (this.progressCallback_ !== null) {
699
+ this.progressCallback_(loaded, total);
700
+ }
701
+ };
702
+ if (this.progressCallback_ !== null) {
703
+ connection.addUploadProgressListener(progressListener);
704
+ }
705
+ // connection.send() never rejects, so we don't need to have a error handler or use catch on the returned promise.
706
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
707
+ connection
708
+ .send(this.url_, this.method_, this.isUsingEmulator, this.body_, this.headers_)
709
+ .then(() => {
710
+ if (this.progressCallback_ !== null) {
711
+ connection.removeUploadProgressListener(progressListener);
712
+ }
713
+ this.pendingConnection_ = null;
714
+ const hitServer = connection.getErrorCode() === ErrorCode.NO_ERROR;
715
+ const status = connection.getStatus();
716
+ if (!hitServer ||
717
+ (isRetryStatusCode(status, this.additionalRetryCodes_) &&
718
+ this.retry)) {
719
+ const wasCanceled = connection.getErrorCode() === ErrorCode.ABORT;
720
+ backoffCallback(false, new RequestEndStatus(false, null, wasCanceled));
721
+ return;
722
+ }
723
+ const successCode = this.successCodes_.indexOf(status) !== -1;
724
+ backoffCallback(true, new RequestEndStatus(successCode, connection));
725
+ });
726
+ };
727
+ /**
728
+ * @param requestWentThrough - True if the request eventually went
729
+ * through, false if it hit the retry limit or was canceled.
730
+ */
731
+ const backoffDone = (requestWentThrough, status) => {
732
+ const resolve = this.resolve_;
733
+ const reject = this.reject_;
734
+ const connection = status.connection;
735
+ if (status.wasSuccessCode) {
736
+ try {
737
+ const result = this.callback_(connection, connection.getResponse());
738
+ if (isJustDef(result)) {
739
+ resolve(result);
740
+ }
741
+ else {
742
+ resolve();
743
+ }
744
+ }
745
+ catch (e) {
746
+ reject(e);
747
+ }
748
+ }
749
+ else {
750
+ if (connection !== null) {
751
+ const err = unknown();
752
+ err.serverResponse = connection.getErrorText();
753
+ if (this.errorCallback_) {
754
+ reject(this.errorCallback_(connection, err));
755
+ }
756
+ else {
757
+ reject(err);
758
+ }
759
+ }
760
+ else {
761
+ if (status.canceled) {
762
+ const err = this.appDelete_ ? appDeleted() : canceled();
763
+ reject(err);
764
+ }
765
+ else {
766
+ const err = retryLimitExceeded();
767
+ reject(err);
768
+ }
769
+ }
770
+ }
771
+ };
772
+ if (this.canceled_) {
773
+ backoffDone(false, new RequestEndStatus(false, null, true));
774
+ }
775
+ else {
776
+ this.backoffId_ = start(doTheRequest, backoffDone, this.timeout_);
777
+ }
778
+ }
779
+ /** @inheritDoc */
780
+ getPromise() {
781
+ return this.promise_;
782
+ }
783
+ /** @inheritDoc */
784
+ cancel(appDelete) {
785
+ this.canceled_ = true;
786
+ this.appDelete_ = appDelete || false;
787
+ if (this.backoffId_ !== null) {
788
+ stop(this.backoffId_);
789
+ }
790
+ if (this.pendingConnection_ !== null) {
791
+ this.pendingConnection_.abort();
792
+ }
793
+ }
794
+ }
795
+ /**
796
+ * A collection of information about the result of a network request.
797
+ * @param opt_canceled - Defaults to false.
798
+ */
799
+ class RequestEndStatus {
800
+ constructor(wasSuccessCode, connection, canceled) {
801
+ this.wasSuccessCode = wasSuccessCode;
802
+ this.connection = connection;
803
+ this.canceled = !!canceled;
804
+ }
805
+ }
806
+ function addAuthHeader_(headers, authToken) {
807
+ if (authToken !== null && authToken.length > 0) {
808
+ headers['Authorization'] = 'Firebase ' + authToken;
809
+ }
810
+ }
811
+ function addVersionHeader_(headers, firebaseVersion) {
812
+ headers['X-Firebase-Storage-Version'] =
813
+ 'webjs/' + (firebaseVersion ?? 'AppManager');
814
+ }
815
+ function addGmpidHeader_(headers, appId) {
816
+ if (appId) {
817
+ headers['X-Firebase-GMPID'] = appId;
818
+ }
819
+ }
820
+ function addAppCheckHeader_(headers, appCheckToken) {
821
+ if (appCheckToken !== null) {
822
+ headers['X-Firebase-AppCheck'] = appCheckToken;
823
+ }
824
+ }
825
+ function makeRequest(requestInfo, appId, authToken, appCheckToken, requestFactory, firebaseVersion, retry = true, isUsingEmulator = false) {
826
+ const queryPart = makeQueryString(requestInfo.urlParams);
827
+ const url = requestInfo.url + queryPart;
828
+ const headers = Object.assign({}, requestInfo.headers);
829
+ addGmpidHeader_(headers, appId);
830
+ addAuthHeader_(headers, authToken);
831
+ addVersionHeader_(headers, firebaseVersion);
832
+ addAppCheckHeader_(headers, appCheckToken);
833
+ return new NetworkRequest(url, requestInfo.method, headers, requestInfo.body, requestInfo.successCodes, requestInfo.additionalRetryCodes, requestInfo.handler, requestInfo.errorHandler, requestInfo.timeout, requestInfo.progressCallback, requestFactory, retry, isUsingEmulator);
834
+ }
835
+
836
+ /**
837
+ * @license
838
+ * Copyright 2017 Google LLC
839
+ *
840
+ * Licensed under the Apache License, Version 2.0 (the "License");
841
+ * you may not use this file except in compliance with the License.
842
+ * You may obtain a copy of the License at
843
+ *
844
+ * http://www.apache.org/licenses/LICENSE-2.0
845
+ *
846
+ * Unless required by applicable law or agreed to in writing, software
847
+ * distributed under the License is distributed on an "AS IS" BASIS,
848
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
849
+ * See the License for the specific language governing permissions and
850
+ * limitations under the License.
851
+ */
852
+ function getBlobBuilder() {
853
+ if (typeof BlobBuilder !== 'undefined') {
854
+ return BlobBuilder;
855
+ }
856
+ else if (typeof WebKitBlobBuilder !== 'undefined') {
857
+ return WebKitBlobBuilder;
858
+ }
859
+ else {
860
+ return undefined;
861
+ }
862
+ }
863
+ /**
864
+ * Concatenates one or more values together and converts them to a Blob.
865
+ *
866
+ * @param args The values that will make up the resulting blob.
867
+ * @return The blob.
868
+ */
869
+ function getBlob$1(...args) {
870
+ const BlobBuilder = getBlobBuilder();
871
+ if (BlobBuilder !== undefined) {
872
+ const bb = new BlobBuilder();
873
+ for (let i = 0; i < args.length; i++) {
874
+ bb.append(args[i]);
875
+ }
876
+ return bb.getBlob();
877
+ }
878
+ else {
879
+ if (isNativeBlobDefined()) {
880
+ return new Blob(args);
881
+ }
882
+ else {
883
+ throw new StorageError(StorageErrorCode.UNSUPPORTED_ENVIRONMENT, "This browser doesn't seem to support creating Blobs");
884
+ }
885
+ }
886
+ }
887
+ /**
888
+ * Slices the blob. The returned blob contains data from the start byte
889
+ * (inclusive) till the end byte (exclusive). Negative indices cannot be used.
890
+ *
891
+ * @param blob The blob to be sliced.
892
+ * @param start Index of the starting byte.
893
+ * @param end Index of the ending byte.
894
+ * @return The blob slice or null if not supported.
895
+ */
896
+ function sliceBlob(blob, start, end) {
897
+ if (blob.webkitSlice) {
898
+ return blob.webkitSlice(start, end);
899
+ }
900
+ else if (blob.mozSlice) {
901
+ return blob.mozSlice(start, end);
902
+ }
903
+ else if (blob.slice) {
904
+ return blob.slice(start, end);
905
+ }
906
+ return null;
907
+ }
908
+
909
+ /**
910
+ * @license
911
+ * Copyright 2021 Google LLC
912
+ *
913
+ * Licensed under the Apache License, Version 2.0 (the "License");
914
+ * you may not use this file except in compliance with the License.
915
+ * You may obtain a copy of the License at
916
+ *
917
+ * http://www.apache.org/licenses/LICENSE-2.0
918
+ *
919
+ * Unless required by applicable law or agreed to in writing, software
920
+ * distributed under the License is distributed on an "AS IS" BASIS,
921
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
922
+ * See the License for the specific language governing permissions and
923
+ * limitations under the License.
924
+ */
925
+ /** Converts a Base64 encoded string to a binary string. */
926
+ function decodeBase64(encoded) {
927
+ if (typeof atob === 'undefined') {
928
+ throw missingPolyFill('base-64');
929
+ }
930
+ return atob(encoded);
931
+ }
932
+
933
+ /**
934
+ * @license
935
+ * Copyright 2017 Google LLC
936
+ *
937
+ * Licensed under the Apache License, Version 2.0 (the "License");
938
+ * you may not use this file except in compliance with the License.
939
+ * You may obtain a copy of the License at
940
+ *
941
+ * http://www.apache.org/licenses/LICENSE-2.0
942
+ *
943
+ * Unless required by applicable law or agreed to in writing, software
944
+ * distributed under the License is distributed on an "AS IS" BASIS,
945
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
946
+ * See the License for the specific language governing permissions and
947
+ * limitations under the License.
948
+ */
949
+ /**
950
+ * An enumeration of the possible string formats for upload.
951
+ * @public
952
+ */
953
+ const StringFormat = {
954
+ /**
955
+ * Indicates the string should be interpreted "raw", that is, as normal text.
956
+ * The string will be interpreted as UTF-16, then uploaded as a UTF-8 byte
957
+ * sequence.
958
+ * Example: The string 'Hello! \\ud83d\\ude0a' becomes the byte sequence
959
+ * 48 65 6c 6c 6f 21 20 f0 9f 98 8a
960
+ */
961
+ RAW: 'raw',
962
+ /**
963
+ * Indicates the string should be interpreted as base64-encoded data.
964
+ * Padding characters (trailing '='s) are optional.
965
+ * Example: The string 'rWmO++E6t7/rlw==' becomes the byte sequence
966
+ * ad 69 8e fb e1 3a b7 bf eb 97
967
+ */
968
+ BASE64: 'base64',
969
+ /**
970
+ * Indicates the string should be interpreted as base64url-encoded data.
971
+ * Padding characters (trailing '='s) are optional.
972
+ * Example: The string 'rWmO--E6t7_rlw==' becomes the byte sequence
973
+ * ad 69 8e fb e1 3a b7 bf eb 97
974
+ */
975
+ BASE64URL: 'base64url',
976
+ /**
977
+ * Indicates the string is a data URL, such as one obtained from
978
+ * canvas.toDataURL().
979
+ * Example: the string 'data:application/octet-stream;base64,aaaa'
980
+ * becomes the byte sequence
981
+ * 69 a6 9a
982
+ * (the content-type "application/octet-stream" is also applied, but can
983
+ * be overridden in the metadata object).
984
+ */
985
+ DATA_URL: 'data_url'
986
+ };
987
+ class StringData {
988
+ constructor(data, contentType) {
989
+ this.data = data;
990
+ this.contentType = contentType || null;
991
+ }
992
+ }
993
+ /**
994
+ * @internal
995
+ */
996
+ function dataFromString(format, stringData) {
997
+ switch (format) {
998
+ case StringFormat.RAW:
999
+ return new StringData(utf8Bytes_(stringData));
1000
+ case StringFormat.BASE64:
1001
+ case StringFormat.BASE64URL:
1002
+ return new StringData(base64Bytes_(format, stringData));
1003
+ case StringFormat.DATA_URL:
1004
+ return new StringData(dataURLBytes_(stringData), dataURLContentType_(stringData));
1005
+ // do nothing
1006
+ }
1007
+ // assert(false);
1008
+ throw unknown();
1009
+ }
1010
+ function utf8Bytes_(value) {
1011
+ const b = [];
1012
+ for (let i = 0; i < value.length; i++) {
1013
+ let c = value.charCodeAt(i);
1014
+ if (c <= 127) {
1015
+ b.push(c);
1016
+ }
1017
+ else {
1018
+ if (c <= 2047) {
1019
+ b.push(192 | (c >> 6), 128 | (c & 63));
1020
+ }
1021
+ else {
1022
+ if ((c & 64512) === 55296) {
1023
+ // The start of a surrogate pair.
1024
+ const valid = i < value.length - 1 && (value.charCodeAt(i + 1) & 64512) === 56320;
1025
+ if (!valid) {
1026
+ // The second surrogate wasn't there.
1027
+ b.push(239, 191, 189);
1028
+ }
1029
+ else {
1030
+ const hi = c;
1031
+ const lo = value.charCodeAt(++i);
1032
+ c = 65536 | ((hi & 1023) << 10) | (lo & 1023);
1033
+ b.push(240 | (c >> 18), 128 | ((c >> 12) & 63), 128 | ((c >> 6) & 63), 128 | (c & 63));
1034
+ }
1035
+ }
1036
+ else {
1037
+ if ((c & 64512) === 56320) {
1038
+ // Invalid low surrogate.
1039
+ b.push(239, 191, 189);
1040
+ }
1041
+ else {
1042
+ b.push(224 | (c >> 12), 128 | ((c >> 6) & 63), 128 | (c & 63));
1043
+ }
1044
+ }
1045
+ }
1046
+ }
1047
+ }
1048
+ return new Uint8Array(b);
1049
+ }
1050
+ function percentEncodedBytes_(value) {
1051
+ let decoded;
1052
+ try {
1053
+ decoded = decodeURIComponent(value);
1054
+ }
1055
+ catch (e) {
1056
+ throw invalidFormat(StringFormat.DATA_URL, 'Malformed data URL.');
1057
+ }
1058
+ return utf8Bytes_(decoded);
1059
+ }
1060
+ function base64Bytes_(format, value) {
1061
+ switch (format) {
1062
+ case StringFormat.BASE64: {
1063
+ const hasMinus = value.indexOf('-') !== -1;
1064
+ const hasUnder = value.indexOf('_') !== -1;
1065
+ if (hasMinus || hasUnder) {
1066
+ const invalidChar = hasMinus ? '-' : '_';
1067
+ throw invalidFormat(format, "Invalid character '" +
1068
+ invalidChar +
1069
+ "' found: is it base64url encoded?");
1070
+ }
1071
+ break;
1072
+ }
1073
+ case StringFormat.BASE64URL: {
1074
+ const hasPlus = value.indexOf('+') !== -1;
1075
+ const hasSlash = value.indexOf('/') !== -1;
1076
+ if (hasPlus || hasSlash) {
1077
+ const invalidChar = hasPlus ? '+' : '/';
1078
+ throw invalidFormat(format, "Invalid character '" + invalidChar + "' found: is it base64 encoded?");
1079
+ }
1080
+ value = value.replace(/-/g, '+').replace(/_/g, '/');
1081
+ break;
1082
+ }
1083
+ // do nothing
1084
+ }
1085
+ let bytes;
1086
+ try {
1087
+ bytes = decodeBase64(value);
1088
+ }
1089
+ catch (e) {
1090
+ if (e.message.includes('polyfill')) {
1091
+ throw e;
1092
+ }
1093
+ throw invalidFormat(format, 'Invalid character found');
1094
+ }
1095
+ const array = new Uint8Array(bytes.length);
1096
+ for (let i = 0; i < bytes.length; i++) {
1097
+ array[i] = bytes.charCodeAt(i);
1098
+ }
1099
+ return array;
1100
+ }
1101
+ class DataURLParts {
1102
+ constructor(dataURL) {
1103
+ this.base64 = false;
1104
+ this.contentType = null;
1105
+ const matches = dataURL.match(/^data:([^,]+)?,/);
1106
+ if (matches === null) {
1107
+ throw invalidFormat(StringFormat.DATA_URL, "Must be formatted 'data:[<mediatype>][;base64],<data>");
1108
+ }
1109
+ const middle = matches[1] || null;
1110
+ if (middle != null) {
1111
+ this.base64 = endsWith(middle, ';base64');
1112
+ this.contentType = this.base64
1113
+ ? middle.substring(0, middle.length - ';base64'.length)
1114
+ : middle;
1115
+ }
1116
+ this.rest = dataURL.substring(dataURL.indexOf(',') + 1);
1117
+ }
1118
+ }
1119
+ function dataURLBytes_(dataUrl) {
1120
+ const parts = new DataURLParts(dataUrl);
1121
+ if (parts.base64) {
1122
+ return base64Bytes_(StringFormat.BASE64, parts.rest);
1123
+ }
1124
+ else {
1125
+ return percentEncodedBytes_(parts.rest);
1126
+ }
1127
+ }
1128
+ function dataURLContentType_(dataUrl) {
1129
+ const parts = new DataURLParts(dataUrl);
1130
+ return parts.contentType;
1131
+ }
1132
+ function endsWith(s, end) {
1133
+ const longEnough = s.length >= end.length;
1134
+ if (!longEnough) {
1135
+ return false;
1136
+ }
1137
+ return s.substring(s.length - end.length) === end;
1138
+ }
1139
+
1140
+ /**
1141
+ * @license
1142
+ * Copyright 2017 Google LLC
1143
+ *
1144
+ * Licensed under the Apache License, Version 2.0 (the "License");
1145
+ * you may not use this file except in compliance with the License.
1146
+ * You may obtain a copy of the License at
1147
+ *
1148
+ * http://www.apache.org/licenses/LICENSE-2.0
1149
+ *
1150
+ * Unless required by applicable law or agreed to in writing, software
1151
+ * distributed under the License is distributed on an "AS IS" BASIS,
1152
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1153
+ * See the License for the specific language governing permissions and
1154
+ * limitations under the License.
1155
+ */
1156
+ /**
1157
+ * @param opt_elideCopy - If true, doesn't copy mutable input data
1158
+ * (e.g. Uint8Arrays). Pass true only if you know the objects will not be
1159
+ * modified after this blob's construction.
1160
+ *
1161
+ * @internal
1162
+ */
1163
+ class FbsBlob {
1164
+ constructor(data, elideCopy) {
1165
+ let size = 0;
1166
+ let blobType = '';
1167
+ if (isNativeBlob(data)) {
1168
+ this.data_ = data;
1169
+ size = data.size;
1170
+ blobType = data.type;
1171
+ }
1172
+ else if (data instanceof ArrayBuffer) {
1173
+ if (elideCopy) {
1174
+ this.data_ = new Uint8Array(data);
1175
+ }
1176
+ else {
1177
+ this.data_ = new Uint8Array(data.byteLength);
1178
+ this.data_.set(new Uint8Array(data));
1179
+ }
1180
+ size = this.data_.length;
1181
+ }
1182
+ else if (data instanceof Uint8Array) {
1183
+ if (elideCopy) {
1184
+ this.data_ = data;
1185
+ }
1186
+ else {
1187
+ this.data_ = new Uint8Array(data.length);
1188
+ this.data_.set(data);
1189
+ }
1190
+ size = data.length;
1191
+ }
1192
+ this.size_ = size;
1193
+ this.type_ = blobType;
1194
+ }
1195
+ size() {
1196
+ return this.size_;
1197
+ }
1198
+ type() {
1199
+ return this.type_;
1200
+ }
1201
+ slice(startByte, endByte) {
1202
+ if (isNativeBlob(this.data_)) {
1203
+ const realBlob = this.data_;
1204
+ const sliced = sliceBlob(realBlob, startByte, endByte);
1205
+ if (sliced === null) {
1206
+ return null;
1207
+ }
1208
+ return new FbsBlob(sliced);
1209
+ }
1210
+ else {
1211
+ const slice = new Uint8Array(this.data_.buffer, startByte, endByte - startByte);
1212
+ return new FbsBlob(slice, true);
1213
+ }
1214
+ }
1215
+ static getBlob(...args) {
1216
+ if (isNativeBlobDefined()) {
1217
+ const blobby = args.map((val) => {
1218
+ if (val instanceof FbsBlob) {
1219
+ return val.data_;
1220
+ }
1221
+ else {
1222
+ return val;
1223
+ }
1224
+ });
1225
+ return new FbsBlob(getBlob$1.apply(null, blobby));
1226
+ }
1227
+ else {
1228
+ const uint8Arrays = args.map((val) => {
1229
+ if (isString(val)) {
1230
+ return dataFromString(StringFormat.RAW, val).data;
1231
+ }
1232
+ else {
1233
+ // Blobs don't exist, so this has to be a Uint8Array.
1234
+ return val.data_;
1235
+ }
1236
+ });
1237
+ let finalLength = 0;
1238
+ uint8Arrays.forEach((array) => {
1239
+ finalLength += array.byteLength;
1240
+ });
1241
+ const merged = new Uint8Array(finalLength);
1242
+ let index = 0;
1243
+ uint8Arrays.forEach((array) => {
1244
+ for (let i = 0; i < array.length; i++) {
1245
+ merged[index++] = array[i];
1246
+ }
1247
+ });
1248
+ return new FbsBlob(merged, true);
1249
+ }
1250
+ }
1251
+ uploadData() {
1252
+ return this.data_;
1253
+ }
1254
+ }
1255
+
1256
+ /**
1257
+ * @license
1258
+ * Copyright 2017 Google LLC
1259
+ *
1260
+ * Licensed under the Apache License, Version 2.0 (the "License");
1261
+ * you may not use this file except in compliance with the License.
1262
+ * You may obtain a copy of the License at
1263
+ *
1264
+ * http://www.apache.org/licenses/LICENSE-2.0
1265
+ *
1266
+ * Unless required by applicable law or agreed to in writing, software
1267
+ * distributed under the License is distributed on an "AS IS" BASIS,
1268
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1269
+ * See the License for the specific language governing permissions and
1270
+ * limitations under the License.
1271
+ */
1272
+ /**
1273
+ * Returns the Object resulting from parsing the given JSON, or null if the
1274
+ * given string does not represent a JSON object.
1275
+ */
1276
+ function jsonObjectOrNull(s) {
1277
+ let obj;
1278
+ try {
1279
+ obj = JSON.parse(s);
1280
+ }
1281
+ catch (e) {
1282
+ return null;
1283
+ }
1284
+ if (isNonArrayObject(obj)) {
1285
+ return obj;
1286
+ }
1287
+ else {
1288
+ return null;
1289
+ }
1290
+ }
1291
+
1292
+ /**
1293
+ * @license
1294
+ * Copyright 2017 Google LLC
1295
+ *
1296
+ * Licensed under the Apache License, Version 2.0 (the "License");
1297
+ * you may not use this file except in compliance with the License.
1298
+ * You may obtain a copy of the License at
1299
+ *
1300
+ * http://www.apache.org/licenses/LICENSE-2.0
1301
+ *
1302
+ * Unless required by applicable law or agreed to in writing, software
1303
+ * distributed under the License is distributed on an "AS IS" BASIS,
1304
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1305
+ * See the License for the specific language governing permissions and
1306
+ * limitations under the License.
1307
+ */
1308
+ /**
1309
+ * @fileoverview Contains helper methods for manipulating paths.
1310
+ */
1311
+ /**
1312
+ * @return Null if the path is already at the root.
1313
+ */
1314
+ function parent(path) {
1315
+ if (path.length === 0) {
1316
+ return null;
1317
+ }
1318
+ const index = path.lastIndexOf('/');
1319
+ if (index === -1) {
1320
+ return '';
1321
+ }
1322
+ const newPath = path.slice(0, index);
1323
+ return newPath;
1324
+ }
1325
+ function child(path, childPath) {
1326
+ const canonicalChildPath = childPath
1327
+ .split('/')
1328
+ .filter(component => component.length > 0)
1329
+ .join('/');
1330
+ if (path.length === 0) {
1331
+ return canonicalChildPath;
1332
+ }
1333
+ else {
1334
+ return path + '/' + canonicalChildPath;
1335
+ }
1336
+ }
1337
+ /**
1338
+ * Returns the last component of a path.
1339
+ * '/foo/bar' -> 'bar'
1340
+ * '/foo/bar/baz/' -> 'baz/'
1341
+ * '/a' -> 'a'
1342
+ */
1343
+ function lastComponent(path) {
1344
+ const index = path.lastIndexOf('/', path.length - 2);
1345
+ if (index === -1) {
1346
+ return path;
1347
+ }
1348
+ else {
1349
+ return path.slice(index + 1);
1350
+ }
1351
+ }
1352
+
1353
+ /**
1354
+ * @license
1355
+ * Copyright 2017 Google LLC
1356
+ *
1357
+ * Licensed under the Apache License, Version 2.0 (the "License");
1358
+ * you may not use this file except in compliance with the License.
1359
+ * You may obtain a copy of the License at
1360
+ *
1361
+ * http://www.apache.org/licenses/LICENSE-2.0
1362
+ *
1363
+ * Unless required by applicable law or agreed to in writing, software
1364
+ * distributed under the License is distributed on an "AS IS" BASIS,
1365
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1366
+ * See the License for the specific language governing permissions and
1367
+ * limitations under the License.
1368
+ */
1369
+ function noXform_(metadata, value) {
1370
+ return value;
1371
+ }
1372
+ class Mapping {
1373
+ constructor(server, local, writable, xform) {
1374
+ this.server = server;
1375
+ this.local = local || server;
1376
+ this.writable = !!writable;
1377
+ this.xform = xform || noXform_;
1378
+ }
1379
+ }
1380
+ let mappings_ = null;
1381
+ function xformPath(fullPath) {
1382
+ if (!isString(fullPath) || fullPath.length < 2) {
1383
+ return fullPath;
1384
+ }
1385
+ else {
1386
+ return lastComponent(fullPath);
1387
+ }
1388
+ }
1389
+ function getMappings() {
1390
+ if (mappings_) {
1391
+ return mappings_;
1392
+ }
1393
+ const mappings = [];
1394
+ mappings.push(new Mapping('bucket'));
1395
+ mappings.push(new Mapping('generation'));
1396
+ mappings.push(new Mapping('metageneration'));
1397
+ mappings.push(new Mapping('name', 'fullPath', true));
1398
+ function mappingsXformPath(_metadata, fullPath) {
1399
+ return xformPath(fullPath);
1400
+ }
1401
+ const nameMapping = new Mapping('name');
1402
+ nameMapping.xform = mappingsXformPath;
1403
+ mappings.push(nameMapping);
1404
+ /**
1405
+ * Coerces the second param to a number, if it is defined.
1406
+ */
1407
+ function xformSize(_metadata, size) {
1408
+ if (size !== undefined) {
1409
+ return Number(size);
1410
+ }
1411
+ else {
1412
+ return size;
1413
+ }
1414
+ }
1415
+ const sizeMapping = new Mapping('size');
1416
+ sizeMapping.xform = xformSize;
1417
+ mappings.push(sizeMapping);
1418
+ mappings.push(new Mapping('timeCreated'));
1419
+ mappings.push(new Mapping('updated'));
1420
+ mappings.push(new Mapping('md5Hash', null, true));
1421
+ mappings.push(new Mapping('cacheControl', null, true));
1422
+ mappings.push(new Mapping('contentDisposition', null, true));
1423
+ mappings.push(new Mapping('contentEncoding', null, true));
1424
+ mappings.push(new Mapping('contentLanguage', null, true));
1425
+ mappings.push(new Mapping('contentType', null, true));
1426
+ mappings.push(new Mapping('metadata', 'customMetadata', true));
1427
+ mappings_ = mappings;
1428
+ return mappings_;
1429
+ }
1430
+ function addRef(metadata, service) {
1431
+ function generateRef() {
1432
+ const bucket = metadata['bucket'];
1433
+ const path = metadata['fullPath'];
1434
+ const loc = new Location(bucket, path);
1435
+ return service._makeStorageReference(loc);
1436
+ }
1437
+ Object.defineProperty(metadata, 'ref', { get: generateRef });
1438
+ }
1439
+ function fromResource(service, resource, mappings) {
1440
+ const metadata = {};
1441
+ metadata['type'] = 'file';
1442
+ const len = mappings.length;
1443
+ for (let i = 0; i < len; i++) {
1444
+ const mapping = mappings[i];
1445
+ metadata[mapping.local] = mapping.xform(metadata, resource[mapping.server]);
1446
+ }
1447
+ addRef(metadata, service);
1448
+ return metadata;
1449
+ }
1450
+ function fromResourceString(service, resourceString, mappings) {
1451
+ const obj = jsonObjectOrNull(resourceString);
1452
+ if (obj === null) {
1453
+ return null;
1454
+ }
1455
+ const resource = obj;
1456
+ return fromResource(service, resource, mappings);
1457
+ }
1458
+ function downloadUrlFromResourceString(metadata, resourceString, host, protocol) {
1459
+ const obj = jsonObjectOrNull(resourceString);
1460
+ if (obj === null) {
1461
+ return null;
1462
+ }
1463
+ if (!isString(obj['downloadTokens'])) {
1464
+ // This can happen if objects are uploaded through GCS and retrieved
1465
+ // through list, so we don't want to throw an Error.
1466
+ return null;
1467
+ }
1468
+ const tokens = obj['downloadTokens'];
1469
+ if (tokens.length === 0) {
1470
+ return null;
1471
+ }
1472
+ const encode = encodeURIComponent;
1473
+ const tokensList = tokens.split(',');
1474
+ const urls = tokensList.map((token) => {
1475
+ const bucket = metadata['bucket'];
1476
+ const path = metadata['fullPath'];
1477
+ const urlPart = '/b/' + encode(bucket) + '/o/' + encode(path);
1478
+ const base = makeUrl(urlPart, host, protocol);
1479
+ const queryString = makeQueryString({
1480
+ alt: 'media',
1481
+ token
1482
+ });
1483
+ return base + queryString;
1484
+ });
1485
+ return urls[0];
1486
+ }
1487
+ function toResourceString(metadata, mappings) {
1488
+ const resource = {};
1489
+ const len = mappings.length;
1490
+ for (let i = 0; i < len; i++) {
1491
+ const mapping = mappings[i];
1492
+ if (mapping.writable) {
1493
+ resource[mapping.server] = metadata[mapping.local];
1494
+ }
1495
+ }
1496
+ return JSON.stringify(resource);
1497
+ }
1498
+
1499
+ /**
1500
+ * @license
1501
+ * Copyright 2019 Google LLC
1502
+ *
1503
+ * Licensed under the Apache License, Version 2.0 (the "License");
1504
+ * you may not use this file except in compliance with the License.
1505
+ * You may obtain a copy of the License at
1506
+ *
1507
+ * http://www.apache.org/licenses/LICENSE-2.0
1508
+ *
1509
+ * Unless required by applicable law or agreed to in writing, software
1510
+ * distributed under the License is distributed on an "AS IS" BASIS,
1511
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1512
+ * See the License for the specific language governing permissions and
1513
+ * limitations under the License.
1514
+ */
1515
+ const PREFIXES_KEY = 'prefixes';
1516
+ const ITEMS_KEY = 'items';
1517
+ function fromBackendResponse(service, bucket, resource) {
1518
+ const listResult = {
1519
+ prefixes: [],
1520
+ items: [],
1521
+ nextPageToken: resource['nextPageToken']
1522
+ };
1523
+ if (resource[PREFIXES_KEY]) {
1524
+ for (const path of resource[PREFIXES_KEY]) {
1525
+ const pathWithoutTrailingSlash = path.replace(/\/$/, '');
1526
+ const reference = service._makeStorageReference(new Location(bucket, pathWithoutTrailingSlash));
1527
+ listResult.prefixes.push(reference);
1528
+ }
1529
+ }
1530
+ if (resource[ITEMS_KEY]) {
1531
+ for (const item of resource[ITEMS_KEY]) {
1532
+ const reference = service._makeStorageReference(new Location(bucket, item['name']));
1533
+ listResult.items.push(reference);
1534
+ }
1535
+ }
1536
+ return listResult;
1537
+ }
1538
+ function fromResponseString(service, bucket, resourceString) {
1539
+ const obj = jsonObjectOrNull(resourceString);
1540
+ if (obj === null) {
1541
+ return null;
1542
+ }
1543
+ const resource = obj;
1544
+ return fromBackendResponse(service, bucket, resource);
1545
+ }
1546
+
1547
+ /**
1548
+ * Contains a fully specified request.
1549
+ *
1550
+ * @param I - the type of the backend's network response.
1551
+ * @param O - the output response type used by the rest of the SDK.
1552
+ */
1553
+ class RequestInfo {
1554
+ constructor(url, method,
1555
+ /**
1556
+ * Returns the value with which to resolve the request's promise. Only called
1557
+ * if the request is successful. Throw from this function to reject the
1558
+ * returned Request's promise with the thrown error.
1559
+ * Note: The XhrIo passed to this function may be reused after this callback
1560
+ * returns. Do not keep a reference to it in any way.
1561
+ */
1562
+ handler, timeout) {
1563
+ this.url = url;
1564
+ this.method = method;
1565
+ this.handler = handler;
1566
+ this.timeout = timeout;
1567
+ this.urlParams = {};
1568
+ this.headers = {};
1569
+ this.body = null;
1570
+ this.errorHandler = null;
1571
+ /**
1572
+ * Called with the current number of bytes uploaded and total size (-1 if not
1573
+ * computable) of the request body (i.e. used to report upload progress).
1574
+ */
1575
+ this.progressCallback = null;
1576
+ this.successCodes = [200];
1577
+ this.additionalRetryCodes = [];
1578
+ }
1579
+ }
1580
+
1581
+ /**
1582
+ * @license
1583
+ * Copyright 2017 Google LLC
1584
+ *
1585
+ * Licensed under the Apache License, Version 2.0 (the "License");
1586
+ * you may not use this file except in compliance with the License.
1587
+ * You may obtain a copy of the License at
1588
+ *
1589
+ * http://www.apache.org/licenses/LICENSE-2.0
1590
+ *
1591
+ * Unless required by applicable law or agreed to in writing, software
1592
+ * distributed under the License is distributed on an "AS IS" BASIS,
1593
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1594
+ * See the License for the specific language governing permissions and
1595
+ * limitations under the License.
1596
+ */
1597
+ /**
1598
+ * Throws the UNKNOWN StorageError if cndn is false.
1599
+ */
1600
+ function handlerCheck(cndn) {
1601
+ if (!cndn) {
1602
+ throw unknown();
1603
+ }
1604
+ }
1605
+ function metadataHandler(service, mappings) {
1606
+ function handler(xhr, text) {
1607
+ const metadata = fromResourceString(service, text, mappings);
1608
+ handlerCheck(metadata !== null);
1609
+ return metadata;
1610
+ }
1611
+ return handler;
1612
+ }
1613
+ function listHandler(service, bucket) {
1614
+ function handler(xhr, text) {
1615
+ const listResult = fromResponseString(service, bucket, text);
1616
+ handlerCheck(listResult !== null);
1617
+ return listResult;
1618
+ }
1619
+ return handler;
1620
+ }
1621
+ function downloadUrlHandler(service, mappings) {
1622
+ function handler(xhr, text) {
1623
+ const metadata = fromResourceString(service, text, mappings);
1624
+ handlerCheck(metadata !== null);
1625
+ return downloadUrlFromResourceString(metadata, text, service.host, service._protocol);
1626
+ }
1627
+ return handler;
1628
+ }
1629
+ function sharedErrorHandler(location) {
1630
+ function errorHandler(xhr, err) {
1631
+ let newErr;
1632
+ if (xhr.getStatus() === 401) {
1633
+ if (
1634
+ // This exact message string is the only consistent part of the
1635
+ // server's error response that identifies it as an App Check error.
1636
+ xhr.getErrorText().includes('Firebase App Check token is invalid')) {
1637
+ newErr = unauthorizedApp();
1638
+ }
1639
+ else {
1640
+ newErr = unauthenticated();
1641
+ }
1642
+ }
1643
+ else {
1644
+ if (xhr.getStatus() === 402) {
1645
+ newErr = quotaExceeded(location.bucket);
1646
+ }
1647
+ else {
1648
+ if (xhr.getStatus() === 403) {
1649
+ newErr = unauthorized(location.path);
1650
+ }
1651
+ else {
1652
+ newErr = err;
1653
+ }
1654
+ }
1655
+ }
1656
+ newErr.status = xhr.getStatus();
1657
+ newErr.serverResponse = err.serverResponse;
1658
+ return newErr;
1659
+ }
1660
+ return errorHandler;
1661
+ }
1662
+ function objectErrorHandler(location) {
1663
+ const shared = sharedErrorHandler(location);
1664
+ function errorHandler(xhr, err) {
1665
+ let newErr = shared(xhr, err);
1666
+ if (xhr.getStatus() === 404) {
1667
+ newErr = objectNotFound(location.path);
1668
+ }
1669
+ newErr.serverResponse = err.serverResponse;
1670
+ return newErr;
1671
+ }
1672
+ return errorHandler;
1673
+ }
1674
+ function getMetadata$2(service, location, mappings) {
1675
+ const urlPart = location.fullServerUrl();
1676
+ const url = makeUrl(urlPart, service.host, service._protocol);
1677
+ const method = 'GET';
1678
+ const timeout = service.maxOperationRetryTime;
1679
+ const requestInfo = new RequestInfo(url, method, metadataHandler(service, mappings), timeout);
1680
+ requestInfo.errorHandler = objectErrorHandler(location);
1681
+ return requestInfo;
1682
+ }
1683
+ function list$2(service, location, delimiter, pageToken, maxResults) {
1684
+ const urlParams = {};
1685
+ if (location.isRoot) {
1686
+ urlParams['prefix'] = '';
1687
+ }
1688
+ else {
1689
+ urlParams['prefix'] = location.path + '/';
1690
+ }
1691
+ if (delimiter && delimiter.length > 0) {
1692
+ urlParams['delimiter'] = delimiter;
1693
+ }
1694
+ if (pageToken) {
1695
+ urlParams['pageToken'] = pageToken;
1696
+ }
1697
+ if (maxResults) {
1698
+ urlParams['maxResults'] = maxResults;
1699
+ }
1700
+ const urlPart = location.bucketOnlyServerUrl();
1701
+ const url = makeUrl(urlPart, service.host, service._protocol);
1702
+ const method = 'GET';
1703
+ const timeout = service.maxOperationRetryTime;
1704
+ const requestInfo = new RequestInfo(url, method, listHandler(service, location.bucket), timeout);
1705
+ requestInfo.urlParams = urlParams;
1706
+ requestInfo.errorHandler = sharedErrorHandler(location);
1707
+ return requestInfo;
1708
+ }
1709
+ function getBytes$1(service, location, maxDownloadSizeBytes) {
1710
+ const urlPart = location.fullServerUrl();
1711
+ const url = makeUrl(urlPart, service.host, service._protocol) + '?alt=media';
1712
+ const method = 'GET';
1713
+ const timeout = service.maxOperationRetryTime;
1714
+ const requestInfo = new RequestInfo(url, method, (_, data) => data, timeout);
1715
+ requestInfo.errorHandler = objectErrorHandler(location);
1716
+ if (maxDownloadSizeBytes !== undefined) {
1717
+ requestInfo.headers['Range'] = `bytes=0-${maxDownloadSizeBytes}`;
1718
+ requestInfo.successCodes = [200 /* OK */, 206 /* Partial Content */];
1719
+ }
1720
+ return requestInfo;
1721
+ }
1722
+ function getDownloadUrl(service, location, mappings) {
1723
+ const urlPart = location.fullServerUrl();
1724
+ const url = makeUrl(urlPart, service.host, service._protocol);
1725
+ const method = 'GET';
1726
+ const timeout = service.maxOperationRetryTime;
1727
+ const requestInfo = new RequestInfo(url, method, downloadUrlHandler(service, mappings), timeout);
1728
+ requestInfo.errorHandler = objectErrorHandler(location);
1729
+ return requestInfo;
1730
+ }
1731
+ function updateMetadata$2(service, location, metadata, mappings) {
1732
+ const urlPart = location.fullServerUrl();
1733
+ const url = makeUrl(urlPart, service.host, service._protocol);
1734
+ const method = 'PATCH';
1735
+ const body = toResourceString(metadata, mappings);
1736
+ const headers = { 'Content-Type': 'application/json; charset=utf-8' };
1737
+ const timeout = service.maxOperationRetryTime;
1738
+ const requestInfo = new RequestInfo(url, method, metadataHandler(service, mappings), timeout);
1739
+ requestInfo.headers = headers;
1740
+ requestInfo.body = body;
1741
+ requestInfo.errorHandler = objectErrorHandler(location);
1742
+ return requestInfo;
1743
+ }
1744
+ function deleteObject$2(service, location) {
1745
+ const urlPart = location.fullServerUrl();
1746
+ const url = makeUrl(urlPart, service.host, service._protocol);
1747
+ const method = 'DELETE';
1748
+ const timeout = service.maxOperationRetryTime;
1749
+ function handler(_xhr, _text) { }
1750
+ const requestInfo = new RequestInfo(url, method, handler, timeout);
1751
+ requestInfo.successCodes = [200, 204];
1752
+ requestInfo.errorHandler = objectErrorHandler(location);
1753
+ return requestInfo;
1754
+ }
1755
+ function determineContentType_(metadata, blob) {
1756
+ return ((metadata && metadata['contentType']) ||
1757
+ (blob && blob.type()) ||
1758
+ 'application/octet-stream');
1759
+ }
1760
+ function metadataForUpload_(location, blob, metadata) {
1761
+ const metadataClone = Object.assign({}, metadata);
1762
+ metadataClone['fullPath'] = location.path;
1763
+ metadataClone['size'] = blob.size();
1764
+ if (!metadataClone['contentType']) {
1765
+ metadataClone['contentType'] = determineContentType_(null, blob);
1766
+ }
1767
+ return metadataClone;
1768
+ }
1769
+ /**
1770
+ * Prepare RequestInfo for uploads as Content-Type: multipart.
1771
+ */
1772
+ function multipartUpload(service, location, mappings, blob, metadata) {
1773
+ const urlPart = location.bucketOnlyServerUrl();
1774
+ const headers = {
1775
+ 'X-Goog-Upload-Protocol': 'multipart'
1776
+ };
1777
+ function genBoundary() {
1778
+ let str = '';
1779
+ for (let i = 0; i < 2; i++) {
1780
+ str = str + Math.random().toString().slice(2);
1781
+ }
1782
+ return str;
1783
+ }
1784
+ const boundary = genBoundary();
1785
+ headers['Content-Type'] = 'multipart/related; boundary=' + boundary;
1786
+ const metadata_ = metadataForUpload_(location, blob, metadata);
1787
+ const metadataString = toResourceString(metadata_, mappings);
1788
+ const preBlobPart = '--' +
1789
+ boundary +
1790
+ '\r\n' +
1791
+ 'Content-Type: application/json; charset=utf-8\r\n\r\n' +
1792
+ metadataString +
1793
+ '\r\n--' +
1794
+ boundary +
1795
+ '\r\n' +
1796
+ 'Content-Type: ' +
1797
+ metadata_['contentType'] +
1798
+ '\r\n\r\n';
1799
+ const postBlobPart = '\r\n--' + boundary + '--';
1800
+ const body = FbsBlob.getBlob(preBlobPart, blob, postBlobPart);
1801
+ if (body === null) {
1802
+ throw cannotSliceBlob();
1803
+ }
1804
+ const urlParams = { name: metadata_['fullPath'] };
1805
+ const url = makeUrl(urlPart, service.host, service._protocol);
1806
+ const method = 'POST';
1807
+ const timeout = service.maxUploadRetryTime;
1808
+ const requestInfo = new RequestInfo(url, method, metadataHandler(service, mappings), timeout);
1809
+ requestInfo.urlParams = urlParams;
1810
+ requestInfo.headers = headers;
1811
+ requestInfo.body = body.uploadData();
1812
+ requestInfo.errorHandler = sharedErrorHandler(location);
1813
+ return requestInfo;
1814
+ }
1815
+ /**
1816
+ * @param current The number of bytes that have been uploaded so far.
1817
+ * @param total The total number of bytes in the upload.
1818
+ * @param opt_finalized True if the server has finished the upload.
1819
+ * @param opt_metadata The upload metadata, should
1820
+ * only be passed if opt_finalized is true.
1821
+ */
1822
+ class ResumableUploadStatus {
1823
+ constructor(current, total, finalized, metadata) {
1824
+ this.current = current;
1825
+ this.total = total;
1826
+ this.finalized = !!finalized;
1827
+ this.metadata = metadata || null;
1828
+ }
1829
+ }
1830
+ function checkResumeHeader_(xhr, allowed) {
1831
+ let status = null;
1832
+ try {
1833
+ status = xhr.getResponseHeader('X-Goog-Upload-Status');
1834
+ }
1835
+ catch (e) {
1836
+ handlerCheck(false);
1837
+ }
1838
+ const allowedStatus = allowed || ['active'];
1839
+ handlerCheck(!!status && allowedStatus.indexOf(status) !== -1);
1840
+ return status;
1841
+ }
1842
+ function createResumableUpload(service, location, mappings, blob, metadata) {
1843
+ const urlPart = location.bucketOnlyServerUrl();
1844
+ const metadataForUpload = metadataForUpload_(location, blob, metadata);
1845
+ const urlParams = { name: metadataForUpload['fullPath'] };
1846
+ const url = makeUrl(urlPart, service.host, service._protocol);
1847
+ const method = 'POST';
1848
+ const headers = {
1849
+ 'X-Goog-Upload-Protocol': 'resumable',
1850
+ 'X-Goog-Upload-Command': 'start',
1851
+ 'X-Goog-Upload-Header-Content-Length': `${blob.size()}`,
1852
+ 'X-Goog-Upload-Header-Content-Type': metadataForUpload['contentType'],
1853
+ 'Content-Type': 'application/json; charset=utf-8'
1854
+ };
1855
+ const body = toResourceString(metadataForUpload, mappings);
1856
+ const timeout = service.maxUploadRetryTime;
1857
+ function handler(xhr) {
1858
+ checkResumeHeader_(xhr);
1859
+ let url;
1860
+ try {
1861
+ url = xhr.getResponseHeader('X-Goog-Upload-URL');
1862
+ }
1863
+ catch (e) {
1864
+ handlerCheck(false);
1865
+ }
1866
+ handlerCheck(isString(url));
1867
+ return url;
1868
+ }
1869
+ const requestInfo = new RequestInfo(url, method, handler, timeout);
1870
+ requestInfo.urlParams = urlParams;
1871
+ requestInfo.headers = headers;
1872
+ requestInfo.body = body;
1873
+ requestInfo.errorHandler = sharedErrorHandler(location);
1874
+ return requestInfo;
1875
+ }
1876
+ /**
1877
+ * @param url From a call to fbs.requests.createResumableUpload.
1878
+ */
1879
+ function getResumableUploadStatus(service, location, url, blob) {
1880
+ const headers = { 'X-Goog-Upload-Command': 'query' };
1881
+ function handler(xhr) {
1882
+ const status = checkResumeHeader_(xhr, ['active', 'final']);
1883
+ let sizeString = null;
1884
+ try {
1885
+ sizeString = xhr.getResponseHeader('X-Goog-Upload-Size-Received');
1886
+ }
1887
+ catch (e) {
1888
+ handlerCheck(false);
1889
+ }
1890
+ if (!sizeString) {
1891
+ // null or empty string
1892
+ handlerCheck(false);
1893
+ }
1894
+ const size = Number(sizeString);
1895
+ handlerCheck(!isNaN(size));
1896
+ return new ResumableUploadStatus(size, blob.size(), status === 'final');
1897
+ }
1898
+ const method = 'POST';
1899
+ const timeout = service.maxUploadRetryTime;
1900
+ const requestInfo = new RequestInfo(url, method, handler, timeout);
1901
+ requestInfo.headers = headers;
1902
+ requestInfo.errorHandler = sharedErrorHandler(location);
1903
+ return requestInfo;
1904
+ }
1905
+ /**
1906
+ * Any uploads via the resumable upload API must transfer a number of bytes
1907
+ * that is a multiple of this number.
1908
+ */
1909
+ const RESUMABLE_UPLOAD_CHUNK_SIZE = 256 * 1024;
1910
+ /**
1911
+ * @param url From a call to fbs.requests.createResumableUpload.
1912
+ * @param chunkSize Number of bytes to upload.
1913
+ * @param status The previous status.
1914
+ * If not passed or null, we start from the beginning.
1915
+ * @throws fbs.Error If the upload is already complete, the passed in status
1916
+ * has a final size inconsistent with the blob, or the blob cannot be sliced
1917
+ * for upload.
1918
+ */
1919
+ function continueResumableUpload(location, service, url, blob, chunkSize, mappings, status, progressCallback) {
1920
+ // TODO(andysoto): standardize on internal asserts
1921
+ // assert(!(opt_status && opt_status.finalized));
1922
+ const status_ = new ResumableUploadStatus(0, 0);
1923
+ if (status) {
1924
+ status_.current = status.current;
1925
+ status_.total = status.total;
1926
+ }
1927
+ else {
1928
+ status_.current = 0;
1929
+ status_.total = blob.size();
1930
+ }
1931
+ if (blob.size() !== status_.total) {
1932
+ throw serverFileWrongSize();
1933
+ }
1934
+ const bytesLeft = status_.total - status_.current;
1935
+ let bytesToUpload = bytesLeft;
1936
+ if (chunkSize > 0) {
1937
+ bytesToUpload = Math.min(bytesToUpload, chunkSize);
1938
+ }
1939
+ const startByte = status_.current;
1940
+ const endByte = startByte + bytesToUpload;
1941
+ let uploadCommand = '';
1942
+ if (bytesToUpload === 0) {
1943
+ uploadCommand = 'finalize';
1944
+ }
1945
+ else if (bytesLeft === bytesToUpload) {
1946
+ uploadCommand = 'upload, finalize';
1947
+ }
1948
+ else {
1949
+ uploadCommand = 'upload';
1950
+ }
1951
+ const headers = {
1952
+ 'X-Goog-Upload-Command': uploadCommand,
1953
+ 'X-Goog-Upload-Offset': `${status_.current}`
1954
+ };
1955
+ const body = blob.slice(startByte, endByte);
1956
+ if (body === null) {
1957
+ throw cannotSliceBlob();
1958
+ }
1959
+ function handler(xhr, text) {
1960
+ // TODO(andysoto): Verify the MD5 of each uploaded range:
1961
+ // the 'x-range-md5' header comes back with status code 308 responses.
1962
+ // We'll only be able to bail out though, because you can't re-upload a
1963
+ // range that you previously uploaded.
1964
+ const uploadStatus = checkResumeHeader_(xhr, ['active', 'final']);
1965
+ const newCurrent = status_.current + bytesToUpload;
1966
+ const size = blob.size();
1967
+ let metadata;
1968
+ if (uploadStatus === 'final') {
1969
+ metadata = metadataHandler(service, mappings)(xhr, text);
1970
+ }
1971
+ else {
1972
+ metadata = null;
1973
+ }
1974
+ return new ResumableUploadStatus(newCurrent, size, uploadStatus === 'final', metadata);
1975
+ }
1976
+ const method = 'POST';
1977
+ const timeout = service.maxUploadRetryTime;
1978
+ const requestInfo = new RequestInfo(url, method, handler, timeout);
1979
+ requestInfo.headers = headers;
1980
+ requestInfo.body = body.uploadData();
1981
+ requestInfo.progressCallback = progressCallback || null;
1982
+ requestInfo.errorHandler = sharedErrorHandler(location);
1983
+ return requestInfo;
1984
+ }
1985
+
1986
+ /**
1987
+ * @license
1988
+ * Copyright 2017 Google LLC
1989
+ *
1990
+ * Licensed under the Apache License, Version 2.0 (the "License");
1991
+ * you may not use this file except in compliance with the License.
1992
+ * You may obtain a copy of the License at
1993
+ *
1994
+ * http://www.apache.org/licenses/LICENSE-2.0
1995
+ *
1996
+ * Unless required by applicable law or agreed to in writing, software
1997
+ * distributed under the License is distributed on an "AS IS" BASIS,
1998
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1999
+ * See the License for the specific language governing permissions and
2000
+ * limitations under the License.
2001
+ */
2002
+ /**
2003
+ * An event that is triggered on a task.
2004
+ * @internal
2005
+ */
2006
+ const TaskEvent = {
2007
+ /**
2008
+ * For this event,
2009
+ * <ul>
2010
+ * <li>The `next` function is triggered on progress updates and when the
2011
+ * task is paused/resumed with an `UploadTaskSnapshot` as the first
2012
+ * argument.</li>
2013
+ * <li>The `error` function is triggered if the upload is canceled or fails
2014
+ * for another reason.</li>
2015
+ * <li>The `complete` function is triggered if the upload completes
2016
+ * successfully.</li>
2017
+ * </ul>
2018
+ */
2019
+ STATE_CHANGED: 'state_changed'
2020
+ };
2021
+ // type keys = keyof TaskState
2022
+ /**
2023
+ * Represents the current state of a running upload.
2024
+ * @internal
2025
+ */
2026
+ const TaskState = {
2027
+ /** The task is currently transferring data. */
2028
+ RUNNING: 'running',
2029
+ /** The task was paused by the user. */
2030
+ PAUSED: 'paused',
2031
+ /** The task completed successfully. */
2032
+ SUCCESS: 'success',
2033
+ /** The task was canceled. */
2034
+ CANCELED: 'canceled',
2035
+ /** The task failed with an error. */
2036
+ ERROR: 'error'
2037
+ };
2038
+ function taskStateFromInternalTaskState(state) {
2039
+ switch (state) {
2040
+ case "running" /* InternalTaskState.RUNNING */:
2041
+ case "pausing" /* InternalTaskState.PAUSING */:
2042
+ case "canceling" /* InternalTaskState.CANCELING */:
2043
+ return TaskState.RUNNING;
2044
+ case "paused" /* InternalTaskState.PAUSED */:
2045
+ return TaskState.PAUSED;
2046
+ case "success" /* InternalTaskState.SUCCESS */:
2047
+ return TaskState.SUCCESS;
2048
+ case "canceled" /* InternalTaskState.CANCELED */:
2049
+ return TaskState.CANCELED;
2050
+ case "error" /* InternalTaskState.ERROR */:
2051
+ return TaskState.ERROR;
2052
+ default:
2053
+ // TODO(andysoto): assert(false);
2054
+ return TaskState.ERROR;
2055
+ }
2056
+ }
2057
+
2058
+ /**
2059
+ * @license
2060
+ * Copyright 2017 Google LLC
2061
+ *
2062
+ * Licensed under the Apache License, Version 2.0 (the "License");
2063
+ * you may not use this file except in compliance with the License.
2064
+ * You may obtain a copy of the License at
2065
+ *
2066
+ * http://www.apache.org/licenses/LICENSE-2.0
2067
+ *
2068
+ * Unless required by applicable law or agreed to in writing, software
2069
+ * distributed under the License is distributed on an "AS IS" BASIS,
2070
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2071
+ * See the License for the specific language governing permissions and
2072
+ * limitations under the License.
2073
+ */
2074
+ class Observer {
2075
+ constructor(nextOrObserver, error, complete) {
2076
+ const asFunctions = isFunction(nextOrObserver) || error != null || complete != null;
2077
+ if (asFunctions) {
2078
+ this.next = nextOrObserver;
2079
+ this.error = error ?? undefined;
2080
+ this.complete = complete ?? undefined;
2081
+ }
2082
+ else {
2083
+ const observer = nextOrObserver;
2084
+ this.next = observer.next;
2085
+ this.error = observer.error;
2086
+ this.complete = observer.complete;
2087
+ }
2088
+ }
2089
+ }
2090
+
2091
+ /**
2092
+ * @license
2093
+ * Copyright 2017 Google LLC
2094
+ *
2095
+ * Licensed under the Apache License, Version 2.0 (the "License");
2096
+ * you may not use this file except in compliance with the License.
2097
+ * You may obtain a copy of the License at
2098
+ *
2099
+ * http://www.apache.org/licenses/LICENSE-2.0
2100
+ *
2101
+ * Unless required by applicable law or agreed to in writing, software
2102
+ * distributed under the License is distributed on an "AS IS" BASIS,
2103
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2104
+ * See the License for the specific language governing permissions and
2105
+ * limitations under the License.
2106
+ */
2107
+ /**
2108
+ * Returns a function that invokes f with its arguments asynchronously as a
2109
+ * microtask, i.e. as soon as possible after the current script returns back
2110
+ * into browser code.
2111
+ */
2112
+ // eslint-disable-next-line @typescript-eslint/ban-types
2113
+ function async(f) {
2114
+ return (...argsToForward) => {
2115
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
2116
+ Promise.resolve().then(() => f(...argsToForward));
2117
+ };
2118
+ }
2119
+
2120
+ /**
2121
+ * @license
2122
+ * Copyright 2017 Google LLC
2123
+ *
2124
+ * Licensed under the Apache License, Version 2.0 (the "License");
2125
+ * you may not use this file except in compliance with the License.
2126
+ * You may obtain a copy of the License at
2127
+ *
2128
+ * http://www.apache.org/licenses/LICENSE-2.0
2129
+ *
2130
+ * Unless required by applicable law or agreed to in writing, software
2131
+ * distributed under the License is distributed on an "AS IS" BASIS,
2132
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2133
+ * See the License for the specific language governing permissions and
2134
+ * limitations under the License.
2135
+ */
2136
+ /** An override for the text-based Connection. Used in tests. */
2137
+ let textFactoryOverride = null;
2138
+ /**
2139
+ * Network layer for browsers. We use this instead of goog.net.XhrIo because
2140
+ * goog.net.XhrIo is hyuuuuge and doesn't work in React Native on Android.
2141
+ */
2142
+ class XhrConnection {
2143
+ constructor() {
2144
+ this.sent_ = false;
2145
+ this.xhr_ = new XMLHttpRequest();
2146
+ this.initXhr();
2147
+ this.errorCode_ = ErrorCode.NO_ERROR;
2148
+ this.sendPromise_ = new Promise(resolve => {
2149
+ this.xhr_.addEventListener('abort', () => {
2150
+ this.errorCode_ = ErrorCode.ABORT;
2151
+ resolve();
2152
+ });
2153
+ this.xhr_.addEventListener('error', () => {
2154
+ this.errorCode_ = ErrorCode.NETWORK_ERROR;
2155
+ resolve();
2156
+ });
2157
+ this.xhr_.addEventListener('load', () => {
2158
+ resolve();
2159
+ });
2160
+ });
2161
+ }
2162
+ send(url, method, isUsingEmulator, body, headers) {
2163
+ if (this.sent_) {
2164
+ throw internalError('cannot .send() more than once');
2165
+ }
2166
+ if (isCloudWorkstation(url) && isUsingEmulator) {
2167
+ this.xhr_.withCredentials = true;
2168
+ }
2169
+ this.sent_ = true;
2170
+ this.xhr_.open(method, url, true);
2171
+ if (headers !== undefined) {
2172
+ for (const key in headers) {
2173
+ if (headers.hasOwnProperty(key)) {
2174
+ this.xhr_.setRequestHeader(key, headers[key].toString());
2175
+ }
2176
+ }
2177
+ }
2178
+ if (body !== undefined) {
2179
+ this.xhr_.send(body);
2180
+ }
2181
+ else {
2182
+ this.xhr_.send();
2183
+ }
2184
+ return this.sendPromise_;
2185
+ }
2186
+ getErrorCode() {
2187
+ if (!this.sent_) {
2188
+ throw internalError('cannot .getErrorCode() before sending');
2189
+ }
2190
+ return this.errorCode_;
2191
+ }
2192
+ getStatus() {
2193
+ if (!this.sent_) {
2194
+ throw internalError('cannot .getStatus() before sending');
2195
+ }
2196
+ try {
2197
+ return this.xhr_.status;
2198
+ }
2199
+ catch (e) {
2200
+ return -1;
2201
+ }
2202
+ }
2203
+ getResponse() {
2204
+ if (!this.sent_) {
2205
+ throw internalError('cannot .getResponse() before sending');
2206
+ }
2207
+ return this.xhr_.response;
2208
+ }
2209
+ getErrorText() {
2210
+ if (!this.sent_) {
2211
+ throw internalError('cannot .getErrorText() before sending');
2212
+ }
2213
+ return this.xhr_.statusText;
2214
+ }
2215
+ /** Aborts the request. */
2216
+ abort() {
2217
+ this.xhr_.abort();
2218
+ }
2219
+ getResponseHeader(header) {
2220
+ return this.xhr_.getResponseHeader(header);
2221
+ }
2222
+ addUploadProgressListener(listener) {
2223
+ if (this.xhr_.upload != null) {
2224
+ this.xhr_.upload.addEventListener('progress', listener);
2225
+ }
2226
+ }
2227
+ removeUploadProgressListener(listener) {
2228
+ if (this.xhr_.upload != null) {
2229
+ this.xhr_.upload.removeEventListener('progress', listener);
2230
+ }
2231
+ }
2232
+ }
2233
+ class XhrTextConnection extends XhrConnection {
2234
+ initXhr() {
2235
+ this.xhr_.responseType = 'text';
2236
+ }
2237
+ }
2238
+ function newTextConnection() {
2239
+ return textFactoryOverride ? textFactoryOverride() : new XhrTextConnection();
2240
+ }
2241
+ class XhrBytesConnection extends XhrConnection {
2242
+ initXhr() {
2243
+ this.xhr_.responseType = 'arraybuffer';
2244
+ }
2245
+ }
2246
+ function newBytesConnection() {
2247
+ return new XhrBytesConnection();
2248
+ }
2249
+ class XhrBlobConnection extends XhrConnection {
2250
+ initXhr() {
2251
+ this.xhr_.responseType = 'blob';
2252
+ }
2253
+ }
2254
+ function newBlobConnection() {
2255
+ return new XhrBlobConnection();
2256
+ }
2257
+
2258
+ /**
2259
+ * @license
2260
+ * Copyright 2017 Google LLC
2261
+ *
2262
+ * Licensed under the Apache License, Version 2.0 (the "License");
2263
+ * you may not use this file except in compliance with the License.
2264
+ * You may obtain a copy of the License at
2265
+ *
2266
+ * http://www.apache.org/licenses/LICENSE-2.0
2267
+ *
2268
+ * Unless required by applicable law or agreed to in writing, software
2269
+ * distributed under the License is distributed on an "AS IS" BASIS,
2270
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2271
+ * See the License for the specific language governing permissions and
2272
+ * limitations under the License.
2273
+ */
2274
+ /**
2275
+ * Represents a blob being uploaded. Can be used to pause/resume/cancel the
2276
+ * upload and manage callbacks for various events.
2277
+ * @internal
2278
+ */
2279
+ class UploadTask {
2280
+ isExponentialBackoffExpired() {
2281
+ return this.sleepTime > this.maxSleepTime;
2282
+ }
2283
+ /**
2284
+ * @param ref - The firebaseStorage.Reference object this task came
2285
+ * from, untyped to avoid cyclic dependencies.
2286
+ * @param blob - The blob to upload.
2287
+ */
2288
+ constructor(ref, blob, metadata = null) {
2289
+ /**
2290
+ * Number of bytes transferred so far.
2291
+ */
2292
+ this._transferred = 0;
2293
+ this._needToFetchStatus = false;
2294
+ this._needToFetchMetadata = false;
2295
+ this._observers = [];
2296
+ this._error = undefined;
2297
+ this._uploadUrl = undefined;
2298
+ this._request = undefined;
2299
+ this._chunkMultiplier = 1;
2300
+ this._resolve = undefined;
2301
+ this._reject = undefined;
2302
+ this._ref = ref;
2303
+ this._blob = blob;
2304
+ this._metadata = metadata;
2305
+ this._mappings = getMappings();
2306
+ this._resumable = this._shouldDoResumable(this._blob);
2307
+ this._state = "running" /* InternalTaskState.RUNNING */;
2308
+ this._errorHandler = error => {
2309
+ this._request = undefined;
2310
+ this._chunkMultiplier = 1;
2311
+ if (error._codeEquals(StorageErrorCode.CANCELED)) {
2312
+ this._needToFetchStatus = true;
2313
+ this.completeTransitions_();
2314
+ }
2315
+ else {
2316
+ const backoffExpired = this.isExponentialBackoffExpired();
2317
+ if (isRetryStatusCode(error.status, [])) {
2318
+ if (backoffExpired) {
2319
+ error = retryLimitExceeded();
2320
+ }
2321
+ else {
2322
+ this.sleepTime = Math.max(this.sleepTime * 2, DEFAULT_MIN_SLEEP_TIME_MILLIS);
2323
+ this._needToFetchStatus = true;
2324
+ this.completeTransitions_();
2325
+ return;
2326
+ }
2327
+ }
2328
+ this._error = error;
2329
+ this._transition("error" /* InternalTaskState.ERROR */);
2330
+ }
2331
+ };
2332
+ this._metadataErrorHandler = error => {
2333
+ this._request = undefined;
2334
+ if (error._codeEquals(StorageErrorCode.CANCELED)) {
2335
+ this.completeTransitions_();
2336
+ }
2337
+ else {
2338
+ this._error = error;
2339
+ this._transition("error" /* InternalTaskState.ERROR */);
2340
+ }
2341
+ };
2342
+ this.sleepTime = 0;
2343
+ this.maxSleepTime = this._ref.storage.maxUploadRetryTime;
2344
+ this._promise = new Promise((resolve, reject) => {
2345
+ this._resolve = resolve;
2346
+ this._reject = reject;
2347
+ this._start();
2348
+ });
2349
+ // Prevent uncaught rejections on the internal promise from bubbling out
2350
+ // to the top level with a dummy handler.
2351
+ this._promise.then(null, () => { });
2352
+ }
2353
+ _makeProgressCallback() {
2354
+ const sizeBefore = this._transferred;
2355
+ return loaded => this._updateProgress(sizeBefore + loaded);
2356
+ }
2357
+ _shouldDoResumable(blob) {
2358
+ return blob.size() > 256 * 1024;
2359
+ }
2360
+ _start() {
2361
+ if (this._state !== "running" /* InternalTaskState.RUNNING */) {
2362
+ // This can happen if someone pauses us in a resume callback, for example.
2363
+ return;
2364
+ }
2365
+ if (this._request !== undefined) {
2366
+ return;
2367
+ }
2368
+ if (this._resumable) {
2369
+ if (this._uploadUrl === undefined) {
2370
+ this._createResumable();
2371
+ }
2372
+ else {
2373
+ if (this._needToFetchStatus) {
2374
+ this._fetchStatus();
2375
+ }
2376
+ else {
2377
+ if (this._needToFetchMetadata) {
2378
+ // Happens if we miss the metadata on upload completion.
2379
+ this._fetchMetadata();
2380
+ }
2381
+ else {
2382
+ this.pendingTimeout = setTimeout(() => {
2383
+ this.pendingTimeout = undefined;
2384
+ this._continueUpload();
2385
+ }, this.sleepTime);
2386
+ }
2387
+ }
2388
+ }
2389
+ }
2390
+ else {
2391
+ this._oneShotUpload();
2392
+ }
2393
+ }
2394
+ _resolveToken(callback) {
2395
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
2396
+ Promise.all([
2397
+ this._ref.storage._getAuthToken(),
2398
+ this._ref.storage._getAppCheckToken()
2399
+ ]).then(([authToken, appCheckToken]) => {
2400
+ switch (this._state) {
2401
+ case "running" /* InternalTaskState.RUNNING */:
2402
+ callback(authToken, appCheckToken);
2403
+ break;
2404
+ case "canceling" /* InternalTaskState.CANCELING */:
2405
+ this._transition("canceled" /* InternalTaskState.CANCELED */);
2406
+ break;
2407
+ case "pausing" /* InternalTaskState.PAUSING */:
2408
+ this._transition("paused" /* InternalTaskState.PAUSED */);
2409
+ break;
2410
+ }
2411
+ });
2412
+ }
2413
+ // TODO(andysoto): assert false
2414
+ _createResumable() {
2415
+ this._resolveToken((authToken, appCheckToken) => {
2416
+ const requestInfo = createResumableUpload(this._ref.storage, this._ref._location, this._mappings, this._blob, this._metadata);
2417
+ const createRequest = this._ref.storage._makeRequest(requestInfo, newTextConnection, authToken, appCheckToken);
2418
+ this._request = createRequest;
2419
+ createRequest.getPromise().then((url) => {
2420
+ this._request = undefined;
2421
+ this._uploadUrl = url;
2422
+ this._needToFetchStatus = false;
2423
+ this.completeTransitions_();
2424
+ }, this._errorHandler);
2425
+ });
2426
+ }
2427
+ _fetchStatus() {
2428
+ // TODO(andysoto): assert(this.uploadUrl_ !== null);
2429
+ const url = this._uploadUrl;
2430
+ this._resolveToken((authToken, appCheckToken) => {
2431
+ const requestInfo = getResumableUploadStatus(this._ref.storage, this._ref._location, url, this._blob);
2432
+ const statusRequest = this._ref.storage._makeRequest(requestInfo, newTextConnection, authToken, appCheckToken);
2433
+ this._request = statusRequest;
2434
+ statusRequest.getPromise().then(status => {
2435
+ status = status;
2436
+ this._request = undefined;
2437
+ this._updateProgress(status.current);
2438
+ this._needToFetchStatus = false;
2439
+ if (status.finalized) {
2440
+ this._needToFetchMetadata = true;
2441
+ }
2442
+ this.completeTransitions_();
2443
+ }, this._errorHandler);
2444
+ });
2445
+ }
2446
+ _continueUpload() {
2447
+ const chunkSize = RESUMABLE_UPLOAD_CHUNK_SIZE * this._chunkMultiplier;
2448
+ const status = new ResumableUploadStatus(this._transferred, this._blob.size());
2449
+ // TODO(andysoto): assert(this.uploadUrl_ !== null);
2450
+ const url = this._uploadUrl;
2451
+ this._resolveToken((authToken, appCheckToken) => {
2452
+ let requestInfo;
2453
+ try {
2454
+ requestInfo = continueResumableUpload(this._ref._location, this._ref.storage, url, this._blob, chunkSize, this._mappings, status, this._makeProgressCallback());
2455
+ }
2456
+ catch (e) {
2457
+ this._error = e;
2458
+ this._transition("error" /* InternalTaskState.ERROR */);
2459
+ return;
2460
+ }
2461
+ const uploadRequest = this._ref.storage._makeRequest(requestInfo, newTextConnection, authToken, appCheckToken,
2462
+ /*retry=*/ false // Upload requests should not be retried as each retry should be preceded by another query request. Which is handled in this file.
2463
+ );
2464
+ this._request = uploadRequest;
2465
+ uploadRequest.getPromise().then((newStatus) => {
2466
+ this._increaseMultiplier();
2467
+ this._request = undefined;
2468
+ this._updateProgress(newStatus.current);
2469
+ if (newStatus.finalized) {
2470
+ this._metadata = newStatus.metadata;
2471
+ this._transition("success" /* InternalTaskState.SUCCESS */);
2472
+ }
2473
+ else {
2474
+ this.completeTransitions_();
2475
+ }
2476
+ }, this._errorHandler);
2477
+ });
2478
+ }
2479
+ _increaseMultiplier() {
2480
+ const currentSize = RESUMABLE_UPLOAD_CHUNK_SIZE * this._chunkMultiplier;
2481
+ // Max chunk size is 32M.
2482
+ if (currentSize * 2 < 32 * 1024 * 1024) {
2483
+ this._chunkMultiplier *= 2;
2484
+ }
2485
+ }
2486
+ _fetchMetadata() {
2487
+ this._resolveToken((authToken, appCheckToken) => {
2488
+ const requestInfo = getMetadata$2(this._ref.storage, this._ref._location, this._mappings);
2489
+ const metadataRequest = this._ref.storage._makeRequest(requestInfo, newTextConnection, authToken, appCheckToken);
2490
+ this._request = metadataRequest;
2491
+ metadataRequest.getPromise().then(metadata => {
2492
+ this._request = undefined;
2493
+ this._metadata = metadata;
2494
+ this._transition("success" /* InternalTaskState.SUCCESS */);
2495
+ }, this._metadataErrorHandler);
2496
+ });
2497
+ }
2498
+ _oneShotUpload() {
2499
+ this._resolveToken((authToken, appCheckToken) => {
2500
+ const requestInfo = multipartUpload(this._ref.storage, this._ref._location, this._mappings, this._blob, this._metadata);
2501
+ const multipartRequest = this._ref.storage._makeRequest(requestInfo, newTextConnection, authToken, appCheckToken);
2502
+ this._request = multipartRequest;
2503
+ multipartRequest.getPromise().then(metadata => {
2504
+ this._request = undefined;
2505
+ this._metadata = metadata;
2506
+ this._updateProgress(this._blob.size());
2507
+ this._transition("success" /* InternalTaskState.SUCCESS */);
2508
+ }, this._errorHandler);
2509
+ });
2510
+ }
2511
+ _updateProgress(transferred) {
2512
+ const old = this._transferred;
2513
+ this._transferred = transferred;
2514
+ // A progress update can make the "transferred" value smaller (e.g. a
2515
+ // partial upload not completed by server, after which the "transferred"
2516
+ // value may reset to the value at the beginning of the request).
2517
+ if (this._transferred !== old) {
2518
+ this._notifyObservers();
2519
+ }
2520
+ }
2521
+ _transition(state) {
2522
+ if (this._state === state) {
2523
+ return;
2524
+ }
2525
+ switch (state) {
2526
+ case "canceling" /* InternalTaskState.CANCELING */:
2527
+ case "pausing" /* InternalTaskState.PAUSING */:
2528
+ // TODO(andysoto):
2529
+ // assert(this.state_ === InternalTaskState.RUNNING ||
2530
+ // this.state_ === InternalTaskState.PAUSING);
2531
+ this._state = state;
2532
+ if (this._request !== undefined) {
2533
+ this._request.cancel();
2534
+ }
2535
+ else if (this.pendingTimeout) {
2536
+ clearTimeout(this.pendingTimeout);
2537
+ this.pendingTimeout = undefined;
2538
+ this.completeTransitions_();
2539
+ }
2540
+ break;
2541
+ case "running" /* InternalTaskState.RUNNING */:
2542
+ // TODO(andysoto):
2543
+ // assert(this.state_ === InternalTaskState.PAUSED ||
2544
+ // this.state_ === InternalTaskState.PAUSING);
2545
+ const wasPaused = this._state === "paused" /* InternalTaskState.PAUSED */;
2546
+ this._state = state;
2547
+ if (wasPaused) {
2548
+ this._notifyObservers();
2549
+ this._start();
2550
+ }
2551
+ break;
2552
+ case "paused" /* InternalTaskState.PAUSED */:
2553
+ // TODO(andysoto):
2554
+ // assert(this.state_ === InternalTaskState.PAUSING);
2555
+ this._state = state;
2556
+ this._notifyObservers();
2557
+ break;
2558
+ case "canceled" /* InternalTaskState.CANCELED */:
2559
+ // TODO(andysoto):
2560
+ // assert(this.state_ === InternalTaskState.PAUSED ||
2561
+ // this.state_ === InternalTaskState.CANCELING);
2562
+ this._error = canceled();
2563
+ this._state = state;
2564
+ this._notifyObservers();
2565
+ break;
2566
+ case "error" /* InternalTaskState.ERROR */:
2567
+ // TODO(andysoto):
2568
+ // assert(this.state_ === InternalTaskState.RUNNING ||
2569
+ // this.state_ === InternalTaskState.PAUSING ||
2570
+ // this.state_ === InternalTaskState.CANCELING);
2571
+ this._state = state;
2572
+ this._notifyObservers();
2573
+ break;
2574
+ case "success" /* InternalTaskState.SUCCESS */:
2575
+ // TODO(andysoto):
2576
+ // assert(this.state_ === InternalTaskState.RUNNING ||
2577
+ // this.state_ === InternalTaskState.PAUSING ||
2578
+ // this.state_ === InternalTaskState.CANCELING);
2579
+ this._state = state;
2580
+ this._notifyObservers();
2581
+ break;
2582
+ }
2583
+ }
2584
+ completeTransitions_() {
2585
+ switch (this._state) {
2586
+ case "pausing" /* InternalTaskState.PAUSING */:
2587
+ this._transition("paused" /* InternalTaskState.PAUSED */);
2588
+ break;
2589
+ case "canceling" /* InternalTaskState.CANCELING */:
2590
+ this._transition("canceled" /* InternalTaskState.CANCELED */);
2591
+ break;
2592
+ case "running" /* InternalTaskState.RUNNING */:
2593
+ this._start();
2594
+ break;
2595
+ }
2596
+ }
2597
+ /**
2598
+ * A snapshot of the current task state.
2599
+ */
2600
+ get snapshot() {
2601
+ const externalState = taskStateFromInternalTaskState(this._state);
2602
+ return {
2603
+ bytesTransferred: this._transferred,
2604
+ totalBytes: this._blob.size(),
2605
+ state: externalState,
2606
+ metadata: this._metadata,
2607
+ task: this,
2608
+ ref: this._ref
2609
+ };
2610
+ }
2611
+ /**
2612
+ * Adds a callback for an event.
2613
+ * @param type - The type of event to listen for.
2614
+ * @param nextOrObserver -
2615
+ * The `next` function, which gets called for each item in
2616
+ * the event stream, or an observer object with some or all of these three
2617
+ * properties (`next`, `error`, `complete`).
2618
+ * @param error - A function that gets called with a `StorageError`
2619
+ * if the event stream ends due to an error.
2620
+ * @param completed - A function that gets called if the
2621
+ * event stream ends normally.
2622
+ * @returns
2623
+ * If only the event argument is passed, returns a function you can use to
2624
+ * add callbacks (see the examples above). If more than just the event
2625
+ * argument is passed, returns a function you can call to unregister the
2626
+ * callbacks.
2627
+ */
2628
+ on(type, nextOrObserver, error, completed) {
2629
+ // Note: `type` isn't being used. Its type is also incorrect. TaskEvent should not be a string.
2630
+ const observer = new Observer(nextOrObserver || undefined, error || undefined, completed || undefined);
2631
+ this._addObserver(observer);
2632
+ return () => {
2633
+ this._removeObserver(observer);
2634
+ };
2635
+ }
2636
+ /**
2637
+ * This object behaves like a Promise, and resolves with its snapshot data
2638
+ * when the upload completes.
2639
+ * @param onFulfilled - The fulfillment callback. Promise chaining works as normal.
2640
+ * @param onRejected - The rejection callback.
2641
+ */
2642
+ then(onFulfilled, onRejected) {
2643
+ // These casts are needed so that TypeScript can infer the types of the
2644
+ // resulting Promise.
2645
+ return this._promise.then(onFulfilled, onRejected);
2646
+ }
2647
+ /**
2648
+ * Equivalent to calling `then(null, onRejected)`.
2649
+ */
2650
+ catch(onRejected) {
2651
+ return this.then(null, onRejected);
2652
+ }
2653
+ /**
2654
+ * Adds the given observer.
2655
+ */
2656
+ _addObserver(observer) {
2657
+ this._observers.push(observer);
2658
+ this._notifyObserver(observer);
2659
+ }
2660
+ /**
2661
+ * Removes the given observer.
2662
+ */
2663
+ _removeObserver(observer) {
2664
+ const i = this._observers.indexOf(observer);
2665
+ if (i !== -1) {
2666
+ this._observers.splice(i, 1);
2667
+ }
2668
+ }
2669
+ _notifyObservers() {
2670
+ this._finishPromise();
2671
+ const observers = this._observers.slice();
2672
+ observers.forEach(observer => {
2673
+ this._notifyObserver(observer);
2674
+ });
2675
+ }
2676
+ _finishPromise() {
2677
+ if (this._resolve !== undefined) {
2678
+ let triggered = true;
2679
+ switch (taskStateFromInternalTaskState(this._state)) {
2680
+ case TaskState.SUCCESS:
2681
+ async(this._resolve.bind(null, this.snapshot))();
2682
+ break;
2683
+ case TaskState.CANCELED:
2684
+ case TaskState.ERROR:
2685
+ const toCall = this._reject;
2686
+ async(toCall.bind(null, this._error))();
2687
+ break;
2688
+ default:
2689
+ triggered = false;
2690
+ break;
2691
+ }
2692
+ if (triggered) {
2693
+ this._resolve = undefined;
2694
+ this._reject = undefined;
2695
+ }
2696
+ }
2697
+ }
2698
+ _notifyObserver(observer) {
2699
+ const externalState = taskStateFromInternalTaskState(this._state);
2700
+ switch (externalState) {
2701
+ case TaskState.RUNNING:
2702
+ case TaskState.PAUSED:
2703
+ if (observer.next) {
2704
+ async(observer.next.bind(observer, this.snapshot))();
2705
+ }
2706
+ break;
2707
+ case TaskState.SUCCESS:
2708
+ if (observer.complete) {
2709
+ async(observer.complete.bind(observer))();
2710
+ }
2711
+ break;
2712
+ case TaskState.CANCELED:
2713
+ case TaskState.ERROR:
2714
+ if (observer.error) {
2715
+ async(observer.error.bind(observer, this._error))();
2716
+ }
2717
+ break;
2718
+ default:
2719
+ // TODO(andysoto): assert(false);
2720
+ if (observer.error) {
2721
+ async(observer.error.bind(observer, this._error))();
2722
+ }
2723
+ }
2724
+ }
2725
+ /**
2726
+ * Resumes a paused task. Has no effect on a currently running or failed task.
2727
+ * @returns True if the operation took effect, false if ignored.
2728
+ */
2729
+ resume() {
2730
+ const valid = this._state === "paused" /* InternalTaskState.PAUSED */ ||
2731
+ this._state === "pausing" /* InternalTaskState.PAUSING */;
2732
+ if (valid) {
2733
+ this._transition("running" /* InternalTaskState.RUNNING */);
2734
+ }
2735
+ return valid;
2736
+ }
2737
+ /**
2738
+ * Pauses a currently running task. Has no effect on a paused or failed task.
2739
+ * @returns True if the operation took effect, false if ignored.
2740
+ */
2741
+ pause() {
2742
+ const valid = this._state === "running" /* InternalTaskState.RUNNING */;
2743
+ if (valid) {
2744
+ this._transition("pausing" /* InternalTaskState.PAUSING */);
2745
+ }
2746
+ return valid;
2747
+ }
2748
+ /**
2749
+ * Cancels a currently running or paused task. Has no effect on a complete or
2750
+ * failed task.
2751
+ * @returns True if the operation took effect, false if ignored.
2752
+ */
2753
+ cancel() {
2754
+ const valid = this._state === "running" /* InternalTaskState.RUNNING */ ||
2755
+ this._state === "pausing" /* InternalTaskState.PAUSING */;
2756
+ if (valid) {
2757
+ this._transition("canceling" /* InternalTaskState.CANCELING */);
2758
+ }
2759
+ return valid;
2760
+ }
2761
+ }
2762
+
2763
+ /**
2764
+ * @license
2765
+ * Copyright 2019 Google LLC
2766
+ *
2767
+ * Licensed under the Apache License, Version 2.0 (the "License");
2768
+ * you may not use this file except in compliance with the License.
2769
+ * You may obtain a copy of the License at
2770
+ *
2771
+ * http://www.apache.org/licenses/LICENSE-2.0
2772
+ *
2773
+ * Unless required by applicable law or agreed to in writing, software
2774
+ * distributed under the License is distributed on an "AS IS" BASIS,
2775
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2776
+ * See the License for the specific language governing permissions and
2777
+ * limitations under the License.
2778
+ */
2779
+ /**
2780
+ * Provides methods to interact with a bucket in the Firebase Storage service.
2781
+ * @internal
2782
+ * @param _location - An fbs.location, or the URL at
2783
+ * which to base this object, in one of the following forms:
2784
+ * gs://<bucket>/<object-path>
2785
+ * http[s]://firebasestorage.googleapis.com/
2786
+ * <api-version>/b/<bucket>/o/<object-path>
2787
+ * Any query or fragment strings will be ignored in the http[s]
2788
+ * format. If no value is passed, the storage object will use a URL based on
2789
+ * the project ID of the base firebase.App instance.
2790
+ */
2791
+ class Reference {
2792
+ constructor(_service, location) {
2793
+ this._service = _service;
2794
+ if (location instanceof Location) {
2795
+ this._location = location;
2796
+ }
2797
+ else {
2798
+ this._location = Location.makeFromUrl(location, _service.host);
2799
+ }
2800
+ }
2801
+ /**
2802
+ * Returns the URL for the bucket and path this object references,
2803
+ * in the form gs://<bucket>/<object-path>
2804
+ * @override
2805
+ */
2806
+ toString() {
2807
+ return 'gs://' + this._location.bucket + '/' + this._location.path;
2808
+ }
2809
+ _newRef(service, location) {
2810
+ return new Reference(service, location);
2811
+ }
2812
+ /**
2813
+ * A reference to the root of this object's bucket.
2814
+ */
2815
+ get root() {
2816
+ const location = new Location(this._location.bucket, '');
2817
+ return this._newRef(this._service, location);
2818
+ }
2819
+ /**
2820
+ * The name of the bucket containing this reference's object.
2821
+ */
2822
+ get bucket() {
2823
+ return this._location.bucket;
2824
+ }
2825
+ /**
2826
+ * The full path of this object.
2827
+ */
2828
+ get fullPath() {
2829
+ return this._location.path;
2830
+ }
2831
+ /**
2832
+ * The short name of this object, which is the last component of the full path.
2833
+ * For example, if fullPath is 'full/path/image.png', name is 'image.png'.
2834
+ */
2835
+ get name() {
2836
+ return lastComponent(this._location.path);
2837
+ }
2838
+ /**
2839
+ * The `StorageService` instance this `StorageReference` is associated with.
2840
+ */
2841
+ get storage() {
2842
+ return this._service;
2843
+ }
2844
+ /**
2845
+ * A `StorageReference` pointing to the parent location of this `StorageReference`, or null if
2846
+ * this reference is the root.
2847
+ */
2848
+ get parent() {
2849
+ const newPath = parent(this._location.path);
2850
+ if (newPath === null) {
2851
+ return null;
2852
+ }
2853
+ const location = new Location(this._location.bucket, newPath);
2854
+ return new Reference(this._service, location);
2855
+ }
2856
+ /**
2857
+ * Utility function to throw an error in methods that do not accept a root reference.
2858
+ */
2859
+ _throwIfRoot(name) {
2860
+ if (this._location.path === '') {
2861
+ throw invalidRootOperation(name);
2862
+ }
2863
+ }
2864
+ }
2865
+ /**
2866
+ * Download the bytes at the object's location.
2867
+ * @returns A Promise containing the downloaded bytes.
2868
+ */
2869
+ function getBytesInternal(ref, maxDownloadSizeBytes) {
2870
+ ref._throwIfRoot('getBytes');
2871
+ const requestInfo = getBytes$1(ref.storage, ref._location, maxDownloadSizeBytes);
2872
+ return ref.storage
2873
+ .makeRequestWithTokens(requestInfo, newBytesConnection)
2874
+ .then(bytes => maxDownloadSizeBytes !== undefined
2875
+ ? // GCS may not honor the Range header for small files
2876
+ bytes.slice(0, maxDownloadSizeBytes)
2877
+ : bytes);
2878
+ }
2879
+ /**
2880
+ * Download the bytes at the object's location.
2881
+ * @returns A Promise containing the downloaded blob.
2882
+ */
2883
+ function getBlobInternal(ref, maxDownloadSizeBytes) {
2884
+ ref._throwIfRoot('getBlob');
2885
+ const requestInfo = getBytes$1(ref.storage, ref._location, maxDownloadSizeBytes);
2886
+ return ref.storage
2887
+ .makeRequestWithTokens(requestInfo, newBlobConnection)
2888
+ .then(blob => maxDownloadSizeBytes !== undefined
2889
+ ? // GCS may not honor the Range header for small files
2890
+ blob.slice(0, maxDownloadSizeBytes)
2891
+ : blob);
2892
+ }
2893
+ /**
2894
+ * Uploads data to this object's location.
2895
+ * The upload is not resumable.
2896
+ *
2897
+ * @param ref - StorageReference where data should be uploaded.
2898
+ * @param data - The data to upload.
2899
+ * @param metadata - Metadata for the newly uploaded data.
2900
+ * @returns A Promise containing an UploadResult
2901
+ */
2902
+ function uploadBytes$1(ref, data, metadata) {
2903
+ ref._throwIfRoot('uploadBytes');
2904
+ const requestInfo = multipartUpload(ref.storage, ref._location, getMappings(), new FbsBlob(data, true), metadata);
2905
+ return ref.storage
2906
+ .makeRequestWithTokens(requestInfo, newTextConnection)
2907
+ .then(finalMetadata => {
2908
+ return {
2909
+ metadata: finalMetadata,
2910
+ ref
2911
+ };
2912
+ });
2913
+ }
2914
+ /**
2915
+ * Uploads data to this object's location.
2916
+ * The upload can be paused and resumed, and exposes progress updates.
2917
+ * @public
2918
+ * @param ref - StorageReference where data should be uploaded.
2919
+ * @param data - The data to upload.
2920
+ * @param metadata - Metadata for the newly uploaded data.
2921
+ * @returns An UploadTask
2922
+ */
2923
+ function uploadBytesResumable$1(ref, data, metadata) {
2924
+ ref._throwIfRoot('uploadBytesResumable');
2925
+ return new UploadTask(ref, new FbsBlob(data), metadata);
2926
+ }
2927
+ /**
2928
+ * Uploads a string to this object's location.
2929
+ * The upload is not resumable.
2930
+ * @public
2931
+ * @param ref - StorageReference where string should be uploaded.
2932
+ * @param value - The string to upload.
2933
+ * @param format - The format of the string to upload.
2934
+ * @param metadata - Metadata for the newly uploaded string.
2935
+ * @returns A Promise containing an UploadResult
2936
+ */
2937
+ function uploadString$1(ref, value, format = StringFormat.RAW, metadata) {
2938
+ ref._throwIfRoot('uploadString');
2939
+ const data = dataFromString(format, value);
2940
+ const metadataClone = { ...metadata };
2941
+ if (metadataClone['contentType'] == null && data.contentType != null) {
2942
+ metadataClone['contentType'] = data.contentType;
2943
+ }
2944
+ return uploadBytes$1(ref, data.data, metadataClone);
2945
+ }
2946
+ /**
2947
+ * List all items (files) and prefixes (folders) under this storage reference.
2948
+ *
2949
+ * This is a helper method for calling list() repeatedly until there are
2950
+ * no more results. The default pagination size is 1000.
2951
+ *
2952
+ * Note: The results may not be consistent if objects are changed while this
2953
+ * operation is running.
2954
+ *
2955
+ * Warning: listAll may potentially consume too many resources if there are
2956
+ * too many results.
2957
+ * @public
2958
+ * @param ref - StorageReference to get list from.
2959
+ *
2960
+ * @returns A Promise that resolves with all the items and prefixes under
2961
+ * the current storage reference. `prefixes` contains references to
2962
+ * sub-directories and `items` contains references to objects in this
2963
+ * folder. `nextPageToken` is never returned.
2964
+ */
2965
+ function listAll$1(ref) {
2966
+ const accumulator = {
2967
+ prefixes: [],
2968
+ items: []
2969
+ };
2970
+ return listAllHelper(ref, accumulator).then(() => accumulator);
2971
+ }
2972
+ /**
2973
+ * Separated from listAll because async functions can't use "arguments".
2974
+ * @param ref
2975
+ * @param accumulator
2976
+ * @param pageToken
2977
+ */
2978
+ async function listAllHelper(ref, accumulator, pageToken) {
2979
+ const opt = {
2980
+ // maxResults is 1000 by default.
2981
+ pageToken
2982
+ };
2983
+ const nextPage = await list$1(ref, opt);
2984
+ accumulator.prefixes.push(...nextPage.prefixes);
2985
+ accumulator.items.push(...nextPage.items);
2986
+ if (nextPage.nextPageToken != null) {
2987
+ await listAllHelper(ref, accumulator, nextPage.nextPageToken);
2988
+ }
2989
+ }
2990
+ /**
2991
+ * List items (files) and prefixes (folders) under this storage reference.
2992
+ *
2993
+ * List API is only available for Firebase Rules Version 2.
2994
+ *
2995
+ * GCS is a key-blob store. Firebase Storage imposes the semantic of '/'
2996
+ * delimited folder structure.
2997
+ * Refer to GCS's List API if you want to learn more.
2998
+ *
2999
+ * To adhere to Firebase Rules's Semantics, Firebase Storage does not
3000
+ * support objects whose paths end with "/" or contain two consecutive
3001
+ * "/"s. Firebase Storage List API will filter these unsupported objects.
3002
+ * list() may fail if there are too many unsupported objects in the bucket.
3003
+ * @public
3004
+ *
3005
+ * @param ref - StorageReference to get list from.
3006
+ * @param options - See ListOptions for details.
3007
+ * @returns A Promise that resolves with the items and prefixes.
3008
+ * `prefixes` contains references to sub-folders and `items`
3009
+ * contains references to objects in this folder. `nextPageToken`
3010
+ * can be used to get the rest of the results.
3011
+ */
3012
+ function list$1(ref, options) {
3013
+ if (options != null) {
3014
+ if (typeof options.maxResults === 'number') {
3015
+ validateNumber('options.maxResults',
3016
+ /* minValue= */ 1,
3017
+ /* maxValue= */ 1000, options.maxResults);
3018
+ }
3019
+ }
3020
+ const op = options || {};
3021
+ const requestInfo = list$2(ref.storage, ref._location,
3022
+ /*delimiter= */ '/', op.pageToken, op.maxResults);
3023
+ return ref.storage.makeRequestWithTokens(requestInfo, newTextConnection);
3024
+ }
3025
+ /**
3026
+ * A `Promise` that resolves with the metadata for this object. If this
3027
+ * object doesn't exist or metadata cannot be retrieved, the promise is
3028
+ * rejected.
3029
+ * @public
3030
+ * @param ref - StorageReference to get metadata from.
3031
+ */
3032
+ function getMetadata$1(ref) {
3033
+ ref._throwIfRoot('getMetadata');
3034
+ const requestInfo = getMetadata$2(ref.storage, ref._location, getMappings());
3035
+ return ref.storage.makeRequestWithTokens(requestInfo, newTextConnection);
3036
+ }
3037
+ /**
3038
+ * Updates the metadata for this object.
3039
+ * @public
3040
+ * @param ref - StorageReference to update metadata for.
3041
+ * @param metadata - The new metadata for the object.
3042
+ * Only values that have been explicitly set will be changed. Explicitly
3043
+ * setting a value to null will remove the metadata.
3044
+ * @returns A `Promise` that resolves
3045
+ * with the new metadata for this object.
3046
+ * See `firebaseStorage.Reference.prototype.getMetadata`
3047
+ */
3048
+ function updateMetadata$1(ref, metadata) {
3049
+ ref._throwIfRoot('updateMetadata');
3050
+ const requestInfo = updateMetadata$2(ref.storage, ref._location, metadata, getMappings());
3051
+ return ref.storage.makeRequestWithTokens(requestInfo, newTextConnection);
3052
+ }
3053
+ /**
3054
+ * Returns the download URL for the given Reference.
3055
+ * @public
3056
+ * @returns A `Promise` that resolves with the download
3057
+ * URL for this object.
3058
+ */
3059
+ function getDownloadURL$1(ref) {
3060
+ ref._throwIfRoot('getDownloadURL');
3061
+ const requestInfo = getDownloadUrl(ref.storage, ref._location, getMappings());
3062
+ return ref.storage
3063
+ .makeRequestWithTokens(requestInfo, newTextConnection)
3064
+ .then(url => {
3065
+ if (url === null) {
3066
+ throw noDownloadURL();
3067
+ }
3068
+ return url;
3069
+ });
3070
+ }
3071
+ /**
3072
+ * Deletes the object at this location.
3073
+ * @public
3074
+ * @param ref - StorageReference for object to delete.
3075
+ * @returns A `Promise` that resolves if the deletion succeeds.
3076
+ */
3077
+ function deleteObject$1(ref) {
3078
+ ref._throwIfRoot('deleteObject');
3079
+ const requestInfo = deleteObject$2(ref.storage, ref._location);
3080
+ return ref.storage.makeRequestWithTokens(requestInfo, newTextConnection);
3081
+ }
3082
+ /**
3083
+ * Returns reference for object obtained by appending `childPath` to `ref`.
3084
+ *
3085
+ * @param ref - StorageReference to get child of.
3086
+ * @param childPath - Child path from provided ref.
3087
+ * @returns A reference to the object obtained by
3088
+ * appending childPath, removing any duplicate, beginning, or trailing
3089
+ * slashes.
3090
+ *
3091
+ */
3092
+ function _getChild$1(ref, childPath) {
3093
+ const newPath = child(ref._location.path, childPath);
3094
+ const location = new Location(ref._location.bucket, newPath);
3095
+ return new Reference(ref.storage, location);
3096
+ }
3097
+
3098
+ /**
3099
+ * @license
3100
+ * Copyright 2017 Google LLC
3101
+ *
3102
+ * Licensed under the Apache License, Version 2.0 (the "License");
3103
+ * you may not use this file except in compliance with the License.
3104
+ * You may obtain a copy of the License at
3105
+ *
3106
+ * http://www.apache.org/licenses/LICENSE-2.0
3107
+ *
3108
+ * Unless required by applicable law or agreed to in writing, software
3109
+ * distributed under the License is distributed on an "AS IS" BASIS,
3110
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3111
+ * See the License for the specific language governing permissions and
3112
+ * limitations under the License.
3113
+ */
3114
+ function isUrl(path) {
3115
+ return /^[A-Za-z]+:\/\//.test(path);
3116
+ }
3117
+ /**
3118
+ * Returns a firebaseStorage.Reference for the given url.
3119
+ */
3120
+ function refFromURL(service, url) {
3121
+ return new Reference(service, url);
3122
+ }
3123
+ /**
3124
+ * Returns a firebaseStorage.Reference for the given path in the default
3125
+ * bucket.
3126
+ */
3127
+ function refFromPath(ref, path) {
3128
+ if (ref instanceof FirebaseStorageImpl) {
3129
+ const service = ref;
3130
+ if (service._bucket == null) {
3131
+ throw noDefaultBucket();
3132
+ }
3133
+ const reference = new Reference(service, service._bucket);
3134
+ if (path != null) {
3135
+ return refFromPath(reference, path);
3136
+ }
3137
+ else {
3138
+ return reference;
3139
+ }
3140
+ }
3141
+ else {
3142
+ // ref is a Reference
3143
+ if (path !== undefined) {
3144
+ return _getChild$1(ref, path);
3145
+ }
3146
+ else {
3147
+ return ref;
3148
+ }
3149
+ }
3150
+ }
3151
+ function ref$1(serviceOrRef, pathOrUrl) {
3152
+ if (pathOrUrl && isUrl(pathOrUrl)) {
3153
+ if (serviceOrRef instanceof FirebaseStorageImpl) {
3154
+ return refFromURL(serviceOrRef, pathOrUrl);
3155
+ }
3156
+ else {
3157
+ throw invalidArgument('To use ref(service, url), the first argument must be a Storage instance.');
3158
+ }
3159
+ }
3160
+ else {
3161
+ return refFromPath(serviceOrRef, pathOrUrl);
3162
+ }
3163
+ }
3164
+ function extractBucket(host, config) {
3165
+ const bucketString = config?.[CONFIG_STORAGE_BUCKET_KEY];
3166
+ if (bucketString == null) {
3167
+ return null;
3168
+ }
3169
+ return Location.makeFromBucketSpec(bucketString, host);
3170
+ }
3171
+ function connectStorageEmulator$1(storage, host, port, options = {}) {
3172
+ storage.host = `${host}:${port}`;
3173
+ const useSsl = isCloudWorkstation(host);
3174
+ // Workaround to get cookies in Firebase Studio
3175
+ if (useSsl) {
3176
+ void pingServer(`https://${storage.host}/b`);
3177
+ updateEmulatorBanner('Storage', true);
3178
+ }
3179
+ storage._isUsingEmulator = true;
3180
+ storage._protocol = useSsl ? 'https' : 'http';
3181
+ const { mockUserToken } = options;
3182
+ if (mockUserToken) {
3183
+ storage._overrideAuthToken =
3184
+ typeof mockUserToken === 'string'
3185
+ ? mockUserToken
3186
+ : createMockUserToken(mockUserToken, storage.app.options.projectId);
3187
+ }
3188
+ }
3189
+ /**
3190
+ * A service that provides Firebase Storage Reference instances.
3191
+ * @param opt_url - gs:// url to a custom Storage Bucket
3192
+ *
3193
+ * @internal
3194
+ */
3195
+ class FirebaseStorageImpl {
3196
+ constructor(
3197
+ /**
3198
+ * FirebaseApp associated with this StorageService instance.
3199
+ */
3200
+ app, _authProvider,
3201
+ /**
3202
+ * @internal
3203
+ */
3204
+ _appCheckProvider,
3205
+ /**
3206
+ * @internal
3207
+ */
3208
+ _url, _firebaseVersion, _isUsingEmulator = false) {
3209
+ this.app = app;
3210
+ this._authProvider = _authProvider;
3211
+ this._appCheckProvider = _appCheckProvider;
3212
+ this._url = _url;
3213
+ this._firebaseVersion = _firebaseVersion;
3214
+ this._isUsingEmulator = _isUsingEmulator;
3215
+ this._bucket = null;
3216
+ /**
3217
+ * This string can be in the formats:
3218
+ * - host
3219
+ * - host:port
3220
+ */
3221
+ this._host = DEFAULT_HOST;
3222
+ this._protocol = 'https';
3223
+ this._appId = null;
3224
+ this._deleted = false;
3225
+ this._maxOperationRetryTime = DEFAULT_MAX_OPERATION_RETRY_TIME;
3226
+ this._maxUploadRetryTime = DEFAULT_MAX_UPLOAD_RETRY_TIME;
3227
+ this._requests = new Set();
3228
+ if (_url != null) {
3229
+ this._bucket = Location.makeFromBucketSpec(_url, this._host);
3230
+ }
3231
+ else {
3232
+ this._bucket = extractBucket(this._host, this.app.options);
3233
+ }
3234
+ }
3235
+ /**
3236
+ * The host string for this service, in the form of `host` or
3237
+ * `host:port`.
3238
+ */
3239
+ get host() {
3240
+ return this._host;
3241
+ }
3242
+ set host(host) {
3243
+ this._host = host;
3244
+ if (this._url != null) {
3245
+ this._bucket = Location.makeFromBucketSpec(this._url, host);
3246
+ }
3247
+ else {
3248
+ this._bucket = extractBucket(host, this.app.options);
3249
+ }
3250
+ }
3251
+ /**
3252
+ * The maximum time to retry uploads in milliseconds.
3253
+ */
3254
+ get maxUploadRetryTime() {
3255
+ return this._maxUploadRetryTime;
3256
+ }
3257
+ set maxUploadRetryTime(time) {
3258
+ validateNumber('time',
3259
+ /* minValue=*/ 0,
3260
+ /* maxValue= */ Number.POSITIVE_INFINITY, time);
3261
+ this._maxUploadRetryTime = time;
3262
+ }
3263
+ /**
3264
+ * The maximum time to retry operations other than uploads or downloads in
3265
+ * milliseconds.
3266
+ */
3267
+ get maxOperationRetryTime() {
3268
+ return this._maxOperationRetryTime;
3269
+ }
3270
+ set maxOperationRetryTime(time) {
3271
+ validateNumber('time',
3272
+ /* minValue=*/ 0,
3273
+ /* maxValue= */ Number.POSITIVE_INFINITY, time);
3274
+ this._maxOperationRetryTime = time;
3275
+ }
3276
+ async _getAuthToken() {
3277
+ if (this._overrideAuthToken) {
3278
+ return this._overrideAuthToken;
3279
+ }
3280
+ const auth = this._authProvider.getImmediate({ optional: true });
3281
+ if (auth) {
3282
+ const tokenData = await auth.getToken();
3283
+ if (tokenData !== null) {
3284
+ return tokenData.accessToken;
3285
+ }
3286
+ }
3287
+ return null;
3288
+ }
3289
+ async _getAppCheckToken() {
3290
+ if (_isFirebaseServerApp(this.app) && this.app.settings.appCheckToken) {
3291
+ return this.app.settings.appCheckToken;
3292
+ }
3293
+ const appCheck = this._appCheckProvider.getImmediate({ optional: true });
3294
+ if (appCheck) {
3295
+ const result = await appCheck.getToken();
3296
+ // TODO: What do we want to do if there is an error getting the token?
3297
+ // Context: appCheck.getToken() will never throw even if an error happened. In the error case, a dummy token will be
3298
+ // returned along with an error field describing the error. In general, we shouldn't care about the error condition and just use
3299
+ // the token (actual or dummy) to send requests.
3300
+ return result.token;
3301
+ }
3302
+ return null;
3303
+ }
3304
+ /**
3305
+ * Stop running requests and prevent more from being created.
3306
+ */
3307
+ _delete() {
3308
+ if (!this._deleted) {
3309
+ this._deleted = true;
3310
+ this._requests.forEach(request => request.cancel());
3311
+ this._requests.clear();
3312
+ }
3313
+ return Promise.resolve();
3314
+ }
3315
+ /**
3316
+ * Returns a new firebaseStorage.Reference object referencing this StorageService
3317
+ * at the given Location.
3318
+ */
3319
+ _makeStorageReference(loc) {
3320
+ return new Reference(this, loc);
3321
+ }
3322
+ /**
3323
+ * @param requestInfo - HTTP RequestInfo object
3324
+ * @param authToken - Firebase auth token
3325
+ */
3326
+ _makeRequest(requestInfo, requestFactory, authToken, appCheckToken, retry = true) {
3327
+ if (!this._deleted) {
3328
+ const request = makeRequest(requestInfo, this._appId, authToken, appCheckToken, requestFactory, this._firebaseVersion, retry, this._isUsingEmulator);
3329
+ this._requests.add(request);
3330
+ // Request removes itself from set when complete.
3331
+ request.getPromise().then(() => this._requests.delete(request), () => this._requests.delete(request));
3332
+ return request;
3333
+ }
3334
+ else {
3335
+ return new FailRequest(appDeleted());
3336
+ }
3337
+ }
3338
+ async makeRequestWithTokens(requestInfo, requestFactory) {
3339
+ const [authToken, appCheckToken] = await Promise.all([
3340
+ this._getAuthToken(),
3341
+ this._getAppCheckToken()
3342
+ ]);
3343
+ return this._makeRequest(requestInfo, requestFactory, authToken, appCheckToken).getPromise();
3344
+ }
3345
+ }
3346
+
3347
+ const name = "@firebase/storage";
3348
+ const version = "0.14.1";
3349
+
3350
+ /**
3351
+ * @license
3352
+ * Copyright 2020 Google LLC
3353
+ *
3354
+ * Licensed under the Apache License, Version 2.0 (the "License");
3355
+ * you may not use this file except in compliance with the License.
3356
+ * You may obtain a copy of the License at
3357
+ *
3358
+ * http://www.apache.org/licenses/LICENSE-2.0
3359
+ *
3360
+ * Unless required by applicable law or agreed to in writing, software
3361
+ * distributed under the License is distributed on an "AS IS" BASIS,
3362
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3363
+ * See the License for the specific language governing permissions and
3364
+ * limitations under the License.
3365
+ */
3366
+ /**
3367
+ * Type constant for Firebase Storage.
3368
+ */
3369
+ const STORAGE_TYPE = 'storage';
3370
+
3371
+ /**
3372
+ * @license
3373
+ * Copyright 2020 Google LLC
3374
+ *
3375
+ * Licensed under the Apache License, Version 2.0 (the "License");
3376
+ * you may not use this file except in compliance with the License.
3377
+ * You may obtain a copy of the License at
3378
+ *
3379
+ * http://www.apache.org/licenses/LICENSE-2.0
3380
+ *
3381
+ * Unless required by applicable law or agreed to in writing, software
3382
+ * distributed under the License is distributed on an "AS IS" BASIS,
3383
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3384
+ * See the License for the specific language governing permissions and
3385
+ * limitations under the License.
3386
+ */
3387
+ /**
3388
+ * Downloads the data at the object's location. Returns an error if the object
3389
+ * is not found.
3390
+ *
3391
+ * To use this functionality, you have to whitelist your app's origin in your
3392
+ * Cloud Storage bucket. See also
3393
+ * https://cloud.google.com/storage/docs/configuring-cors
3394
+ *
3395
+ * @public
3396
+ * @param ref - StorageReference where data should be downloaded.
3397
+ * @param maxDownloadSizeBytes - If set, the maximum allowed size in bytes to
3398
+ * retrieve.
3399
+ * @returns A Promise containing the object's bytes
3400
+ */
3401
+ function getBytes(ref, maxDownloadSizeBytes) {
3402
+ ref = getModularInstance(ref);
3403
+ return getBytesInternal(ref, maxDownloadSizeBytes);
3404
+ }
3405
+ /**
3406
+ * Uploads data to this object's location.
3407
+ * The upload is not resumable.
3408
+ * @public
3409
+ * @param ref - {@link StorageReference} where data should be uploaded.
3410
+ * @param data - The data to upload.
3411
+ * @param metadata - Metadata for the data to upload.
3412
+ * @returns A Promise containing an UploadResult
3413
+ */
3414
+ function uploadBytes(ref, data, metadata) {
3415
+ ref = getModularInstance(ref);
3416
+ return uploadBytes$1(ref, data, metadata);
3417
+ }
3418
+ /**
3419
+ * Uploads a string to this object's location.
3420
+ * The upload is not resumable.
3421
+ * @public
3422
+ * @param ref - {@link StorageReference} where string should be uploaded.
3423
+ * @param value - The string to upload.
3424
+ * @param format - The format of the string to upload.
3425
+ * @param metadata - Metadata for the string to upload.
3426
+ * @returns A Promise containing an UploadResult
3427
+ */
3428
+ function uploadString(ref, value, format, metadata) {
3429
+ ref = getModularInstance(ref);
3430
+ return uploadString$1(ref, value, format, metadata);
3431
+ }
3432
+ /**
3433
+ * Uploads data to this object's location.
3434
+ * The upload can be paused and resumed, and exposes progress updates.
3435
+ * @public
3436
+ * @param ref - {@link StorageReference} where data should be uploaded.
3437
+ * @param data - The data to upload.
3438
+ * @param metadata - Metadata for the data to upload.
3439
+ * @returns An UploadTask
3440
+ */
3441
+ function uploadBytesResumable(ref, data, metadata) {
3442
+ ref = getModularInstance(ref);
3443
+ return uploadBytesResumable$1(ref, data, metadata);
3444
+ }
3445
+ /**
3446
+ * A `Promise` that resolves with the metadata for this object. If this
3447
+ * object doesn't exist or metadata cannot be retrieved, the promise is
3448
+ * rejected.
3449
+ * @public
3450
+ * @param ref - {@link StorageReference} to get metadata from.
3451
+ */
3452
+ function getMetadata(ref) {
3453
+ ref = getModularInstance(ref);
3454
+ return getMetadata$1(ref);
3455
+ }
3456
+ /**
3457
+ * Updates the metadata for this object.
3458
+ * @public
3459
+ * @param ref - {@link StorageReference} to update metadata for.
3460
+ * @param metadata - The new metadata for the object.
3461
+ * Only values that have been explicitly set will be changed. Explicitly
3462
+ * setting a value to null will remove the metadata.
3463
+ * @returns A `Promise` that resolves with the new metadata for this object.
3464
+ */
3465
+ function updateMetadata(ref, metadata) {
3466
+ ref = getModularInstance(ref);
3467
+ return updateMetadata$1(ref, metadata);
3468
+ }
3469
+ /**
3470
+ * List items (files) and prefixes (folders) under this storage reference.
3471
+ *
3472
+ * List API is only available for Firebase Rules Version 2.
3473
+ *
3474
+ * GCS is a key-blob store. Firebase Storage imposes the semantic of '/'
3475
+ * delimited folder structure.
3476
+ * Refer to GCS's List API if you want to learn more.
3477
+ *
3478
+ * To adhere to Firebase Rules's Semantics, Firebase Storage does not
3479
+ * support objects whose paths end with "/" or contain two consecutive
3480
+ * "/"s. Firebase Storage List API will filter these unsupported objects.
3481
+ * list() may fail if there are too many unsupported objects in the bucket.
3482
+ * @public
3483
+ *
3484
+ * @param ref - {@link StorageReference} to get list from.
3485
+ * @param options - See {@link ListOptions} for details.
3486
+ * @returns A `Promise` that resolves with the items and prefixes.
3487
+ * `prefixes` contains references to sub-folders and `items`
3488
+ * contains references to objects in this folder. `nextPageToken`
3489
+ * can be used to get the rest of the results.
3490
+ */
3491
+ function list(ref, options) {
3492
+ ref = getModularInstance(ref);
3493
+ return list$1(ref, options);
3494
+ }
3495
+ /**
3496
+ * List all items (files) and prefixes (folders) under this storage reference.
3497
+ *
3498
+ * This is a helper method for calling list() repeatedly until there are
3499
+ * no more results. The default pagination size is 1000.
3500
+ *
3501
+ * Note: The results may not be consistent if objects are changed while this
3502
+ * operation is running.
3503
+ *
3504
+ * Warning: `listAll` may potentially consume too many resources if there are
3505
+ * too many results.
3506
+ * @public
3507
+ * @param ref - {@link StorageReference} to get list from.
3508
+ *
3509
+ * @returns A `Promise` that resolves with all the items and prefixes under
3510
+ * the current storage reference. `prefixes` contains references to
3511
+ * sub-directories and `items` contains references to objects in this
3512
+ * folder. `nextPageToken` is never returned.
3513
+ */
3514
+ function listAll(ref) {
3515
+ ref = getModularInstance(ref);
3516
+ return listAll$1(ref);
3517
+ }
3518
+ /**
3519
+ * Returns the download URL for the given {@link StorageReference}.
3520
+ * @public
3521
+ * @param ref - {@link StorageReference} to get the download URL for.
3522
+ * @returns A `Promise` that resolves with the download
3523
+ * URL for this object.
3524
+ */
3525
+ function getDownloadURL(ref) {
3526
+ ref = getModularInstance(ref);
3527
+ return getDownloadURL$1(ref);
3528
+ }
3529
+ /**
3530
+ * Deletes the object at this location.
3531
+ * @public
3532
+ * @param ref - {@link StorageReference} for object to delete.
3533
+ * @returns A `Promise` that resolves if the deletion succeeds.
3534
+ */
3535
+ function deleteObject(ref) {
3536
+ ref = getModularInstance(ref);
3537
+ return deleteObject$1(ref);
3538
+ }
3539
+ function ref(serviceOrRef, pathOrUrl) {
3540
+ serviceOrRef = getModularInstance(serviceOrRef);
3541
+ return ref$1(serviceOrRef, pathOrUrl);
3542
+ }
3543
+ /**
3544
+ * @internal
3545
+ */
3546
+ function _getChild(ref, childPath) {
3547
+ return _getChild$1(ref, childPath);
3548
+ }
3549
+ /**
3550
+ * Gets a {@link FirebaseStorage} instance for the given Firebase app.
3551
+ * @public
3552
+ * @param app - Firebase app to get {@link FirebaseStorage} instance for.
3553
+ * @param bucketUrl - The gs:// url to your Firebase Storage Bucket.
3554
+ * If not passed, uses the app's default Storage Bucket.
3555
+ * @returns A {@link FirebaseStorage} instance.
3556
+ */
3557
+ function getStorage(app = getApp(), bucketUrl) {
3558
+ app = getModularInstance(app);
3559
+ const storageProvider = _getProvider(app, STORAGE_TYPE);
3560
+ const storageInstance = storageProvider.getImmediate({
3561
+ identifier: bucketUrl
3562
+ });
3563
+ const emulator = getDefaultEmulatorHostnameAndPort('storage');
3564
+ if (emulator) {
3565
+ connectStorageEmulator(storageInstance, ...emulator);
3566
+ }
3567
+ return storageInstance;
3568
+ }
3569
+ /**
3570
+ * Modify this {@link FirebaseStorage} instance to communicate with the Cloud Storage emulator.
3571
+ *
3572
+ * @param storage - The {@link FirebaseStorage} instance
3573
+ * @param host - The emulator host (ex: localhost)
3574
+ * @param port - The emulator port (ex: 5001)
3575
+ * @param options - Emulator options. `options.mockUserToken` is the mock auth
3576
+ * token to use for unit testing Security Rules.
3577
+ * @public
3578
+ */
3579
+ function connectStorageEmulator(storage, host, port, options = {}) {
3580
+ connectStorageEmulator$1(storage, host, port, options);
3581
+ }
3582
+
3583
+ /**
3584
+ * @license
3585
+ * Copyright 2021 Google LLC
3586
+ *
3587
+ * Licensed under the Apache License, Version 2.0 (the "License");
3588
+ * you may not use this file except in compliance with the License.
3589
+ * You may obtain a copy of the License at
3590
+ *
3591
+ * http://www.apache.org/licenses/LICENSE-2.0
3592
+ *
3593
+ * Unless required by applicable law or agreed to in writing, software
3594
+ * distributed under the License is distributed on an "AS IS" BASIS,
3595
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3596
+ * See the License for the specific language governing permissions and
3597
+ * limitations under the License.
3598
+ */
3599
+ /**
3600
+ * Downloads the data at the object's location. Returns an error if the object
3601
+ * is not found.
3602
+ *
3603
+ * To use this functionality, you have to whitelist your app's origin in your
3604
+ * Cloud Storage bucket. See also
3605
+ * https://cloud.google.com/storage/docs/configuring-cors
3606
+ *
3607
+ * This API is not available in Node.
3608
+ *
3609
+ * @public
3610
+ * @param ref - StorageReference where data should be downloaded.
3611
+ * @param maxDownloadSizeBytes - If set, the maximum allowed size in bytes to
3612
+ * retrieve.
3613
+ * @returns A Promise that resolves with a Blob containing the object's bytes
3614
+ */
3615
+ function getBlob(ref, maxDownloadSizeBytes) {
3616
+ ref = getModularInstance(ref);
3617
+ return getBlobInternal(ref, maxDownloadSizeBytes);
3618
+ }
3619
+ /**
3620
+ * Downloads the data at the object's location. Raises an error event if the
3621
+ * object is not found.
3622
+ *
3623
+ * This API is only available in Node.
3624
+ *
3625
+ * @public
3626
+ * @param ref - StorageReference where data should be downloaded.
3627
+ * @param maxDownloadSizeBytes - If set, the maximum allowed size in bytes to
3628
+ * retrieve.
3629
+ * @returns A stream with the object's data as bytes
3630
+ */
3631
+ function getStream(ref, maxDownloadSizeBytes) {
3632
+ throw new Error('getStream() is only supported by NodeJS builds');
3633
+ }
3634
+
3635
+ /**
3636
+ * Cloud Storage for Firebase
3637
+ *
3638
+ * @packageDocumentation
3639
+ */
3640
+ function factory(container, { instanceIdentifier: url }) {
3641
+ const app = container.getProvider('app').getImmediate();
3642
+ const authProvider = container.getProvider('auth-internal');
3643
+ const appCheckProvider = container.getProvider('app-check-internal');
3644
+ return new FirebaseStorageImpl(app, authProvider, appCheckProvider, url, SDK_VERSION);
3645
+ }
3646
+ function registerStorage() {
3647
+ _registerComponent(new Component(STORAGE_TYPE, factory, "PUBLIC" /* ComponentType.PUBLIC */).setMultipleInstances(true));
3648
+ //RUNTIME_ENV will be replaced during the compilation to "node" for nodejs and an empty string for browser
3649
+ registerVersion(name, version, '');
3650
+ // BUILD_TARGET will be replaced by values like esm, cjs, etc during the compilation
3651
+ registerVersion(name, version, 'esm2020');
3652
+ }
3653
+ registerStorage();
3654
+
3655
+ export { StorageError, StorageErrorCode, StringFormat, FbsBlob as _FbsBlob, Location as _Location, TaskEvent as _TaskEvent, TaskState as _TaskState, UploadTask as _UploadTask, dataFromString as _dataFromString, _getChild, invalidArgument as _invalidArgument, invalidRootOperation as _invalidRootOperation, connectStorageEmulator, deleteObject, getBlob, getBytes, getDownloadURL, getMetadata, getStorage, getStream, list, listAll, ref, updateMetadata, uploadBytes, uploadBytesResumable, uploadString };
3656
+ //# sourceMappingURL=index.esm.js.map