diff --git a/packages/storage/android/src/main/java/io/invertase/firebase/storage/ReactNativeFirebaseStorageCommon.java b/packages/storage/android/src/main/java/io/invertase/firebase/storage/ReactNativeFirebaseStorageCommon.java index d988c85e..5ac65402 100644 --- a/packages/storage/android/src/main/java/io/invertase/firebase/storage/ReactNativeFirebaseStorageCommon.java +++ b/packages/storage/android/src/main/java/io/invertase/firebase/storage/ReactNativeFirebaseStorageCommon.java @@ -27,9 +27,12 @@ import android.webkit.MimeTypeMap; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; +import com.google.firebase.storage.ListResult; import com.google.firebase.storage.StorageException; import com.google.firebase.storage.StorageMetadata; +import com.google.firebase.storage.StorageReference; import com.google.firebase.storage.StorageTask; import java.util.Map; @@ -194,6 +197,27 @@ class ReactNativeFirebaseStorageCommon { return metadata; } + static WritableMap getListResultAsMap(ListResult listResult) { + WritableMap map = Arguments.createMap(); + map.putString("nextPageToken", listResult.getPageToken()); + + WritableArray items = Arguments.createArray(); + WritableArray prefixes = Arguments.createArray(); + + for (StorageReference reference : listResult.getItems()) { + items.pushString(reference.getPath()); + } + + for (StorageReference reference : listResult.getPrefixes()) { + prefixes.pushString(reference.getPath()); + } + + map.putArray("items", items); + map.putArray("prefixes", prefixes); + + return map; + } + static String[] getExceptionCodeAndMessage(@Nullable Exception exception) { String code = STATUS_UNKNOWN; String message = "An unknown error has occurred."; diff --git a/packages/storage/android/src/main/java/io/invertase/firebase/storage/ReactNativeFirebaseStorageModule.java b/packages/storage/android/src/main/java/io/invertase/firebase/storage/ReactNativeFirebaseStorageModule.java index 5e4999d8..c89ae50b 100644 --- a/packages/storage/android/src/main/java/io/invertase/firebase/storage/ReactNativeFirebaseStorageModule.java +++ b/packages/storage/android/src/main/java/io/invertase/firebase/storage/ReactNativeFirebaseStorageModule.java @@ -22,13 +22,17 @@ import android.net.Uri; import android.os.Build; import android.os.Environment; +import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.bridge.WritableMap; import com.google.android.gms.tasks.Task; import com.google.firebase.FirebaseApp; import com.google.firebase.storage.FirebaseStorage; +import com.google.firebase.storage.ListResult; import com.google.firebase.storage.StorageMetadata; import com.google.firebase.storage.StorageReference; @@ -41,6 +45,7 @@ import java.util.Objects; import io.invertase.firebase.common.ReactNativeFirebaseModule; import static io.invertase.firebase.storage.ReactNativeFirebaseStorageCommon.buildMetadataFromMap; +import static io.invertase.firebase.storage.ReactNativeFirebaseStorageCommon.getListResultAsMap; import static io.invertase.firebase.storage.ReactNativeFirebaseStorageCommon.getMetadataAsMap; import static io.invertase.firebase.storage.ReactNativeFirebaseStorageCommon.isExternalStorageWritable; import static io.invertase.firebase.storage.ReactNativeFirebaseStorageCommon.promiseRejectStorageException; @@ -113,6 +118,41 @@ public class ReactNativeFirebaseStorageModule extends ReactNativeFirebaseModule }); } + @ReactMethod + public void list(String appName, String url, ReadableMap listOptions, Promise promise) { + StorageReference reference = getReferenceFromUrl(url, appName); + Task list; + + int maxResults = listOptions.getInt("maxResults"); + + if (listOptions.hasKey("pageToken")) { + String pageToken = listOptions.getString("pageToken"); + list = reference.list(maxResults, Objects.requireNonNull(pageToken)); + } else { + list = reference.list(maxResults); + } + + list.addOnCompleteListener(getExecutor(), task -> { + if (task.isSuccessful()) { + promise.resolve(getListResultAsMap(task.getResult())); + } else { + promiseRejectStorageException(promise, task.getException()); + } + }); + } + + @ReactMethod + public void listAll(String appName, String url, Promise promise) { + StorageReference reference = getReferenceFromUrl(url, appName); + reference.listAll().addOnCompleteListener(getExecutor(), task -> { + if (task.isSuccessful()) { + promise.resolve(getListResultAsMap(task.getResult())); + } else { + promiseRejectStorageException(promise, task.getException()); + } + }); + } + /** * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#updateMetadata */ diff --git a/packages/storage/e2e/StorageReference.e2e.js b/packages/storage/e2e/StorageReference.e2e.js index 4ff3243a..e988026c 100644 --- a/packages/storage/e2e/StorageReference.e2e.js +++ b/packages/storage/e2e/StorageReference.e2e.js @@ -221,6 +221,133 @@ describe('storage() -> StorageReference', () => { }); }); + describe('list', () => { + it('should return list results', async () => { + const storageReference = firebase.storage().ref('/list'); + const result = await storageReference.list(); + + result.constructor.name.should.eql('StorageListResult'); + result.should.have.property('nextPageToken'); + + result.items.should.be.Array(); + result.items.length.should.be.greaterThan(0); + result.items[0].constructor.name.should.eql('StorageReference'); + + result.prefixes.should.be.Array(); + result.prefixes.length.should.be.greaterThan(0); + result.prefixes[0].constructor.name.should.eql('StorageReference'); + }); + + it('throws if options is not an object', () => { + try { + const storageReference = firebase.storage().ref('/'); + storageReference.list(123); + return Promise.reject(new Error('Did not throw')); + } catch (error) { + error.message.should.containEql("'options' expected an object value"); + return Promise.resolve(); + } + }); + + describe('maxResults', () => { + it('should limit with maxResults are passed', async () => { + const storageReference = firebase.storage().ref('/list'); + const result = await storageReference.list({ + maxResults: 1, + }); + + result.nextPageToken.should.be.String(); + + result.items.should.be.Array(); + result.items.length.should.eql(1); + result.items[0].constructor.name.should.eql('StorageReference'); + + result.prefixes.should.be.Array(); + // todo length? + }); + + it('throws if maxResults is not a number', () => { + try { + const storageReference = firebase.storage().ref('/list'); + storageReference.list({ + maxResults: '123', + }); + return Promise.reject(new Error('Did not throw')); + } catch (error) { + error.message.should.containEql("'options.maxResults' expected a number value"); + return Promise.resolve(); + } + }); + + it('throws if maxResults is not a valid number', () => { + try { + const storageReference = firebase.storage().ref('/list'); + storageReference.list({ + maxResults: 2000, + }); + return Promise.reject(new Error('Did not throw')); + } catch (error) { + error.message.should.containEql( + "'options.maxResults' expected a number value between 1-1000", + ); + return Promise.resolve(); + } + }); + }); + + describe('pageToken', () => { + it('throws if pageToken is not a string', () => { + try { + const storageReference = firebase.storage().ref('/list'); + storageReference.list({ + pageToken: 123, + }); + return Promise.reject(new Error('Did not throw')); + } catch (error) { + error.message.should.containEql("'options.pageToken' expected a string value"); + return Promise.resolve(); + } + }); + + it('should return and use a page token', async () => { + const storageReference = firebase.storage().ref('/list'); + const result1 = await storageReference.list({ + maxResults: 1, + }); + + const item1 = result1.items[0].fullPath; + + const result2 = await storageReference.list({ + maxResults: 1, + pageToken: result1.nextPageToken, + }); + + const item2 = result2.items[0].fullPath; + + if (item1 === item2) { + throw new Error('Expected item results to be different.'); + } + }); + }); + }); + + describe('listAll', () => { + it('should return all results', async () => { + const storageReference = firebase.storage().ref('/list'); + const result = await storageReference.listAll(); + + should.equal(result.nextPageToken, null); + + result.items.should.be.Array(); + result.items.length.should.be.greaterThan(0); + result.items[0].constructor.name.should.eql('StorageReference'); + + result.prefixes.should.be.Array(); + result.prefixes.length.should.be.greaterThan(0); + result.prefixes[0].constructor.name.should.eql('StorageReference'); + }); + }); + describe('updateMetadata', () => { it('should return the updated metadata for a file', async () => { const storageReference = firebase.storage().ref('/writeOnly.jpeg'); diff --git a/packages/storage/ios/RNFBStorage/RNFBStorageCommon.h b/packages/storage/ios/RNFBStorage/RNFBStorageCommon.h index 1c38a4a3..83fcbd8a 100644 --- a/packages/storage/ios/RNFBStorage/RNFBStorageCommon.h +++ b/packages/storage/ios/RNFBStorage/RNFBStorageCommon.h @@ -25,6 +25,8 @@ + (NSDictionary *)metadataToDict:(FIRStorageMetadata *)metadata; ++ (NSDictionary *)listResultToDict:(FIRStorageListResult *)listResult; + + (PHAsset *)fetchAssetForPath:(NSString *)localFilePath; + (NSString *)utiToMimeType:(NSString *)dataUTI; diff --git a/packages/storage/ios/RNFBStorage/RNFBStorageCommon.m b/packages/storage/ios/RNFBStorage/RNFBStorageCommon.m index 25f98202..4240d097 100644 --- a/packages/storage/ios/RNFBStorage/RNFBStorageCommon.m +++ b/packages/storage/ios/RNFBStorage/RNFBStorageCommon.m @@ -299,6 +299,25 @@ return storageMetadata; } ++ (NSDictionary *)listResultToDict:(FIRStorageListResult *)listResult { + NSMutableArray *items = [[NSMutableArray alloc]init]; + NSMutableArray *prefixes = [[NSMutableArray alloc]init]; + + for (FIRStorageReference *ref in listResult.items) { + [items addObject:[ref fullPath]]; + } + + for (FIRStorageReference *ref in listResult.prefixes) { + [prefixes addObject:[ref fullPath]]; + } + + return @{ + @"nextPageToken": [listResult pageToken] != nil ? (id) [listResult pageToken] : [NSNull null], + @"items": items, + @"prefixes": prefixes, + }; +} + + (NSMutableDictionary *)getUploadTaskAsDictionary:(FIRStorageTaskSnapshot *)task { if (task == nil) { return [@{ diff --git a/packages/storage/ios/RNFBStorage/RNFBStorageModule.m b/packages/storage/ios/RNFBStorage/RNFBStorageModule.m index c23a5949..51528cc9 100644 --- a/packages/storage/ios/RNFBStorage/RNFBStorageModule.m +++ b/packages/storage/ios/RNFBStorage/RNFBStorageModule.m @@ -153,6 +153,59 @@ RCT_EXPORT_METHOD(updateMetadata: }]; } +/** + * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#list + */ +RCT_EXPORT_METHOD(list: + (FIRApp *) firebaseApp + : (NSString *) url + : (NSDictionary *) listOptions + : (RCTPromiseResolveBlock) resolve + : (RCTPromiseRejectBlock) reject +) { + FIRStorageReference *storageReference = [self getReferenceFromUrl:url app:firebaseApp]; + long *maxResults = [listOptions[@"maxResults"] pointerValue]; + + id completionBlock = ^(FIRStorageListResult *result, NSError *error) { + if (error != nil) { + [self promiseRejectStorageException:reject error:error]; + } else { + NSDictionary * dick = [RNFBStorageCommon listResultToDict:result]; + // so we can see the result + resolve(dick); + } + }; + + if (listOptions[@"pageToken"]) { + NSString *pageToken = listOptions[@"pageToken"]; + [storageReference listWithMaxResults:(int64_t) maxResults pageToken:pageToken completion:completionBlock]; + } else { + [storageReference listWithMaxResults:(int64_t) maxResults completion:completionBlock]; + } +} + +/** + * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#listAll + */ +RCT_EXPORT_METHOD(listAll: + (FIRApp *) firebaseApp + : (NSString *) url + : (RCTPromiseResolveBlock) resolve + : (RCTPromiseRejectBlock) reject +) { + FIRStorageReference *storageReference = [self getReferenceFromUrl:url app:firebaseApp]; + + id completionBlock = ^(FIRStorageListResult *result, NSError *error) { + if (error != nil) { + [self promiseRejectStorageException:reject error:error]; + } else { + resolve([RNFBStorageCommon listResultToDict:result]); + } + }; + + [storageReference listAllWithCompletion:completionBlock]; +} + /** * @url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxDownloadRetryTime */ diff --git a/packages/storage/lib/StorageListResult.js b/packages/storage/lib/StorageListResult.js new file mode 100644 index 00000000..ab1c383d --- /dev/null +++ b/packages/storage/lib/StorageListResult.js @@ -0,0 +1,43 @@ +/* eslint-disable no-console */ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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. + * + */ + +// To avoid React Native require cycle warnings +let StorageReference = null; +export function provideStorageReferenceClass(storageReference) { + StorageReference = storageReference; +} + +export default class StorageListResult { + constructor(storage, nativeData) { + this._nextPageToken = nativeData.nextPageToken || null; + this._items = nativeData.items.map(path => new StorageReference(storage, path)); + this._prefixes = nativeData.prefixes.map(path => new StorageReference(storage, path)); + } + + get items() { + return this._items; + } + + get nextPageToken() { + return this._nextPageToken; + } + + get prefixes() { + return this._prefixes; + } +} diff --git a/packages/storage/lib/StorageReference.js b/packages/storage/lib/StorageReference.js index 029d72c2..3d537b44 100644 --- a/packages/storage/lib/StorageReference.js +++ b/packages/storage/lib/StorageReference.js @@ -25,11 +25,15 @@ import { getDataUrlParts, pathLastComponent, ReferenceBase, + isObject, + hasOwnProperty, + isNumber, } from '@react-native-firebase/common'; import { validateMetadata } from './utils'; import StorageStatics from './StorageStatics'; import StorageUploadTask from './StorageUploadTask'; import StorageDownloadTask from './StorageDownloadTask'; +import StorageListResult, { provideStorageReferenceClass } from './StorageListResult'; export default class StorageReference extends ReferenceBase { constructor(storage, path) { @@ -112,6 +116,64 @@ export default class StorageReference extends ReferenceBase { return this._storage.native.getMetadata(this.toString()); } + /** + * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#list + */ + list(options) { + if (!isUndefined(options) && !isObject(options)) { + throw new Error( + "firebase.storage.StorageReference.list(*) 'options' expected an object value.", + ); + } + + const listOptions = { + maxResults: 1000, + }; + + if (options) { + if (hasOwnProperty(options, 'maxResults')) { + if (!isNumber(options.maxResults)) { + throw new Error( + "firebase.storage.StorageReference.list(*) 'options.maxResults' expected a number value.", + ); + } + + // todo integer check + + if (options.maxResults < 1 || options.maxResults > 1000) { + throw new Error( + "firebase.storage.StorageReference.list(*) 'options.maxResults' expected a number value between 1-1000.", + ); + } + + listOptions.maxResults = options.maxResults; + } + + if (options.pageToken) { + if (!isString(options.pageToken)) { + throw new Error( + "firebase.storage.StorageReference.list(*) 'options.pageToken' expected a string value.", + ); + } + + listOptions.pageToken = options.pageToken; + } + } + + return this._storage.native + .list(this.toString(), listOptions) + .then(data => new StorageListResult(this._storage, data)); + } + + /** + * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#listAll + */ + listAll() { + return this._storage.native + .listAll(this.toString()) + .then(data => new StorageListResult(this._storage, data)); + } + /** * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#put */ @@ -182,7 +244,7 @@ export default class StorageReference extends ReferenceBase { */ toString() { if (this.path.length <= 1) { - return this._storage._customUrlOrRegion; + return `${this._storage._customUrlOrRegion}`; } return `${this._storage._customUrlOrRegion}/${this.path}`; @@ -244,3 +306,5 @@ export default class StorageReference extends ReferenceBase { ); } } + +provideStorageReferenceClass(StorageReference); diff --git a/packages/storage/lib/index.d.ts b/packages/storage/lib/index.d.ts index afc94ee8..72df9859 100644 --- a/packages/storage/lib/index.d.ts +++ b/packages/storage/lib/index.d.ts @@ -531,6 +531,49 @@ export namespace Storage { */ getMetadata(): Promise; + /** + * 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. + * + * #### Example + * + * ```js + * const ref = firebase.storage().ref('/'); + * const results = await ref.list({ + * maxResults: 30, + * }); + * ``` + * + * @param options An optional ListOptions interface. + */ + list(options?: ListOptions): Promise; + + /** + * 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. + * + * #### Example + * + * ```js + * const ref = firebase.storage().ref('/'); + * const results = await ref.listAll(); + * ``` + */ + listAll(): Promise; + /** * Puts a file from local disk onto the storage bucket. * @@ -870,6 +913,43 @@ export namespace Storage { error?: NativeFirebaseError; } + /** + * The options `list()` accepts. + */ + export interface ListOptions { + /** + * If set, limits the total number of `prefixes` and `items` to return. The default and maximum maxResults is 1000. + */ + maxResults?: number; + + /** + * The `nextPageToken` from a previous call to `list()`. If provided, listing is resumed from the previous position. + */ + pageToken?: string; + } + + /** + * Result returned by `list()`. + */ + export interface ListResult { + /** + * Objects in this directory. You can call `getMetadate()` and `getDownloadUrl()` on them. + */ + items: Reference[]; + + /** + * If set, there might be more results for this list. Use this token to resume the list. + */ + nextPageToken: string | null; + + /** + * References to prefixes (sub-folders). You can call `list()` on them to get its contents. + * + * Folders are implicit based on '/' in the object paths. For example, if a bucket has two objects '/a/b/1' and '/a/b/2', list('/a') will return '/a/b' as a prefix. + */ + prefixes: Reference[]; + } + /** * The Cloud Storage service is available for the default app, a given app or a specific storage bucket. * diff --git a/packages/storage/lib/index.js.flow b/packages/storage/lib/index.js.flow index 49495735..fe1e0401 100644 --- a/packages/storage/lib/index.js.flow +++ b/packages/storage/lib/index.js.flow @@ -507,36 +507,286 @@ export interface FullMetadata extends SettableMetadata { updated: string; } -// TODO(salakar) -----\/ +/** + * The options `list()` accepts. + */ +export interface ListOptions { + /** + * If set, limits the total number of `prefixes` and `items` to return. The default and maximum maxResults is 1000. + */ + maxResults?: number; + + /** + * The `nextPageToken` from a previous call to `list()`. If provided, listing is resumed from the previous position. + */ + pageToken?: string; +} + +/** + * Result returned by `list()`. + */ +export interface ListResult { + /** + * Objects in this directory. You can call `getMetadate()` and `getDownloadUrl()` on them. + */ + items: Reference[]; + + /** + * If set, there might be more results for this list. Use this token to resume the list. + */ + nextPageToken: string | null; + + /** + * References to prefixes (sub-folders). You can call `list()` on them to get its contents. + * + * Folders are implicit based on '/' in the object paths. For example, if a bucket has two objects '/a/b/1' and '/a/b/2', list('/a') will return '/a/b' as a prefix. + */ + prefixes: Reference[]; +} + +/** + * Represents a reference to a Google Cloud Storage object in React Native Firebase. + * + * A reference can be used to upload and download storage objects, get/set storage object metadata, retrieve storage object download urls and delete storage objects. + * + * #### Example 1 + * + * Get a reference to a specific storage path. + * + * ```js + * const ref = firebase.storage().ref('invertase/logo.png'); + * ``` + * + * #### Example 2 + * + * Get a reference to a specific storage path on another bucket in the same firebase project. + * + * ```js + * const ref = firebase.storage().refFromURL('gs://other-bucket/invertase/logo.png'); + * ``` + */ export interface Reference { + /** + * The name of the bucket containing this reference's object. + */ bucket: string; - + /** + * A reference pointing to the parent location of this reference, or null if this reference is the root. + */ parent: Reference | null; - + /** + * The full path of this object. + */ fullPath: string; - + /** + * The short name of this object, which is the last component of the full path. For example, + * if fullPath is 'full/path/image.png', name is 'image.png'. + */ name: string; - + /** + * A reference to the root of this reference's bucket. + */ root: Reference; - + /** + * The storage service associated with this reference. + */ storage: Module; + /** + * Returns a gs:// URL for this object in the form `gs://///`. + * + * #### Example + * + * ```js + * const ref = firebase.storage().ref('invertase/logo.png'); + * console.log('Full path: ', ref.toString()); // gs://invertase.io/invertase/logo.png + * ``` + */ toString(): string; + /** + * Returns a reference to a relative path from this reference. + * + * #### Example + * + * ```js + * const parent = firebase.storage().ref('invertase'); + * const ref = parent.child('logo.png'); + * ``` + * + * @param path The relative path from this reference. Leading, trailing, and consecutive slashes are removed. + */ child(path: string): Reference; + /** + * Deletes the object at this reference's location. + * + * #### Example + * + * ```js + * const ref = firebase.storage().ref('invertase/logo.png'); + * await ref.delete(); + * ``` + */ delete(): Promise; + /** + * Fetches a long lived download URL for this object. + * + * #### Example + * + * ```js + * const ref = firebase.storage().ref('invertase/logo.png'); + * const url = await ref.getDownloadURL(); + * ``` + */ getDownloadURL(): Promise; + /** + * Fetches metadata for the object at this location, if one exists. + * + * #### Example + * + * ```js + * const ref = firebase.storage().ref('invertase/logo.png'); + * const metadata = await ref.getMetadata(); + * console.log('Cache control: ', metadata.cacheControl); + * ``` + */ getMetadata(): Promise; + /** + * 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. + * + * #### Example + * + * ```js + * const ref = firebase.storage().ref('/'); + * const results = await ref.list({ + * maxResults: 30, + * }); + * ``` + * + * @param options An optional ListOptions interface. + */ + list(options?: ListOptions): Promise; + + /** + * 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. + * + * #### Example + * + * ```js + * const ref = firebase.storage().ref('/'); + * const results = await ref.listAll(); + * ``` + */ + listAll(): Promise; + + /** + * Puts a file from local disk onto the storage bucket. + * + * #### Example + * + * ```js + * const ref = firebase.storage().ref('invertase/new-logo.png'); + * const path = `${firebase.utils.FilePath.DOCUMENT_DIRECTORY}/new-logo.png`; + * const task = ref.putFile(path, { + * cacheControl: 'no-store', // disable caching + * }); + * ``` + * + * @param localFilePath The local file path to upload to the bucket at the reference location. + * @param metadata Any additional `SettableMetadata` for this task. + */ putFile(localFilePath: string, metadata?: SettableMetadata): Task; + /** + * Downloads a file to the specified local file path on the device. + * + * #### Example + * + * Get a Download Storage task to download a file: + * + * ```js + * const downloadTo = `${firebase.utils.FilePath.DOCUMENT_DIRECTORY}/foobar.json`; + * + * const task = firebase.storage().ref('/foo/bar.json').writeToFile(downloadTo); + * ``` + * @param localFilePath + */ + writeToFile(localFilePath: string): Task; + + /** + * Puts data onto the storage bucket. + * + * #### Example + * + * ```js + * const ref = firebase.storage().ref('invertase/new-logo.png'); + * const task = ref.put(BLOB, { + * cacheControl: 'no-store', // disable caching + * }); + * ``` + * + * @param data The data to upload to the storage bucket at the reference location. + * @param metadata + */ put(data: Blob | Uint8Array | ArrayBuffer, metadata?: SettableMetadata): Task; - putString(data: string, format?: StringFormat, metadata?: SettableMetadata): Task; + /** + * Puts a string on the storage bucket. Depending on the string type, set a {@link storage.StringFormat} type. + * + * #### Example + * + * ```js + * const ref = firebase.storage().ref('invertase/new-logo.png'); + * const task = ref.putString('PEZvbyBCYXI+', firebase.storage.StringFormat.BASE64, { + * cacheControl: 'no-store', // disable caching + * }); + * ``` + * + * @param data The string data, must match the format provided. + * @param format The format type of the string, e.g. a Base64 format string. + * @param metadata Any additional `SettableMetadata` for this task. + */ + putString( + data: string, + format?: 'raw' | 'base64' | 'base64url' | 'data_url', + metadata?: SettableMetadata, + ): Task; + /** + * Updates the metadata for this reference object on the storage bucket. + * + * #### Example + * + * ```js + * const ref = firebase.storage().ref('invertase/nsfw-logo.png'); + * const updatedMetadata = await ref.updateMetadata({ + * customMetadata: { + * 'nsfw': 'true', + * } + * }); + * ``` + * + * @param metadata A `SettableMetadata` instance to update. + */ updateMetadata(metadata: SettableMetadata): Promise; } diff --git a/tests/e2e/init.js b/tests/e2e/init.js index e6c074b9..ffdd1f40 100755 --- a/tests/e2e/init.js +++ b/tests/e2e/init.js @@ -46,7 +46,7 @@ const PACKAGES = [ 'utils', 'ml-natural-language', 'ml-vision', - // 'invites', + 'invites', 'fiam', 'auth', 'database', diff --git a/tests/ios/Podfile.lock b/tests/ios/Podfile.lock index bd3ec073..ef731d58 100644 --- a/tests/ios/Podfile.lock +++ b/tests/ios/Podfile.lock @@ -312,62 +312,62 @@ PODS: - React-RCTWebSocket (0.60.4): - React-Core (= 0.60.4) - React-fishhook (= 0.60.4) - - RNFBAnalytics (0.0.26): + - RNFBAnalytics (0.1.0): - Firebase/Core (~> 6.5.0) - React - RNFBApp - - RNFBApp (0.0.26): + - RNFBApp (0.1.0): - Firebase/Core (~> 6.5.0) - React - - RNFBAuth (0.0.26): + - RNFBAuth (0.1.0): - Firebase/Auth (~> 6.5.0) - Firebase/Core (~> 6.5.0) - React - RNFBApp - - RNFBConfig (0.0.26): + - RNFBConfig (0.1.0): - Firebase/Core (~> 6.5.0) - Firebase/RemoteConfig (~> 6.5.0) - React - RNFBApp - - RNFBCrashlytics (0.0.26): + - RNFBCrashlytics (0.1.0): - Crashlytics (~> 3.12.0) - Fabric (~> 1.9.0) - Firebase/Core (~> 6.5.0) - React - RNFBApp - - RNFBDatabase (0.0.26): + - RNFBDatabase (0.1.0): - Firebase/Core (~> 6.5.0) - Firebase/Database (~> 6.5.0) - React - RNFBApp - - RNFBDynamicLinks (0.0.26): + - RNFBDynamicLinks (0.1.0): - Firebase/Core (~> 6.5.0) - Firebase/DynamicLinks (~> 6.5.0) - React - RNFBApp - - RNFBFiam (0.0.26): + - RNFBFiam (0.1.0): - Firebase/Core (~> 6.5.0) - Firebase/InAppMessagingDisplay (~> 6.5.0) - React - RNFBApp - - RNFBFirestore (0.0.26): + - RNFBFirestore (0.1.0): - Firebase/Core (~> 6.5.0) - Firebase/Firestore (~> 6.5.0) - React - RNFBApp - - RNFBFunctions (0.0.26): + - RNFBFunctions (0.1.0): - Firebase/Functions (~> 6.5.0) - React - RNFBApp - - RNFBIid (0.0.26): + - RNFBIid (0.1.0): - Firebase/Core (~> 6.5.0) - React - RNFBApp - - RNFBMessaging (0.0.26): + - RNFBMessaging (0.1.0): - Firebase/Messaging (~> 6.5.0) - React - RNFBApp - - RNFBMlNaturalLanguage (0.0.26): + - RNFBMlNaturalLanguage (0.1.0): - Firebase/Core (~> 6.5.0) - Firebase/MLCommon (~> 6.5.0) - Firebase/MLNaturalLanguage (~> 6.5.0) @@ -375,17 +375,17 @@ PODS: - Firebase/MLNLSmartReply (~> 6.5.0) - React - RNFBApp - - RNFBPerf (0.0.26): + - RNFBPerf (0.1.0): - Firebase/Core (~> 6.5.0) - Firebase/Performance (~> 6.5.0) - React - RNFBApp - - RNFBStorage (0.0.26): + - RNFBStorage (0.1.0): - Firebase/Core (~> 6.5.0) - Firebase/Storage (~> 6.5.0) - React - RNFBApp - - RNFBUtils (0.0.26): + - RNFBUtils (0.1.0): - Firebase/Core (~> 6.5.0) - React - RNFBApp @@ -608,22 +608,22 @@ SPEC CHECKSUMS: React-RCTText: e0f224898b13af9aa036ea7cb3d438daa68c1044 React-RCTVibration: 0bea40cd51bd089bd591a8f74c86e91fdf2666c5 React-RCTWebSocket: 163873f4cdd5f1058a9483443404fc3801581cb6 - RNFBAnalytics: 71420d837ca8540a46cb2a864923ffd270be7d1d - RNFBApp: 6e1a89e541d640780af502473f3478113f3fcef0 - RNFBAuth: 19478f2c21bb3088dedc46c66a60288d905ba3e0 - RNFBConfig: 9a6e827781f8030dd0b9a9dd9a08551dafee4ff7 - RNFBCrashlytics: 759d6774287ed596e248b0a288eaa495c52dbec7 - RNFBDatabase: be81d1e368b2b748965fcf474a4a7f7e6e74df8d - RNFBDynamicLinks: c093448437b3e5dd50fde383af69a84225924c58 - RNFBFiam: f500776891ab53a2380766a8dda331484989962b - RNFBFirestore: 10af675d54d88fd44bf6c6666d1e5d806ba72bcd - RNFBFunctions: 38ae5a1fb23af6ebacb5ab62d2d0004cb0e4a580 - RNFBIid: 179e4d9b85cd267ec841d00f532bd16693d6fa75 - RNFBMessaging: e8cd71ce0d54c378038a24cee3122e35ea596bec - RNFBMlNaturalLanguage: e61654420ab0020fd72f0144878d3a40e5ce2907 - RNFBPerf: ed8f26e1ad933ab9e4b0657dd7f1d5a0025dd59f - RNFBStorage: f7fc03c0be9e6d8d3b4bc7a25be81841118bfa18 - RNFBUtils: 9e8b7925e0a235ba08a81e1f3c877b3f2cb06723 + RNFBAnalytics: 69a5aa7ab165b09e2c032b4240eda4df4162a6af + RNFBApp: 1517b1e22b8933c87d5d7eb232486b68afdcb308 + RNFBAuth: b844d8e2e89b04b30ecae8dff2e2decc68ad488e + RNFBConfig: 28528ef2531045b081fe3166d51a69182389bb27 + RNFBCrashlytics: 207f072a151242027ccc20549ac616a52bf25ef5 + RNFBDatabase: cab5cef18b05d5ec4d190d68ddab0d495c254995 + RNFBDynamicLinks: dbb1d425136f6cd6a3e4029662841be373e931f3 + RNFBFiam: 083a9ed7b8cf5c3b2d0022f129a3bcd05edd9a58 + RNFBFirestore: 6f4ab90c880906aaa0b2cc63d9fe0ce28cb1d3cd + RNFBFunctions: ca2cfc68ed63d0621c8ef46def3d93972120c293 + RNFBIid: a068c7f9692b4c68ce3ff5d7b3c0cbb9c430eb94 + RNFBMessaging: eda58ceb6650043d65ab28eccb1ca272291d0fcd + RNFBMlNaturalLanguage: bdc99e787ad3183d6a19e7222503d707e28eb4f6 + RNFBPerf: bfb1f25cc79452b99272c9382b41cec20e9c058c + RNFBStorage: 195d5dd4ebc11f8d2e436f5d0eff2360285b8d31 + RNFBUtils: 400e5a6c825ae8720bedb2fd876d3d02a4d51adc yoga: c2c050f6ae6e222534760cc82f559b89214b67e2 PODFILE CHECKSUM: 0142c48fc8ad8e230e216fc15af267405c520250