import firebase from '@firebase/app-compat'; import { FirebaseError } from '@firebase/util'; import { _getChild, uploadBytesResumable, StringFormat as StringFormat$1, _UploadTask, _FbsBlob, listAll, list, getMetadata, updateMetadata, getDownloadURL, deleteObject, ref, _Location, connectStorageEmulator } from '@firebase/storage'; import { Component } from '@firebase/component'; /** * An error returned by the Firebase Storage SDK. * @public */ class FirebaseStorageError extends FirebaseError { /** * @param code - A StorageErrorCode string to be prefixed with 'storage/' and * added to the end of the message. * @param message - Error message. */ constructor(code, message) { super(prependCode(code), `Firebase Storage: ${message} (${prependCode(code)})`); /** * Stores custom error data unque to FirebaseStorageError. */ this.customData = { serverResponse: null }; this._baseMessage = this.message; // Without this, `instanceof FirebaseStorageError`, in tests for example, // returns false. Object.setPrototypeOf(this, FirebaseStorageError.prototype); } /** * Compares a StorageErrorCode against this error's code, filtering out the prefix. */ _codeEquals(code) { return prependCode(code) === this.code; } /** * Optional response message that was added by the server. */ get serverResponse() { return this.customData.serverResponse; } set serverResponse(serverResponse) { this.customData.serverResponse = serverResponse; if (this.customData.serverResponse) { this.message = `${this._baseMessage}\n${this.customData.serverResponse}`; } else { this.message = this._baseMessage; } } } function prependCode(code) { return 'storage/' + code; } function unknown() { const message = 'An unknown error occurred, please check the error payload for ' + 'server response.'; return new FirebaseStorageError("unknown" /* UNKNOWN */, message); } function invalidArgument(message) { return new FirebaseStorageError("invalid-argument" /* INVALID_ARGUMENT */, message); } /** * @param name - The name of the operation that was invalid. */ function invalidRootOperation(name) { return new FirebaseStorageError("invalid-root-operation" /* INVALID_ROOT_OPERATION */, "The operation '" + name + "' cannot be performed on a root reference, create a non-root " + "reference using child, such as .child('file.png')."); } /** * @param format - The format that was not valid. * @param message - A message describing the format violation. */ function invalidFormat(format, message) { return new FirebaseStorageError("invalid-format" /* INVALID_FORMAT */, "String does not match format '" + format + "': " + message); } /** * @license * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** Converts a Base64 encoded string to a binary string. */ function decodeBase64(encoded) { return atob(encoded); } /** * @license * Copyright 2017 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * An enumeration of the possible string formats for upload. * @public */ const StringFormat = { /** * Indicates the string should be interpreted "raw", that is, as normal text. * The string will be interpreted as UTF-16, then uploaded as a UTF-8 byte * sequence. * Example: The string 'Hello! \\ud83d\\ude0a' becomes the byte sequence * 48 65 6c 6c 6f 21 20 f0 9f 98 8a */ RAW: 'raw', /** * Indicates the string should be interpreted as base64-encoded data. * Padding characters (trailing '='s) are optional. * Example: The string 'rWmO++E6t7/rlw==' becomes the byte sequence * ad 69 8e fb e1 3a b7 bf eb 97 */ BASE64: 'base64', /** * Indicates the string should be interpreted as base64url-encoded data. * Padding characters (trailing '='s) are optional. * Example: The string 'rWmO--E6t7_rlw==' becomes the byte sequence * ad 69 8e fb e1 3a b7 bf eb 97 */ BASE64URL: 'base64url', /** * Indicates the string is a data URL, such as one obtained from * canvas.toDataURL(). * Example: the string 'data:application/octet-stream;base64,aaaa' * becomes the byte sequence * 69 a6 9a * (the content-type "application/octet-stream" is also applied, but can * be overridden in the metadata object). */ DATA_URL: 'data_url' }; class StringData { constructor(data, contentType) { this.data = data; this.contentType = contentType || null; } } function dataFromString(format, stringData) { switch (format) { case StringFormat.RAW: return new StringData(utf8Bytes_(stringData)); case StringFormat.BASE64: case StringFormat.BASE64URL: return new StringData(base64Bytes_(format, stringData)); case StringFormat.DATA_URL: return new StringData(dataURLBytes_(stringData), dataURLContentType_(stringData)); // do nothing } // assert(false); throw unknown(); } function utf8Bytes_(value) { const b = []; for (let i = 0; i < value.length; i++) { let c = value.charCodeAt(i); if (c <= 127) { b.push(c); } else { if (c <= 2047) { b.push(192 | (c >> 6), 128 | (c & 63)); } else { if ((c & 64512) === 55296) { // The start of a surrogate pair. const valid = i < value.length - 1 && (value.charCodeAt(i + 1) & 64512) === 56320; if (!valid) { // The second surrogate wasn't there. b.push(239, 191, 189); } else { const hi = c; const lo = value.charCodeAt(++i); c = 65536 | ((hi & 1023) << 10) | (lo & 1023); b.push(240 | (c >> 18), 128 | ((c >> 12) & 63), 128 | ((c >> 6) & 63), 128 | (c & 63)); } } else { if ((c & 64512) === 56320) { // Invalid low surrogate. b.push(239, 191, 189); } else { b.push(224 | (c >> 12), 128 | ((c >> 6) & 63), 128 | (c & 63)); } } } } } return new Uint8Array(b); } function percentEncodedBytes_(value) { let decoded; try { decoded = decodeURIComponent(value); } catch (e) { throw invalidFormat(StringFormat.DATA_URL, 'Malformed data URL.'); } return utf8Bytes_(decoded); } function base64Bytes_(format, value) { switch (format) { case StringFormat.BASE64: { const hasMinus = value.indexOf('-') !== -1; const hasUnder = value.indexOf('_') !== -1; if (hasMinus || hasUnder) { const invalidChar = hasMinus ? '-' : '_'; throw invalidFormat(format, "Invalid character '" + invalidChar + "' found: is it base64url encoded?"); } break; } case StringFormat.BASE64URL: { const hasPlus = value.indexOf('+') !== -1; const hasSlash = value.indexOf('/') !== -1; if (hasPlus || hasSlash) { const invalidChar = hasPlus ? '+' : '/'; throw invalidFormat(format, "Invalid character '" + invalidChar + "' found: is it base64 encoded?"); } value = value.replace(/-/g, '+').replace(/_/g, '/'); break; } // do nothing } let bytes; try { bytes = decodeBase64(value); } catch (e) { throw invalidFormat(format, 'Invalid character found'); } const array = new Uint8Array(bytes.length); for (let i = 0; i < bytes.length; i++) { array[i] = bytes.charCodeAt(i); } return array; } class DataURLParts { constructor(dataURL) { this.base64 = false; this.contentType = null; const matches = dataURL.match(/^data:([^,]+)?,/); if (matches === null) { throw invalidFormat(StringFormat.DATA_URL, "Must be formatted 'data:[<mediatype>][;base64],<data>"); } const middle = matches[1] || null; if (middle != null) { this.base64 = endsWith(middle, ';base64'); this.contentType = this.base64 ? middle.substring(0, middle.length - ';base64'.length) : middle; } this.rest = dataURL.substring(dataURL.indexOf(',') + 1); } } function dataURLBytes_(dataUrl) { const parts = new DataURLParts(dataUrl); if (parts.base64) { return base64Bytes_(StringFormat.BASE64, parts.rest); } else { return percentEncodedBytes_(parts.rest); } } function dataURLContentType_(dataUrl) { const parts = new DataURLParts(dataUrl); return parts.contentType; } function endsWith(s, end) { const longEnough = s.length >= end.length; if (!longEnough) { return false; } return s.substring(s.length - end.length) === end; } /** * @license * Copyright 2017 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * An event that is triggered on a task. */ const TaskEvent = { /** * For this event, * <ul> * <li>The `next` function is triggered on progress updates and when the * task is paused/resumed with an `UploadTaskSnapshot` as the first * argument.</li> * <li>The `error` function is triggered if the upload is canceled or fails * for another reason.</li> * <li>The `complete` function is triggered if the upload completes * successfully.</li> * </ul> */ STATE_CHANGED: 'state_changed' }; /** * Represents the current state of a running upload. */ const TaskState = { /** The task is currently transferring data. */ RUNNING: 'running', /** The task was paused by the user. */ PAUSED: 'paused', /** The task completed successfully. */ SUCCESS: 'success', /** The task was canceled. */ CANCELED: 'canceled', /** The task failed with an error. */ ERROR: 'error' }; /** * @license * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ class UploadTaskSnapshotCompat { constructor(_delegate, task, ref) { this._delegate = _delegate; this.task = task; this.ref = ref; } get bytesTransferred() { return this._delegate.bytesTransferred; } get metadata() { return this._delegate.metadata; } get state() { return this._delegate.state; } get totalBytes() { return this._delegate.totalBytes; } } /** * @license * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ class UploadTaskCompat { constructor(_delegate, _ref) { this._delegate = _delegate; this._ref = _ref; this.cancel = this._delegate.cancel.bind(this._delegate); this.catch = this._delegate.catch.bind(this._delegate); this.pause = this._delegate.pause.bind(this._delegate); this.resume = this._delegate.resume.bind(this._delegate); } get snapshot() { return new UploadTaskSnapshotCompat(this._delegate.snapshot, this, this._ref); } then(onFulfilled, onRejected) { return this._delegate.then(snapshot => { if (onFulfilled) { return onFulfilled(new UploadTaskSnapshotCompat(snapshot, this, this._ref)); } }, onRejected); } on(type, nextOrObserver, error, completed) { let wrappedNextOrObserver = undefined; if (!!nextOrObserver) { if (typeof nextOrObserver === 'function') { wrappedNextOrObserver = (taskSnapshot) => nextOrObserver(new UploadTaskSnapshotCompat(taskSnapshot, this, this._ref)); } else { wrappedNextOrObserver = { next: !!nextOrObserver.next ? (taskSnapshot) => nextOrObserver.next(new UploadTaskSnapshotCompat(taskSnapshot, this, this._ref)) : undefined, complete: nextOrObserver.complete || undefined, error: nextOrObserver.error || undefined }; } } return this._delegate.on(type, wrappedNextOrObserver, error || undefined, completed || undefined); } } /** * @license * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ class ListResultCompat { constructor(_delegate, _service) { this._delegate = _delegate; this._service = _service; } get prefixes() { return this._delegate.prefixes.map(ref => new ReferenceCompat(ref, this._service)); } get items() { return this._delegate.items.map(ref => new ReferenceCompat(ref, this._service)); } get nextPageToken() { return this._delegate.nextPageToken || null; } } /** * @license * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ class ReferenceCompat { constructor(_delegate, storage) { this._delegate = _delegate; this.storage = storage; } get name() { return this._delegate.name; } get bucket() { return this._delegate.bucket; } get fullPath() { return this._delegate.fullPath; } toString() { return this._delegate.toString(); } /** * @returns A reference to the object obtained by * appending childPath, removing any duplicate, beginning, or trailing * slashes. */ child(childPath) { const reference = _getChild(this._delegate, childPath); return new ReferenceCompat(reference, this.storage); } get root() { return new ReferenceCompat(this._delegate.root, this.storage); } /** * @returns A reference to the parent of the * current object, or null if the current object is the root. */ get parent() { const reference = this._delegate.parent; if (reference == null) { return null; } return new ReferenceCompat(reference, this.storage); } /** * Uploads a blob to this object's location. * @param data - The blob to upload. * @returns An UploadTask that lets you control and * observe the upload. */ put(data, metadata) { this._throwIfRoot('put'); return new UploadTaskCompat(uploadBytesResumable(this._delegate, data, metadata), this); } /** * Uploads a string to this object's location. * @param value - The string to upload. * @param format - The format of the string to upload. * @returns An UploadTask that lets you control and * observe the upload. */ putString(value, format = StringFormat$1.RAW, metadata) { this._throwIfRoot('putString'); const data = dataFromString(format, value); const metadataClone = Object.assign({}, metadata); if (metadataClone['contentType'] == null && data.contentType != null) { metadataClone['contentType'] = data.contentType; } return new UploadTaskCompat(new _UploadTask(this._delegate, new _FbsBlob(data.data, true), metadataClone), this); } /** * List all items (files) and prefixes (folders) under this storage reference. * * This is a helper method for calling list() repeatedly until there are * no more results. The default pagination size is 1000. * * Note: The results may not be consistent if objects are changed while this * operation is running. * * Warning: listAll may potentially consume too many resources if there are * too many results. * * @returns A Promise that resolves with all the items and prefixes under * the current storage reference. `prefixes` contains references to * sub-directories and `items` contains references to objects in this * folder. `nextPageToken` is never returned. */ listAll() { return listAll(this._delegate).then(r => new ListResultCompat(r, this.storage)); } /** * List items (files) and prefixes (folders) under this storage reference. * * List API is only available for Firebase Rules Version 2. * * GCS is a key-blob store. Firebase Storage imposes the semantic of '/' * delimited folder structure. Refer to GCS's List API if you want to learn more. * * To adhere to Firebase Rules's Semantics, Firebase Storage does not * support objects whose paths end with "/" or contain two consecutive * "/"s. Firebase Storage List API will filter these unsupported objects. * list() may fail if there are too many unsupported objects in the bucket. * * @param options - See ListOptions for details. * @returns A Promise that resolves with the items and prefixes. * `prefixes` contains references to sub-folders and `items` * contains references to objects in this folder. `nextPageToken` * can be used to get the rest of the results. */ list(options) { return list(this._delegate, options || undefined).then(r => new ListResultCompat(r, this.storage)); } /** * A promise that resolves with the metadata for this object. If this * object doesn't exist or metadata cannot be retreived, the promise is * rejected. */ getMetadata() { return getMetadata(this._delegate); } /** * Updates the metadata for this object. * @param metadata - The new metadata for the object. * Only values that have been explicitly set will be changed. Explicitly * setting a value to null will remove the metadata. * @returns A promise that resolves * with the new metadata for this object. * @see firebaseStorage.Reference.prototype.getMetadata */ updateMetadata(metadata) { return updateMetadata(this._delegate, metadata); } /** * @returns A promise that resolves with the download * URL for this object. */ getDownloadURL() { return getDownloadURL(this._delegate); } /** * Deletes the object at this location. * @returns A promise that resolves if the deletion succeeds. */ delete() { this._throwIfRoot('delete'); return deleteObject(this._delegate); } _throwIfRoot(name) { if (this._delegate._location.path === '') { throw invalidRootOperation(name); } } } /** * @license * Copyright 2017 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ function isUrl(path) { return /^[A-Za-z]+:\/\//.test(path); } /** * @license * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * A service that provides firebaseStorage.Reference instances. * @param opt_url gs:// url to a custom Storage Bucket */ class StorageServiceCompat { constructor(app, _delegate) { this.app = app; this._delegate = _delegate; } get maxOperationRetryTime() { return this._delegate.maxOperationRetryTime; } get maxUploadRetryTime() { return this._delegate.maxUploadRetryTime; } /** * Returns a firebaseStorage.Reference for the given path in the default * bucket. */ ref(path) { if (isUrl(path)) { throw invalidArgument('ref() expected a child path but got a URL, use refFromURL instead.'); } return new ReferenceCompat(ref(this._delegate, path), this); } /** * Returns a firebaseStorage.Reference object for the given absolute URL, * which must be a gs:// or http[s]:// URL. */ refFromURL(url) { if (!isUrl(url)) { throw invalidArgument('refFromURL() expected a full URL but got a child path, use ref() instead.'); } try { _Location.makeFromUrl(url, this._delegate.host); } catch (e) { throw invalidArgument('refFromUrl() expected a valid full URL but got an invalid one.'); } return new ReferenceCompat(ref(this._delegate, url), this); } setMaxUploadRetryTime(time) { this._delegate.maxUploadRetryTime = time; } setMaxOperationRetryTime(time) { this._delegate.maxOperationRetryTime = time; } useEmulator(host, port) { connectStorageEmulator(this._delegate, host, port); } } const name = "@firebase/storage-compat"; const version = "0.0.900"; /** * @license * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Type constant for Firebase Storage. */ const STORAGE_TYPE = 'storage'; function factory(container, { instanceIdentifier: url }) { // Dependencies const app = container.getProvider('app-compat').getImmediate(); const storageExp = container .getProvider('storage-exp') .getImmediate({ identifier: url }); const storageServiceCompat = new StorageServiceCompat(app, storageExp); return storageServiceCompat; } function registerStorage(instance) { const namespaceExports = { // no-inline TaskState, TaskEvent, StringFormat, Storage: StorageServiceCompat, Reference: ReferenceCompat }; instance.INTERNAL.registerComponent(new Component(STORAGE_TYPE, factory, "PUBLIC" /* PUBLIC */) .setServiceProps(namespaceExports) .setMultipleInstances(true)); instance.registerVersion(name, version); } registerStorage(firebase); export { registerStorage }; //# sourceMappingURL=index.js.map