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