diff --git a/android/src/main/java/io/fullstack/firestack/FirestackStorage.java b/android/src/main/java/io/fullstack/firestack/FirestackStorage.java index 21ed217..882e312 100644 --- a/android/src/main/java/io/fullstack/firestack/FirestackStorage.java +++ b/android/src/main/java/io/fullstack/firestack/FirestackStorage.java @@ -113,16 +113,10 @@ public void downloadFile(final String urlStr, @Override public void doInBackground(StreamDownloadTask.TaskSnapshot taskSnapshot, InputStream inputStream) throws IOException { int indexOfLastSlash = localFile.lastIndexOf("/"); - String pathMinusFileName = localFile.substring(0, indexOfLastSlash) + "/"; - String filename = localFile.substring(indexOfLastSlash+1); + String pathMinusFileName = indexOfLastSlash>0 ? localFile.substring(0, indexOfLastSlash) + "/" : "/"; + String filename = indexOfLastSlash>0 ? localFile.substring(indexOfLastSlash+1) : localFile; File fileWithJustPath = new File(pathMinusFileName); - if (!fileWithJustPath.mkdirs()) { - Log.e(TAG, "Directory not created"); - WritableMap error = Arguments.createMap(); - error.putString("message", "Directory not created"); - callback.invoke(error); - return; - } + fileWithJustPath.mkdirs(); File fileWithFullPath = new File(pathMinusFileName, filename); FileOutputStream output = new FileOutputStream(fileWithFullPath); int bufferSize = 1024; diff --git a/android/src/main/java/io/fullstack/firestack/FirestackUtils.java b/android/src/main/java/io/fullstack/firestack/FirestackUtils.java index 669e337..1625e6c 100644 --- a/android/src/main/java/io/fullstack/firestack/FirestackUtils.java +++ b/android/src/main/java/io/fullstack/firestack/FirestackUtils.java @@ -40,7 +40,7 @@ public static void todoNote(final String tag, final String name, final Callback public static void sendEvent(final ReactContext context, final String eventName, final WritableMap params) { - if (context.hasActiveCatalystInstance()) { + if (context != null && context.hasActiveCatalystInstance()) { context .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) .emit(eventName, params); diff --git a/firestack.android.js b/firestack.android.js index 15d7185..3ebc35e 100644 --- a/firestack.android.js +++ b/firestack.android.js @@ -1,7 +1,6 @@ /** - * @providesModule Firestack * @flow */ import Firestack from './lib/firestack' -export default Firestack \ No newline at end of file +export default Firestack diff --git a/firestack.ios.js b/firestack.ios.js index bc1e69b..3ebc35e 100644 --- a/firestack.ios.js +++ b/firestack.ios.js @@ -1,5 +1,4 @@ /** - * @providesModule Firestack * @flow */ import Firestack from './lib/firestack' diff --git a/lib/firestack.js b/lib/firestack.js index 1bf9153..2961ed0 100644 --- a/lib/firestack.js +++ b/lib/firestack.js @@ -34,7 +34,7 @@ export default class Firestack extends Singleton { * @param options * @param name - TODO support naming multiple instances */ - constructor(options: Object, name: string) { + constructor(options: Object, name?: string) { const instance = super(options); instance.options = options || {}; @@ -192,7 +192,7 @@ export default class Firestack extends Singleton { /** * Redux store **/ - get store(): Object { + get store(): ?Object { return this._store; } diff --git a/lib/modules/auth.js b/lib/modules/auth.js index 04e5775..e871c97 100644 --- a/lib/modules/auth.js +++ b/lib/modules/auth.js @@ -138,7 +138,7 @@ export default class Auth extends Base { * Sign the user in with a third-party authentication provider * @return {Promise} A promise resolved upon completion */ - signInWithCredential(credential): Promise { + signInWithCredential(credential: Object): Promise { return promisify('signInWithProvider', FirestackAuth)(credential.provider, credential.token, credential.secret); } @@ -146,7 +146,7 @@ export default class Auth extends Base { * Re-authenticate a user with a third-party authentication provider * @return {Promise} A promise resolved upon completion */ - reauthenticateUser(credential): Promise { + reauthenticateUser(credential: Object): Promise { return promisify('reauthenticateWithCredentialForProvider', FirestackAuth)(credential.provider, credential.token, credential.secret); } diff --git a/lib/modules/base.js b/lib/modules/base.js index 7aee499..443eafa 100644 --- a/lib/modules/base.js +++ b/lib/modules/base.js @@ -11,8 +11,9 @@ const FirestackModuleEvt = new NativeEventEmitter(FirestackModule); const logs = {}; +type FirestackOptions = {}; export class Base extends EventEmitter { - constructor(firestack, options = {}) { + constructor(firestack: Object, options: FirestackOptions = {}) { super(); this.firestack = firestack; this.eventHandlers = {}; @@ -22,7 +23,7 @@ export class Base extends EventEmitter { } // Logger - get log() { + get log(): Log { if (!logs[this.namespace]) { const debug = this.firestack._debug; logs[this.namespace] = new Log(this.namespace, debug); @@ -38,7 +39,7 @@ export class Base extends EventEmitter { } // TODO unused - do we need this anymore? - _addToFirestackInstance(...methods) { + _addToFirestackInstance(...methods: Array) { methods.forEach(name => { this.firestack[name] = this[name].bind(this); }) @@ -47,15 +48,17 @@ export class Base extends EventEmitter { /** * app instance **/ - get app() { + get app(): Object { return this.firestack.app; } - whenReady(fn) { - return this.firestack.configurePromise.then(fn); + whenReady(promise: Promise<*>): Promise<*> { + return this.firestack.configurePromise.then((result) => { + return promise; + }); } - get namespace() { + get namespace(): string { return 'firestack:base'; } @@ -88,25 +91,21 @@ export class Base extends EventEmitter { } export class ReferenceBase extends Base { - constructor(firestack, path) { + constructor(firestack: Object, path: Array | string) { super(firestack); - this.path = Array.isArray(path) ? - path : - (typeof path == 'string' ? - [path] : []); + this.path = Array.isArray(path) ? path : (typeof path == 'string' ? [path] : []); // sanitize path, just in case - this.path = this.path - .filter(str => str !== ""); + this.path = this.path.filter(str => str !== ''); } - get key() { + get key(): string { const path = this.path; return path.length === 0 ? '/' : path[path.length - 1]; } - pathToString() { + pathToString(): string { let path = this.path; let pathStr = (path.length > 0 ? path.join('/') : '/'); if (pathStr[0] != '/') { diff --git a/lib/modules/storage.js b/lib/modules/storage.js index c5fc6c2..e734703 100644 --- a/lib/modules/storage.js +++ b/lib/modules/storage.js @@ -1,3 +1,4 @@ +/* @flow */ import {NativeModules, NativeEventEmitter} from 'react-native'; const FirestackStorage = NativeModules.FirestackStorage; @@ -13,9 +14,14 @@ class StorageRef extends ReferenceBase { this.storage = storage; } - downloadUrl() { + downloadUrl(): Promise { const path = this.pathToString(); - return promisify('downloadUrl', FirestackStorage)(this.storage.storageUrl, path); + this.log.debug('downloadUrl(', path, ')'); + return promisify('downloadUrl', FirestackStorage)(this.storage.storageUrl, path) + .catch(err => { + this.log.error('Error downloading URL for ', path, '. Error: ', err); + throw err; + }); } /** @@ -23,7 +29,7 @@ class StorageRef extends ReferenceBase { * @param {String} downloadPath Where to store the file * @return {Promise} */ - download (downloadPath, cb) { + download (downloadPath: string, cb: (evt: Object) => Object): Promise { let callback = cb; if (!callback || typeof callback !== 'function') { callback = (evt) => {}; @@ -35,20 +41,25 @@ class StorageRef extends ReferenceBase { listeners.push(this.storage._addListener('download_resumed', callback)); const path = this.pathToString(); + this.log.debug('download(', path, ') -> ', downloadPath); return promisify('downloadFile', FirestackStorage)(this.storage.storageUrl, path, downloadPath) .then((res) => { - console.log('res --->', res); - listeners.forEach(this.storage._removeListener); + this.log.debug('res --->', res); + listeners.forEach(listener => listener.remove()); return res; }) .catch(err => { - console.log('Got an error ->', err); - }) + this.log.error('Error downloading ', path, ' to ', downloadPath, '. Error: ', err); + throw err; + }); } } +type StorageOptionsType = { + storageBucket?: ?string, +}; export default class Storage extends Base { - constructor(firestack, options={}) { + constructor(firestack: Object, options:StorageOptionsType={}) { super(firestack, options); if (this.options.storageBucket) { @@ -58,8 +69,8 @@ export default class Storage extends Base { this.refs = {}; } - ref(...path) { - const key = this._pathKey(path); + ref(...path: Array): StorageRef { + const key = this._pathKey(...path); if (!this.refs[key]) { const ref = new StorageRef(this, path); this.refs[key] = ref; @@ -74,13 +85,14 @@ export default class Storage extends Base { * @param {object} metadata An object containing metadata * @return {Promise} */ - uploadFile(name, filepath, metadata={}, cb) { + uploadFile(name: string, filepath: string, metadata: Object={}, cb: (evt: Object) => Object): Promise { + this.log.debug('uploadFile(', filepath, ') -> ', name); let callback = cb; if (!callback || typeof callback !== 'function') { - callback = (evt) => {} + callback = (evt: Object) => ({}); } - filepath = filepath.replace("file://", ""); + filepath = filepath.replace('file://', ''); const listeners = []; listeners.push(this._addListener('upload_progress', callback)); @@ -88,29 +100,30 @@ export default class Storage extends Base { listeners.push(this._addListener('upload_resumed', callback)); return promisify('uploadFile', FirestackStorage)(this.storageUrl, name, filepath, metadata) .then((res) => { - listeners.forEach(this._removeListener); + listeners.forEach(listener => listener.remove()); return res; + }) + .catch(err => { + this.log.error('Error uploading file ', name, ' to ', filepath, '. Error: ', err); + throw err; }); } - getRealPathFromURI(uri) { + getRealPathFromURI(uri: string): Promise { return promisify('getRealPathFromURI', FirestackStorage)(uri); } - _addListener(evt, cb) { - return FirestackStorageEvt.addListener(evt, cb); - } - - _removeListener(evt) { - return FirestackStorageEvt.removeListener(evt); + _addListener(evt: string, cb: (evt: Object) => Object): {remove: () => void} { + let listener = FirestackStorageEvt.addListener(evt, cb); + return listener; } - setStorageUrl(url) { + setStorageUrl(url: string): void { // return promisify('setStorageUrl', FirestackStorage)(url); this.storageUrl = `gs://${url}`; } - _pathKey(...path) { + _pathKey(...path: Array): string { return path.join('-'); } @@ -126,7 +139,7 @@ export default class Storage extends Base { 'FILETYPE_DIRECTORY': FirestackStorage.FILETYPE_DIRECTORY }; - get namespace() { + get namespace(): string { return 'firestack:storage' } } diff --git a/lib/utils/window-or-global.js b/lib/utils/window-or-global.js index 7b64020..c19a003 100644 --- a/lib/utils/window-or-global.js +++ b/lib/utils/window-or-global.js @@ -2,4 +2,4 @@ // https://github.com/purposeindustries/window-or-global module.exports = (typeof self === 'object' && self.self === self && self) || (typeof global === 'object' && global.global === global && global) || - {} \ No newline at end of file + this