From 0c550f3586293af2ffcab46ad61fd8a6e9dbed7f Mon Sep 17 00:00:00 2001 From: Elton Gao Date: Thu, 9 Nov 2017 10:34:52 -0500 Subject: [PATCH 01/56] Make sure the promise is resolved/rejected for transaction Right now the following code will be broken: ``` async function() { await ref.transaction( function(foo) { // deal with foo }, function(error, committed, ss) { // additional work on complete callback }, true ); // NOTE: Code from here will never execute because promise above never gets resolved } ``` v2 is not returning at the point of calling onComplete, v3 code does --- lib/modules/database/reference.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/modules/database/reference.js b/lib/modules/database/reference.js index ffb1af9f..83f535ac 100644 --- a/lib/modules/database/reference.js +++ b/lib/modules/database/reference.js @@ -195,8 +195,11 @@ export default class Reference extends ReferenceBase { return new Promise((resolve, reject) => { const onCompleteWrapper = (error, committed, snapshotData) => { if (isFunction(onComplete)) { - if (error) return onComplete(error, committed, null); - return onComplete(null, committed, new Snapshot(this, snapshotData)); + if (error) { + onComplete(error, committed, null); + } else { + onComplete(null, committed, new Snapshot(this, snapshotData)); + } } if (error) return reject(error); From 5c43c88f6a4fe1055275a042a63cdee5ec6d5720 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Thu, 16 Nov 2017 16:54:42 +0000 Subject: [PATCH 02/56] [firestore][js] Correct flow type --- lib/modules/firestore/Query.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/modules/firestore/Query.js b/lib/modules/firestore/Query.js index 752296fc..aba8ac81 100644 --- a/lib/modules/firestore/Query.js +++ b/lib/modules/firestore/Query.js @@ -45,7 +45,7 @@ type QueryOptions = { } export type Operator = '<' | '<=' | '=' | '==' | '>' | '>='; type QueryListenOptions = { - includeQueryMetadataChanges: boolean, + includeDocumentMetadataChanges: boolean, includeQueryMetadataChanges: boolean, } From 8bd96846445ca2c99163ae066301d871df7536ab Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 17 Nov 2017 11:07:52 +0000 Subject: [PATCH 03/56] [types] Get flow type working again; Fix majority of firestore type issues --- .eslintrc | 8 +- .flowconfig | 4 +- lib/firebase-app.js | 41 +- lib/firebase.js | 35 +- lib/internals.js | 38 +- lib/modules/firestore/CollectionReference.js | 20 +- lib/modules/firestore/DocumentChange.js | 10 +- lib/modules/firestore/DocumentReference.js | 38 +- lib/modules/firestore/DocumentSnapshot.js | 14 +- lib/modules/firestore/GeoPoint.js | 6 +- lib/modules/firestore/Path.js | 2 +- lib/modules/firestore/Query.js | 113 +- lib/modules/firestore/QuerySnapshot.js | 25 +- lib/modules/firestore/WriteBatch.js | 12 +- lib/modules/firestore/index.js | 25 +- lib/modules/firestore/utils/serialize.js | 97 +- lib/utils/ModuleBase.js | 22 +- lib/utils/ReferenceBase.js | 12 +- lib/utils/SyncTree.js | 44 +- lib/utils/index.js | 42 +- package-lock.json | 3070 +++++++++++++---- package.json | 14 +- tests/ios/Podfile.lock | 2 +- .../project.pbxproj | 2 +- 24 files changed, 2743 insertions(+), 953 deletions(-) diff --git a/.eslintrc b/.eslintrc index 4c0be3c3..2c8b7e3b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -34,7 +34,13 @@ "import/extensions": 0, "import/no-unresolved": 0, "import/no-extraneous-dependencies": 0, - "react/jsx-filename-extension": 0 + "react/jsx-filename-extension": 0, + "no-unused-expressions": 0, + "flowtype/no-unused-expressions": ['error', { + allowShortCircuit: false, + allowTernary: false, + allowTaggedTemplates: false, + }] }, "globals": { "__DEV__": true, diff --git a/.flowconfig b/.flowconfig index 5a8ea5f8..fb97021d 100644 --- a/.flowconfig +++ b/.flowconfig @@ -91,7 +91,7 @@ unsafe.enable_getters_and_setters=true esproposal.class_static_fields=enable esproposal.class_instance_fields=enable -munge_underscores=true +munge_underscores=false module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' @@ -105,4 +105,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-4]\\|1[0-9]\\|[0-9 suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy [version] -^0.46.0 +^0.56.0 diff --git a/lib/firebase-app.js b/lib/firebase-app.js index ae1a254d..3fb2f09b 100644 --- a/lib/firebase-app.js +++ b/lib/firebase-app.js @@ -1,3 +1,6 @@ +/* + * @flow + */ import { NativeModules } from 'react-native'; import INTERNALS from './internals'; @@ -16,10 +19,31 @@ import Firestore, { statics as FirestoreStatics } from './modules/firestore'; import Links, { statics as LinksStatics } from './modules/links'; import Utils, { statics as UtilsStatics } from './modules/utils'; +import type { FirebaseOptions } from './firebase'; + const FirebaseCoreModule = NativeModules.RNFirebase; export default class FirebaseApp { - constructor(name: string, options: Object = {}) { + _extendedProps: { [string] : boolean }; + _initialized: boolean; + _name: string; + _namespaces: { [string]: Object }; + _nativeInitialized: boolean; + _options: FirebaseOptions; + admob: () => AdMob; + auth: () => Auth; + analytics: () => Analytics; + config: () => RemoteConfig; + crash: () => Crash; + database: () => Database; + firestore: () => Firestore; + links: () => Links; + messaging: () => Messaging; + perf: () => Performance; + storage: () => Storage; + utils: () => Utils; + + constructor(name: string, options: FirebaseOptions) { this._name = name; this._namespaces = {}; this._options = Object.assign({}, options); @@ -49,7 +73,7 @@ export default class FirebaseApp { * @param native * @private */ - _initializeApp(native = false) { + _initializeApp(native: boolean = false) { if (native) { // for apps already initialized natively that // we have info from RN constants @@ -67,7 +91,7 @@ export default class FirebaseApp { * * @return {*} */ - get name() { + get name(): string { if (this._name === INTERNALS.STRINGS.DEFAULT_APP_NAME) { // ios and android firebase sdk's return different // app names - so we just return what the web sdk @@ -82,7 +106,7 @@ export default class FirebaseApp { * * @return {*} */ - get options() { + get options(): FirebaseOptions { return Object.assign({}, this._options); } @@ -95,14 +119,14 @@ export default class FirebaseApp { * @param props */ extendApp(props: Object) { - if (!isObject(props)) throw new Error(INTERNALS.ERROR_MISSING_ARG('Object', 'extendApp')); + if (!isObject(props)) throw new Error(INTERNALS.STRINGS.ERROR_MISSING_ARG('Object', 'extendApp')); const keys = Object.keys(props); for (let i = 0, len = keys.length; i < len; i++) { const key = keys[i]; if (!this._extendedProps[key] && Object.hasOwnProperty.call(this, key)) { - throw new Error(INTERNALS.ERROR_PROTECTED_PROP(key)); + throw new Error(INTERNALS.STRINGS.ERROR_PROTECTED_PROP(key)); } this[key] = props[key]; @@ -131,7 +155,7 @@ export default class FirebaseApp { * * @return {*} */ - onReady(): Promise { + onReady(): Promise { if (this._initialized) return Promise.resolve(this); return new Promise((resolve, reject) => { @@ -144,13 +168,12 @@ export default class FirebaseApp { /** * - * @param name * @param statics * @param InstanceClass * @return {function()} * @private */ - _staticsOrModuleInstance(statics = {}, InstanceClass): Function { + _staticsOrModuleInstance(statics: Object = {}, InstanceClass: Class<*>) { const getInstance = () => { const _name = `_${InstanceClass._NAMESPACE}`; diff --git a/lib/firebase.js b/lib/firebase.js index 1cfc1afb..48df2287 100644 --- a/lib/firebase.js +++ b/lib/firebase.js @@ -6,7 +6,7 @@ import { NativeModules, NativeEventEmitter } from 'react-native'; import INTERNALS from './internals'; import FirebaseApp from './firebase-app'; -import { isObject, isString, isAndroid } from './utils'; +import { isObject, isString } from './utils'; // module imports import AdMob, { statics as AdMobStatics } from './modules/admob'; @@ -24,7 +24,31 @@ import Utils, { statics as UtilsStatics } from './modules/utils'; const FirebaseCoreModule = NativeModules.RNFirebase; +export type FirebaseOptions = { + apiKey: string, + appId: string, + databaseURL: string, + messagingSenderId: string, + projectId: string, + storageBucket: string, +} + class FirebaseCore { + _nativeEmitters: { [string]: NativeEventEmitter }; + _nativeSubscriptions: { [string]: boolean }; + admob: () => AdMob; + auth: () => Auth; + analytics: () => Analytics; + config: () => RemoteConfig; + crash: () => Crash; + database: () => Database; + firestore: () => Firestore; + links: () => Links; + messaging: () => Messaging; + perf: () => Performance; + storage: () => Storage; + utils: () => Utils; + constructor() { this._nativeEmitters = {}; this._nativeSubscriptions = {}; @@ -71,7 +95,7 @@ class FirebaseCore { * @param name * @return {*} */ - initializeApp(options: Object = {}, name: string): FirebaseApp { + initializeApp(options: FirebaseOptions, name: string): FirebaseApp { if (name && !isString(name)) { throw new Error(INTERNALS.STRINGS.ERROR_INIT_STRING_NAME); } @@ -163,7 +187,7 @@ class FirebaseCore { * @param nativeEmitter * @private */ - _subscribeForDistribution(eventName, nativeEmitter) { + _subscribeForDistribution(eventName: string, nativeEmitter: NativeEventEmitter) { if (!this._nativeSubscriptions[eventName]) { nativeEmitter.addListener(eventName, (event) => { if (event.appName) { @@ -186,7 +210,7 @@ class FirebaseCore { * @return {function(FirebaseApp=)} * @private */ - _appNamespaceOrStatics(statics = {}, InstanceClass): Function { + _appNamespaceOrStatics(statics: Object = {}, InstanceClass: Class<*>): Function { const namespace = InstanceClass._NAMESPACE; const getNamespace = (app?: FirebaseApp) => { @@ -215,14 +239,13 @@ class FirebaseCore { * @return {*} * @private */ - _getOrSetNativeEmitter(name, nativeModule) { + _getOrSetNativeEmitter(name: string, nativeModule: Object): NativeEventEmitter { if (this._nativeEmitters[name]) { return this._nativeEmitters[name]; } return this._nativeEmitters[name] = new NativeEventEmitter(nativeModule); } - } export default new FirebaseCore(); diff --git a/lib/internals.js b/lib/internals.js index 159ba007..ef7f4998 100644 --- a/lib/internals.js +++ b/lib/internals.js @@ -1,6 +1,10 @@ +/** + * @flow + */ import { Platform, NativeModules } from 'react-native'; import EventEmitter from './utils/emitter/EventEmitter'; +import ModuleBase from './utils/ModuleBase'; import SyncTree from './utils/SyncTree'; const DEFAULT_APP_NAME = Platform.OS === 'ios' ? '__FIRAPP_DEFAULT' : '[DEFAULT]'; @@ -92,35 +96,35 @@ export default { /** * @return {string} */ - ERROR_MISSING_CB(method) { + ERROR_MISSING_CB(method: string) { return `Missing required callback for method ${method}().`; }, /** * @return {string} */ - ERROR_MISSING_ARG(type, method) { + ERROR_MISSING_ARG(type: string, method: string) { return `Missing required argument of type '${type}' for method '${method}()'.`; }, /** * @return {string} */ - ERROR_MISSING_ARG_NAMED(name, type, method) { + ERROR_MISSING_ARG_NAMED(name: string, type: string, method: string) { return `Missing required argument '${name}' of type '${type}' for method '${method}()'.`; }, /** * @return {string} */ - ERROR_ARG_INVALID_VALUE(name, expected, got) { + ERROR_ARG_INVALID_VALUE(name: string, expected: string, got: string) { return `Invalid value for argument '${name}' expected value '${expected}' but got '${got}'.`; }, /** * @return {string} */ - ERROR_PROTECTED_PROP(name) { + ERROR_PROTECTED_PROP(name: string) { return `Property '${name}' is protected and can not be overridden by extendApp.`; }, @@ -129,7 +133,7 @@ export default { * @param namespace * @param nativeModule */ - ERROR_MISSING_MODULE(namespace, nativeModule) { + ERROR_MISSING_MODULE(namespace: string, nativeModule: string) { const snippet = `firebase.${namespace}()`; if (Platform.OS === 'ios') { return `You attempted to use a firebase module that's not installed natively on your iOS project by calling ${snippet}.` + @@ -151,7 +155,7 @@ export default { /** * @return {string} */ - ERROR_APP_NOT_INIT(appName) { + ERROR_APP_NOT_INIT(appName: string) { return `The [${appName}] firebase app has not been initialized!`; }, @@ -160,35 +164,35 @@ export default { * @return {string} * @constructor */ - ERROR_MISSING_OPT(optName) { + ERROR_MISSING_OPT(optName: string) { return `Failed to initialize app. FirebaseOptions missing or invalid '${optName}' property.`; }, /** * @return {string} */ - ERROR_NOT_APP(namespace) { + ERROR_NOT_APP(namespace: string) { return `Invalid FirebaseApp instance passed to firebase.${namespace}(app <--).`; }, /** * @return {string} */ - ERROR_UNSUPPORTED_CLASS_METHOD(className, method) { + ERROR_UNSUPPORTED_CLASS_METHOD(className: string, method: string) { return `${className}.${method}() is unsupported by the native Firebase SDKs.`; }, /** * @return {string} */ - ERROR_UNSUPPORTED_CLASS_PROPERTY(className, property) { + ERROR_UNSUPPORTED_CLASS_PROPERTY(className: string, property: string) { return `${className}.${property} is unsupported by the native Firebase SDKs.`; }, /** * @return {string} */ - ERROR_UNSUPPORTED_MODULE_METHOD(module, method) { + ERROR_UNSUPPORTED_MODULE_METHOD(module: Class, method: string) { return `firebase.${module._NAMESPACE}().${method}() is unsupported by the native Firebase SDKs.`; }, @@ -196,7 +200,7 @@ export default { /** * @return {string} */ - ERROR_PLAY_SERVICES(statusCode) { + ERROR_PLAY_SERVICES(statusCode: number) { const knownError = PLAY_SERVICES_CODES[statusCode]; let start = 'Google Play Services is required to run firebase services on android but a valid installation was not found on this device.'; @@ -208,8 +212,8 @@ export default { return `${start}\r\n\r\n` + '-------------------------\r\n' + (knownError ? - `${knownError.code}: ${knownError.message} (code ${statusCode})` : - `A specific play store availability reason reason was not available (unknown code: ${statusCode || null})` + `${knownError.code}: ${knownError.message} (code ${statusCode})` : + `A specific play store availability reason reason was not available (unknown code: ${statusCode})` ) + '\r\n-------------------------' + '\r\n\r\n' + @@ -226,9 +230,9 @@ export default { SyncTree: NativeModules.RNFirebaseDatabase ? new SyncTree(NativeModules.RNFirebaseDatabase) : null, // internal utils - deleteApp(name: String) { + deleteApp(name: String): Promise { const app = this.APPS[name]; - if (!app) return Promise.resolve(); + if (!app) return Promise.resolve(true); // https://firebase.google.com/docs/reference/js/firebase.app.App#delete return app.delete().then(() => { diff --git a/lib/modules/firestore/CollectionReference.js b/lib/modules/firestore/CollectionReference.js index 05c3a2a5..9c46eda2 100644 --- a/lib/modules/firestore/CollectionReference.js +++ b/lib/modules/firestore/CollectionReference.js @@ -3,19 +3,19 @@ * CollectionReference representation wrapper */ import DocumentReference from './DocumentReference'; -import Path from './Path'; -import Query from './Query'; -import QuerySnapshot from './QuerySnapshot'; +import Query, { type Direction, type Operator } from './Query'; import { firestoreAutoId } from '../../utils'; -import type { Direction, Operator } from './Query'; +import type Firestore from './'; +import type Path from './Path'; +import type QuerySnapshot from './QuerySnapshot'; - /** +/** * @class CollectionReference */ export default class CollectionReference { _collectionPath: Path; - _firestore: Object; + _firestore: Firestore; _query: Query; constructor(firestore: Object, collectionPath: Path) { @@ -71,10 +71,6 @@ export default class CollectionReference { return this._query.limit(n); } - offset(n: number): Query { - return this._query.offset(n); - } - onSnapshot(onNext: () => any, onError?: () => any): () => void { return this._query.onSnapshot(onNext, onError); } @@ -91,10 +87,6 @@ export default class CollectionReference { return this._query.startAt(fieldValues); } - stream(): Stream { - return this._query.stream(); - } - where(fieldPath: string, opStr: Operator, value: any): Query { return this._query.where(fieldPath, opStr, value); } diff --git a/lib/modules/firestore/DocumentChange.js b/lib/modules/firestore/DocumentChange.js index 39697788..b712aa7a 100644 --- a/lib/modules/firestore/DocumentChange.js +++ b/lib/modules/firestore/DocumentChange.js @@ -2,17 +2,19 @@ * @flow * DocumentChange representation wrapper */ -import DocumentSnapshot from './DocumentSnapshot'; +import DocumentSnapshot, { type DocumentSnapshotNativeData } from './DocumentSnapshot'; + +import type Firestore from './'; export type DocumentChangeNativeData = { - document: DocumentSnapshot, + document: DocumentSnapshotNativeData, newIndex: number, oldIndex: number, type: string, } - /** +/** * @class DocumentChange */ export default class DocumentChange { @@ -21,7 +23,7 @@ export default class DocumentChange { _oldIndex: number; _type: string; - constructor(firestore: Object, nativeData: DocumentChangeNativeData) { + constructor(firestore: Firestore, nativeData: DocumentChangeNativeData) { this._document = new DocumentSnapshot(firestore, nativeData.document); this._newIndex = nativeData.newIndex; this._oldIndex = nativeData.oldIndex; diff --git a/lib/modules/firestore/DocumentReference.js b/lib/modules/firestore/DocumentReference.js index 71c1a43c..b6a703ed 100644 --- a/lib/modules/firestore/DocumentReference.js +++ b/lib/modules/firestore/DocumentReference.js @@ -3,11 +3,13 @@ * DocumentReference representation wrapper */ import CollectionReference from './CollectionReference'; -import DocumentSnapshot from './DocumentSnapshot'; -import Path from './Path'; +import DocumentSnapshot, { type DocumentSnapshotNativeData } from './DocumentSnapshot'; import { buildNativeMap } from './utils/serialize'; import { firestoreAutoId, isFunction, isObject, isString } from '../../utils'; +import type Firestore from './'; +import type Path from './Path'; + export type WriteOptions = { merge?: boolean, } @@ -16,24 +18,27 @@ type DocumentListenOptions = { includeMetadataChanges: boolean, } +type ObserverOnError = (Object) => void; +type ObserverOnNext = (DocumentSnapshot) => void; + type Observer = { - next: (DocumentSnapshot) => void, - error?: (Object) => void, + error?: ObserverOnError, + next: ObserverOnNext, } - /** +/** * @class DocumentReference */ export default class DocumentReference { _documentPath: Path; - _firestore: Object; + _firestore: Firestore; - constructor(firestore: Object, documentPath: Path) { + constructor(firestore: Firestore, documentPath: Path) { this._documentPath = documentPath; this._firestore = firestore; } - get firestore(): Object { + get firestore(): Firestore { return this._firestore; } @@ -43,6 +48,9 @@ export default class DocumentReference { get parent(): CollectionReference { const parentPath = this._documentPath.parent(); + if (!parentPath) { + throw new Error('Invalid document path'); + } return new CollectionReference(this._firestore, parentPath); } @@ -71,9 +79,9 @@ export default class DocumentReference { } onSnapshot( - optionsOrObserverOrOnNext: DocumentListenOptions | Observer | (DocumentSnapshot) => void, - observerOrOnNextOrOnError?: Observer | (DocumentSnapshot) => void | (Object) => void, - onError?: (Object) => void + optionsOrObserverOrOnNext: DocumentListenOptions | Observer | ObserverOnNext, + observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError, + onError?: ObserverOnError, ) { let observer = {}; let docListenOptions = {}; @@ -125,8 +133,8 @@ export default class DocumentReference { } const listenerId = firestoreAutoId(); - const listener = (nativeDocumentSnapshot) => { - const documentSnapshot = new DocumentSnapshot(this, nativeDocumentSnapshot); + const listener = (nativeDocumentSnapshot: DocumentSnapshotNativeData) => { + const documentSnapshot = new DocumentSnapshot(this.firestore, nativeDocumentSnapshot); observer.next(documentSnapshot); }; @@ -158,7 +166,7 @@ export default class DocumentReference { .documentSet(this.path, nativeData, writeOptions); } - update(...args: Object | string[]): Promise { + update(...args: Array): Promise { let data = {}; if (args.length === 1) { if (!isObject(args[0])) { @@ -190,7 +198,7 @@ export default class DocumentReference { * Remove document snapshot listener * @param listener */ - _offDocumentSnapshot(listenerId: number, listener: Function) { + _offDocumentSnapshot(listenerId: string, listener: Function) { this._firestore.log.info('Removing onDocumentSnapshot listener'); this._firestore.removeListener(this._firestore._getAppEventName(`onDocumentSnapshot:${listenerId}`), listener); this._firestore.removeListener(this._firestore._getAppEventName(`onDocumentSnapshotError:${listenerId}`), listener); diff --git a/lib/modules/firestore/DocumentSnapshot.js b/lib/modules/firestore/DocumentSnapshot.js index ccff97a6..35899c47 100644 --- a/lib/modules/firestore/DocumentSnapshot.js +++ b/lib/modules/firestore/DocumentSnapshot.js @@ -4,7 +4,9 @@ */ import DocumentReference from './DocumentReference'; import Path from './Path'; -import { parseNativeMap } from './utils/serialize'; +import { parseNativeMap, type TypeMap } from './utils/serialize'; + +import type Firestore from './'; export type SnapshotMetadata = { fromCache: boolean, @@ -12,7 +14,7 @@ export type SnapshotMetadata = { } export type DocumentSnapshotNativeData = { - data: Object, + data: { [string]: TypeMap }, metadata: SnapshotMetadata, path: string, } @@ -21,11 +23,11 @@ export type DocumentSnapshotNativeData = { * @class DocumentSnapshot */ export default class DocumentSnapshot { - _data: Object; + _data: Object | void; _metadata: SnapshotMetadata; _ref: DocumentReference; - constructor(firestore: Object, nativeData: DocumentSnapshotNativeData) { + constructor(firestore: Firestore, nativeData: DocumentSnapshotNativeData) { this._data = parseNativeMap(firestore, nativeData.data); this._metadata = nativeData.metadata; this._ref = new DocumentReference(firestore, Path.fromName(nativeData.path)); @@ -47,11 +49,11 @@ export default class DocumentSnapshot { return this._ref; } - data(): Object { + data(): Object | void { return this._data; } get(fieldPath: string): any { - return this._data[fieldPath]; + return this._data ? this._data[fieldPath] : undefined; } } diff --git a/lib/modules/firestore/GeoPoint.js b/lib/modules/firestore/GeoPoint.js index d99cb19d..2e913c4d 100644 --- a/lib/modules/firestore/GeoPoint.js +++ b/lib/modules/firestore/GeoPoint.js @@ -3,7 +3,7 @@ * GeoPoint representation wrapper */ - /** +/** * @class GeoPoint */ export default class GeoPoint { @@ -19,11 +19,11 @@ export default class GeoPoint { this._longitude = longitude; } - get latitude() { + get latitude(): number { return this._latitude; } - get longitude() { + get longitude(): number { return this._longitude; } } diff --git a/lib/modules/firestore/Path.js b/lib/modules/firestore/Path.js index 0c9eb161..ac6f6a8c 100644 --- a/lib/modules/firestore/Path.js +++ b/lib/modules/firestore/Path.js @@ -3,7 +3,7 @@ * Path representation wrapper */ - /** +/** * @class Path */ export default class Path { diff --git a/lib/modules/firestore/Query.js b/lib/modules/firestore/Query.js index aba8ac81..912e4463 100644 --- a/lib/modules/firestore/Query.js +++ b/lib/modules/firestore/Query.js @@ -2,12 +2,14 @@ * @flow * Query representation wrapper */ -import DocumentSnapshot from './DocumentSnapshot'; -import Path from './Path'; import QuerySnapshot from './QuerySnapshot'; import { buildNativeArray, buildTypeMap } from './utils/serialize'; import { firestoreAutoId, isFunction, isObject } from '../../utils'; +import type DocumentSnapshot from './DocumentSnapshot'; +import type Firestore from './'; +import type Path from './Path'; + const DIRECTIONS = { ASC: 'ASCENDING', asc: 'ASCENDING', @@ -54,19 +56,25 @@ type Observer = { error?: (Object) => void, } - /** +/** * @class Query */ export default class Query { _fieldFilters: FieldFilter[]; _fieldOrders: FieldOrder[]; - _firestore: Object; + _firestore: Firestore; _iid: number; _queryOptions: QueryOptions; _referencePath: Path; - constructor(firestore: Object, path: Path, fieldFilters?: FieldFilter[], - fieldOrders?: FieldOrder[], queryOptions?: QueryOptions) { + constructor( + firestore: Firestore, + path: Path, + fieldFilters?: + FieldFilter[], + fieldOrders?: FieldOrder[], + queryOptions?: QueryOptions, + ) { this._fieldFilters = fieldFilters || []; this._fieldOrders = fieldOrders || []; this._firestore = firestore; @@ -78,24 +86,34 @@ export default class Query { return this._firestore; } - endAt(...snapshotOrVarArgs: any): Query { + endAt(...snapshotOrVarArgs: any[]): Query { const options = { ...this._queryOptions, endAt: this._buildOrderByOption(snapshotOrVarArgs), }; - return new Query(this.firestore, this._referencePath, this._fieldFilters, - this._fieldOrders, options); + return new Query( + this.firestore, + this._referencePath, + this._fieldFilters, + this._fieldOrders, + options, + ); } - endBefore(...snapshotOrVarArgs: any): Query { + endBefore(...snapshotOrVarArgs: any[]): Query { const options = { ...this._queryOptions, endBefore: this._buildOrderByOption(snapshotOrVarArgs), }; - return new Query(this.firestore, this._referencePath, this._fieldFilters, - this._fieldOrders, options); + return new Query( + this.firestore, + this._referencePath, + this._fieldFilters, + this._fieldOrders, + options, + ); } get(): Promise { @@ -117,14 +135,19 @@ export default class Query { ...this._queryOptions, limit, }; - return new Query(this.firestore, this._referencePath, this._fieldFilters, - this._fieldOrders, options); + return new Query( + this.firestore, + this._referencePath, + this._fieldFilters, + this._fieldOrders, + options, + ); } onSnapshot( - optionsOrObserverOrOnNext: QueryListenOptions | Observer | (DocumentSnapshot) => void, - observerOrOnNextOrOnError?: Observer | (DocumentSnapshot) => void | (Object) => void, - onError?: (Object) => void, + optionsOrObserverOrOnNext: QueryListenOptions | Observer | (DocumentSnapshot) => void, + observerOrOnNextOrOnError?: Observer | (DocumentSnapshot) => void | (Object) => void, + onError?: (Object) => void, ) { let observer = {}; let queryListenOptions = {}; @@ -199,12 +222,12 @@ export default class Query { // Add the native listener this._firestore._native .collectionOnSnapshot( - this._referencePath.relativeName, - this._fieldFilters, - this._fieldOrders, - this._queryOptions, - listenerId, - queryListenOptions, + this._referencePath.relativeName, + this._fieldFilters, + this._fieldOrders, + this._queryOptions, + listenerId, + queryListenOptions, ); // Return an unsubscribe method @@ -226,28 +249,43 @@ export default class Query { fieldPath, }; const combinedOrders = this._fieldOrders.concat(newOrder); - return new Query(this.firestore, this._referencePath, this._fieldFilters, - combinedOrders, this._queryOptions); + return new Query( + this.firestore, + this._referencePath, + this._fieldFilters, + combinedOrders, + this._queryOptions, + ); } - startAfter(...snapshotOrVarArgs: any): Query { + startAfter(...snapshotOrVarArgs: any[]): Query { const options = { ...this._queryOptions, startAfter: this._buildOrderByOption(snapshotOrVarArgs), }; - return new Query(this.firestore, this._referencePath, this._fieldFilters, - this._fieldOrders, options); + return new Query( + this.firestore, + this._referencePath, + this._fieldFilters, + this._fieldOrders, + options, + ); } - startAt(...snapshotOrVarArgs: any): Query { + startAt(...snapshotOrVarArgs: any[]): Query { const options = { ...this._queryOptions, startAt: this._buildOrderByOption(snapshotOrVarArgs), }; - return new Query(this.firestore, this._referencePath, this._fieldFilters, - this._fieldOrders, options); + return new Query( + this.firestore, + this._referencePath, + this._fieldFilters, + this._fieldOrders, + options, + ); } where(fieldPath: string, opStr: Operator, value: any): Query { @@ -261,8 +299,13 @@ export default class Query { value: nativeValue, }; const combinedFilters = this._fieldFilters.concat(newFilter); - return new Query(this.firestore, this._referencePath, combinedFilters, - this._fieldOrders, this._queryOptions); + return new Query( + this.firestore, + this._referencePath, + combinedFilters, + this._fieldOrders, + this._queryOptions, + ); } /** @@ -290,7 +333,7 @@ export default class Query { * Remove query snapshot listener * @param listener */ - _offCollectionSnapshot(listenerId: number, listener: Function) { + _offCollectionSnapshot(listenerId: string, listener: Function) { this._firestore.log.info('Removing onQuerySnapshot listener'); this._firestore.removeListener(this._firestore._getAppEventName(`onQuerySnapshot:${listenerId}`), listener); this._firestore.removeListener(this._firestore._getAppEventName(`onQuerySnapshotError:${listenerId}`), listener); @@ -300,7 +343,7 @@ export default class Query { this._fieldFilters, this._fieldOrders, this._queryOptions, - listenerId + listenerId, ); } } diff --git a/lib/modules/firestore/QuerySnapshot.js b/lib/modules/firestore/QuerySnapshot.js index a3ec9050..c7759b22 100644 --- a/lib/modules/firestore/QuerySnapshot.js +++ b/lib/modules/firestore/QuerySnapshot.js @@ -2,12 +2,11 @@ * @flow * QuerySnapshot representation wrapper */ -import DocumentChange from './DocumentChange'; -import DocumentSnapshot from './DocumentSnapshot'; -import Query from './Query'; +import DocumentChange, { type DocumentChangeNativeData } from './DocumentChange'; +import DocumentSnapshot, { type DocumentSnapshotNativeData, type SnapshotMetadata } from './DocumentSnapshot'; -import type { DocumentChangeNativeData } from './DocumentChange'; -import type { DocumentSnapshotNativeData, SnapshotMetadata } from './DocumentSnapshot'; +import type Firestore from './'; +import type Query from './Query'; type QuerySnapshotNativeData = { changes: DocumentChangeNativeData[], @@ -15,7 +14,7 @@ type QuerySnapshotNativeData = { metadata: SnapshotMetadata, } - /** +/** * @class QuerySnapshot */ export default class QuerySnapshot { @@ -24,7 +23,7 @@ export default class QuerySnapshot { _metadata: SnapshotMetadata; _query: Query; - constructor(firestore: Object, query: Query, nativeData: QuerySnapshotNativeData) { + constructor(firestore: Firestore, query: Query, nativeData: QuerySnapshotNativeData) { this._changes = nativeData.changes.map(change => new DocumentChange(firestore, change)); this._docs = nativeData.documents.map(doc => new DocumentSnapshot(firestore, doc)); this._metadata = nativeData.metadata; @@ -43,14 +42,14 @@ export default class QuerySnapshot { return this._docs.length === 0; } - get query(): Query { - return this._query; - } - get metadata(): SnapshotMetadata { return this._metadata; } + get query(): Query { + return this._query; + } + get size(): number { return this._docs.length; } @@ -59,8 +58,8 @@ export default class QuerySnapshot { // TODO: Validation // validate.isFunction('callback', callback); - for (const doc of this._docs) { + this._docs.forEach((doc) => { callback(doc); - } + }); } } diff --git a/lib/modules/firestore/WriteBatch.js b/lib/modules/firestore/WriteBatch.js index 8e657031..70771124 100644 --- a/lib/modules/firestore/WriteBatch.js +++ b/lib/modules/firestore/WriteBatch.js @@ -2,11 +2,11 @@ * @flow * WriteBatch representation wrapper */ -import DocumentReference from './DocumentReference'; import { buildNativeMap } from './utils/serialize'; import { isObject, isString } from '../../utils'; -import type { WriteOptions } from './DocumentReference'; +import type DocumentReference, { WriteOptions } from './DocumentReference'; +import type Firestore from './'; type DocumentWrite = { data?: Object, @@ -15,14 +15,14 @@ type DocumentWrite = { type: 'DELETE' | 'SET' | 'UPDATE', } - /** +/** * @class WriteBatch */ export default class WriteBatch { - _firestore: Object; + _firestore: Firestore; _writes: DocumentWrite[]; - constructor(firestore: Object) { + constructor(firestore: Firestore) { this._firestore = firestore; this._writes = []; } @@ -60,7 +60,7 @@ export default class WriteBatch { return this; } - update(docRef: DocumentReference, ...args: Object | string[]): WriteBatch { + update(docRef: DocumentReference, ...args: any[]): WriteBatch { // TODO: Validation // validate.isDocumentReference('docRef', docRef); let data = {}; diff --git a/lib/modules/firestore/index.js b/lib/modules/firestore/index.js index b24223aa..3161cd03 100644 --- a/lib/modules/firestore/index.js +++ b/lib/modules/firestore/index.js @@ -5,13 +5,16 @@ import ModuleBase from './../../utils/ModuleBase'; import CollectionReference from './CollectionReference'; import DocumentReference from './DocumentReference'; -import DocumentSnapshot from './DocumentSnapshot'; import FieldValue from './FieldValue'; import GeoPoint from './GeoPoint'; import Path from './Path'; import WriteBatch from './WriteBatch'; import INTERNALS from './../../internals'; +import type DocumentSnapshot from './DocumentSnapshot'; +import type FirebaseApp from '../../firebase-app'; +import type QuerySnapshot from './QuerySnapshot'; + type CollectionSyncEvent = { appName: string, querySnapshot?: QuerySnapshot, @@ -37,21 +40,21 @@ export default class Firestore extends ModuleBase { _referencePath: Path; - constructor(firebaseApp: Object, options: Object = {}) { + constructor(firebaseApp: FirebaseApp, options: Object = {}) { super(firebaseApp, options, true); this._referencePath = new Path([]); this.addListener( // sub to internal native event - this fans out to // public event name: onCollectionSnapshot - this._getAppEventName('firestore_collection_sync_event'), + super._getAppEventName('firestore_collection_sync_event'), this._onCollectionSyncEvent.bind(this), ); this.addListener( // sub to internal native event - this fans out to // public event name: onDocumentSnapshot - this._getAppEventName('firestore_document_sync_event'), + super._getAppEventName('firestore_document_sync_event'), this._onDocumentSyncEvent.bind(this), ); } @@ -92,15 +95,15 @@ export default class Firestore extends ModuleBase { throw new Error('Persistence is enabled by default on the Firestore SDKs'); } - runTransaction(updateFunction): Promise { + runTransaction(): Promise { throw new Error('firebase.firestore().runTransaction() coming soon'); } - setLogLevel(logLevel: 'debug' | 'error' | 'silent'): void { + setLogLevel(): void { throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Firestore, 'setLogLevel')); } - settings(settings: Object): void { + settings(): void { throw new Error('firebase.firestore().settings() coming soon'); } @@ -115,9 +118,9 @@ export default class Firestore extends ModuleBase { */ _onCollectionSyncEvent(event: CollectionSyncEvent) { if (event.error) { - this.emit(this._getAppEventName(`onQuerySnapshotError:${event.listenerId}`), event.error); + this.emit(super._getAppEventName(`onQuerySnapshotError:${event.listenerId}`), event.error); } else { - this.emit(this._getAppEventName(`onQuerySnapshot:${event.listenerId}`), event.querySnapshot); + this.emit(super._getAppEventName(`onQuerySnapshot:${event.listenerId}`), event.querySnapshot); } } @@ -128,9 +131,9 @@ export default class Firestore extends ModuleBase { */ _onDocumentSyncEvent(event: DocumentSyncEvent) { if (event.error) { - this.emit(this._getAppEventName(`onDocumentSnapshotError:${event.listenerId}`), event.error); + this.emit(super._getAppEventName(`onDocumentSnapshotError:${event.listenerId}`), event.error); } else { - this.emit(this._getAppEventName(`onDocumentSnapshot:${event.listenerId}`), event.documentSnapshot); + this.emit(super._getAppEventName(`onDocumentSnapshot:${event.listenerId}`), event.documentSnapshot); } } } diff --git a/lib/modules/firestore/utils/serialize.js b/lib/modules/firestore/utils/serialize.js index 5152fcc9..4657711c 100644 --- a/lib/modules/firestore/utils/serialize.js +++ b/lib/modules/firestore/utils/serialize.js @@ -1,4 +1,6 @@ -// @flow +/** + * @flow + */ import DocumentReference from '../DocumentReference'; import { DELETE_FIELD_VALUE, SERVER_TIMESTAMP_FIELD_VALUE } from '../FieldValue'; @@ -6,8 +8,10 @@ import GeoPoint from '../GeoPoint'; import Path from '../Path'; import { typeOf } from '../../../utils'; -type TypeMap = { - type: 'array' | 'boolean' | 'geopoint' | 'null' | 'number' | 'object' | 'reference' | 'string', +import type Firestore from '../'; + +export type TypeMap = { + type: 'array' | 'boolean' | 'date' | 'fieldvalue' | 'geopoint' | 'null' | 'number' | 'object' | 'reference' | 'string', value: any, } @@ -17,65 +21,86 @@ type TypeMap = { * for transmission to the native side */ -export const buildNativeMap = (data: Object): Object => { +export const buildNativeMap = (data: Object): { [string]: TypeMap } => { const nativeData = {}; if (data) { Object.keys(data).forEach((key) => { - nativeData[key] = buildTypeMap(data[key]); + const typeMap = buildTypeMap(data[key]); + if (typeMap) { + nativeData[key] = typeMap; + } }); } return nativeData; }; -export const buildNativeArray = (array: Object[]): any[] => { +export const buildNativeArray = (array: Object[]): TypeMap[] => { const nativeArray = []; if (array) { array.forEach((value) => { - nativeArray.push(buildTypeMap(value)); + const typeMap = buildTypeMap(value); + if (typeMap) { + nativeArray.push(typeMap); + } }); } return nativeArray; }; -export const buildTypeMap = (value: any): any => { - const typeMap = {}; +export const buildTypeMap = (value: any): TypeMap | null => { const type = typeOf(value); if (value === null || value === undefined) { - typeMap.type = 'null'; - typeMap.value = null; + return { + type: 'null', + value: null, + }; } else if (value === DELETE_FIELD_VALUE) { - typeMap.type = 'fieldvalue'; - typeMap.value = 'delete'; + return { + type: 'fieldvalue', + value: 'delete', + }; } else if (value === SERVER_TIMESTAMP_FIELD_VALUE) { - typeMap.type = 'fieldvalue'; - typeMap.value = 'timestamp'; + return { + type: 'fieldvalue', + value: 'timestamp', + }; } else if (type === 'boolean' || type === 'number' || type === 'string') { - typeMap.type = type; - typeMap.value = value; + return { + type, + value, + }; } else if (type === 'array') { - typeMap.type = type; - typeMap.value = buildNativeArray(value); + return { + type, + value: buildNativeArray(value), + }; } else if (type === 'object') { if (value instanceof DocumentReference) { - typeMap.type = 'reference'; - typeMap.value = value.path; + return { + type: 'reference', + value: value.path, + }; } else if (value instanceof GeoPoint) { - typeMap.type = 'geopoint'; - typeMap.value = { - latitude: value.latitude, - longitude: value.longitude, + return { + type: 'geopoint', + value: { + latitude: value.latitude, + longitude: value.longitude, + }, }; } else if (value instanceof Date) { - typeMap.type = 'date'; - typeMap.value = value.getTime(); - } else { - typeMap.type = 'object'; - typeMap.value = buildNativeMap(value); + return { + type: 'date', + value: value.getTime(), + }; } - } else { - console.warn(`Unknown data type received ${type}`); + return { + type: 'object', + value: buildNativeMap(value), + }; } - return typeMap; + console.warn(`Unknown data type received ${type}`); + return null; }; /* @@ -83,7 +108,7 @@ export const buildTypeMap = (value: any): any => { * side and converts to the correct Firestore JS types */ -export const parseNativeMap = (firestore: Object, nativeData: Object): Object => { +export const parseNativeMap = (firestore: Firestore, nativeData: { [string]: TypeMap }): Object | void => { let data; if (nativeData) { data = {}; @@ -94,7 +119,7 @@ export const parseNativeMap = (firestore: Object, nativeData: Object): Object => return data; }; -const parseNativeArray = (firestore: Object, nativeArray: Object[]): any[] => { +const parseNativeArray = (firestore: Firestore, nativeArray: TypeMap[]): any[] => { const array = []; if (nativeArray) { nativeArray.forEach((typeMap) => { @@ -104,7 +129,7 @@ const parseNativeArray = (firestore: Object, nativeArray: Object[]): any[] => { return array; }; -const parseTypeMap = (firestore: Object, typeMap: TypeMap): any => { +const parseTypeMap = (firestore: Firestore, typeMap: TypeMap): any => { const { type, value } = typeMap; if (type === 'null') { return null; diff --git a/lib/utils/ModuleBase.js b/lib/utils/ModuleBase.js index 628ea417..12b548c1 100644 --- a/lib/utils/ModuleBase.js +++ b/lib/utils/ModuleBase.js @@ -6,9 +6,10 @@ import { NativeModules } from 'react-native'; import Log from '../utils/log'; import INTERNALS from './../internals'; import FirebaseCore from './../firebase'; -import FirebaseApp from '../firebase-app'; import { nativeWithApp } from './../utils'; +import type FirebaseApp from '../firebase-app'; + const logs = {}; // Firebase Native SDKs that support multiple app instances @@ -50,7 +51,7 @@ export default class ModuleBase { _options: Object; _appName: string; _namespace: string; - _firebaseApp: Object; + _firebaseApp: FirebaseApp; _eventEmitter: Object; static _NAMESPACE: string; static _NATIVE_MODULE: string; @@ -61,7 +62,7 @@ export default class ModuleBase { * @param options * @param withEventEmitter */ - constructor(firebaseApp: Object, options: Object, withEventEmitter: boolean = false) { + constructor(firebaseApp: FirebaseApp, options: Object, withEventEmitter: boolean = false) { this._module = this.constructor._NATIVE_MODULE.replace('RNFirebase', ''); this._firebaseApp = firebaseApp; this._appName = firebaseApp._name; @@ -73,12 +74,7 @@ export default class ModuleBase { const nativeModule = NativeModules[this.constructor._NATIVE_MODULE]; if (!nativeModule) { - throw new Error( - INTERNALS.STRINGS.ERROR_MISSING_MODULE( - this.constructor._NAMESPACE, - this.constructor._NATIVE_MODULE, - ), - ); + throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(this.constructor._NAMESPACE, this.constructor._NATIVE_MODULE)); } // used by the modules that extend ModuleBase @@ -100,7 +96,7 @@ export default class ModuleBase { * @param moduleName * @private */ - _setupEventEmitter(nativeModule, moduleName) { + _setupEventEmitter(nativeModule: Object, moduleName: string) { this._eventEmitter = FirebaseCore._getOrSetNativeEmitter(`${this._appName}-${this._module}`, nativeModule); const events = NATIVE_MODULE_EVENTS[moduleName]; @@ -117,7 +113,7 @@ export default class ModuleBase { * @return {string} * @private */ - _getAppEventName(eventName) { + _getAppEventName(eventName: string) { return `${this._appName}-${eventName}`; } @@ -131,9 +127,7 @@ export default class ModuleBase { get log(): Log { if (logs[this._namespace]) return logs[this._namespace]; - return logs[this._namespace] = Log.createLogger( - `🔥 ${this._namespace.toUpperCase()}`, - ); + return logs[this._namespace] = Log.createLogger(`🔥 ${this._namespace.toUpperCase()}`); } /* diff --git a/lib/utils/ReferenceBase.js b/lib/utils/ReferenceBase.js index 97fb64a6..4d0daf4e 100644 --- a/lib/utils/ReferenceBase.js +++ b/lib/utils/ReferenceBase.js @@ -1,8 +1,16 @@ /** * @flow */ +import Log from './log'; + +import type Database from '../modules/database'; +import type Storage from '../modules/storage'; + export default class ReferenceBase { - constructor(path: string, module) { + _module: Database | Storage; + path: string; + + constructor(path: string, module: Database | Storage) { this._module = module; this.path = path || '/'; } @@ -17,7 +25,7 @@ export default class ReferenceBase { return this.path === '/' ? null : this.path.substring(this.path.lastIndexOf('/') + 1); } - get log() { + get log(): Log { return this._module.log; } } diff --git a/lib/utils/SyncTree.js b/lib/utils/SyncTree.js index 12cc2078..d8349ef4 100644 --- a/lib/utils/SyncTree.js +++ b/lib/utils/SyncTree.js @@ -1,3 +1,6 @@ +/** + * @flow + */ import { NativeEventEmitter } from 'react-native'; import INTERNALS from './../internals'; @@ -6,13 +9,13 @@ import DatabaseReference from './../modules/database/reference'; import { isString, nativeToJSError } from './../utils'; type Registration = { - key: String, - path: String, - once?: Boolean, - appName: String, - eventType: String, + key: string, + path: string, + once?: boolean, + appName: string, + eventType: string, listener: Function, - eventRegistrationKey: String, + eventRegistrationKey: string, ref: DatabaseReference, } @@ -21,7 +24,12 @@ type Registration = { * subscriptions and keep the listeners in sync in js vs native. */ export default class SyncTree { - constructor(databaseNative) { + _databaseNative: Object; + _nativeEmitter: NativeEventEmitter; + _reverseLookup: { [string]: Registration }; + _tree: { [string]: { [string]: Array }}; + + constructor(databaseNative: Object) { this._tree = {}; this._reverseLookup = {}; this._databaseNative = databaseNative; @@ -110,7 +118,7 @@ export default class SyncTree { * @param registration * @return {null} */ - getRegistration(registration): Registration | null { + getRegistration(registration: string): Registration | null { return this._reverseLookup[registration] ? Object.assign({}, this._reverseLookup[registration]) : null; } @@ -120,7 +128,7 @@ export default class SyncTree { * @param registrations * @return {number} */ - removeListenersForRegistrations(registrations) { + removeListenersForRegistrations(registrations: string | string[]) { if (isString(registrations)) { this.removeRegistration(registrations); INTERNALS.SharedEventEmitter.removeAllListeners(registrations); @@ -143,7 +151,7 @@ export default class SyncTree { * @param registrations * @return {Array} array of registrations removed */ - removeListenerRegistrations(listener, registrations) { + removeListenerRegistrations(listener, registrations: string[]) { if (!Array.isArray(registrations)) return []; const removed = []; @@ -173,7 +181,7 @@ export default class SyncTree { * @param path * @return {Array} */ - getRegistrationsByPath(path): Array { + getRegistrationsByPath(path: string): Array { const out = []; const eventKeys = Object.keys(this._tree[path] || {}); @@ -191,7 +199,7 @@ export default class SyncTree { * @param eventType * @return {Array} */ - getRegistrationsByPathEvent(path, eventType): Array { + getRegistrationsByPathEvent(path: string, eventType: string): Array { if (!this._tree[path]) return []; if (!this._tree[path][eventType]) return []; @@ -228,8 +236,13 @@ export default class SyncTree { * @param listener * @return {String} */ - addRegistration(parameters: Registration, listener): String { - const { path, eventType, eventRegistrationKey, once } = parameters; + addRegistration(parameters: Registration, listener: Function): string { + const { + path, + eventType, + eventRegistrationKey, + once, + } = parameters; if (!this._tree[path]) this._tree[path] = {}; if (!this._tree[path][eventType]) this._tree[path][eventType] = {}; @@ -256,7 +269,7 @@ export default class SyncTree { * @param registration * @return {boolean} */ - removeRegistration(registration: String): Boolean { + removeRegistration(registration: string): boolean { if (!this._reverseLookup[registration]) return false; const { path, eventType, once } = this._reverseLookup[registration]; @@ -298,4 +311,3 @@ export default class SyncTree { }; } } - diff --git a/lib/utils/index.js b/lib/utils/index.js index 137a093a..6f619e4e 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -6,18 +6,10 @@ import { Platform } from 'react-native'; // modeled after base64 web-safe chars, but ordered by ASCII const PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'; const AUTO_ID_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; -const hasOwnProperty = Object.hasOwnProperty; +const { hasOwnProperty } = Object; // const DEFAULT_CHUNK_SIZE = 50; -// Source: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical -const REGEXP_FIELD_NAME = new RegExp( - `^(?:\\.?((?:(?:[A-Za-z_][A-Za-z_0-9]*)|(?:[A-Za-z_][A-Za-z_0-9]*))+))$` -); -const REGEXP_FIELD_PATH = new RegExp( - `^((?:(?:[A-Za-z_][A-Za-z_0-9]*)|(?:[A-Za-z_][A-Za-z_0-9]*))+)(?:\\.((?:(?:[A-Za-z_][A-Za-z_0-9]*)|(?:[A-Za-z_][A-Za-z_0-9]*))+))*$` -); - /** * Deep get a value from an object. * @website https://github.com/Salakar/deeps @@ -26,9 +18,7 @@ const REGEXP_FIELD_PATH = new RegExp( * @param joiner * @returns {*} */ -export function deepGet(object: Object, - path: string, - joiner?: string = '/'): any { +export function deepGet(object: Object, path: string, joiner?: string = '/'): any { const keys = path.split(joiner); let i = 0; @@ -52,9 +42,7 @@ export function deepGet(object: Object, * @param joiner * @returns {*} */ -export function deepExists(object: Object, - path: string, - joiner?: string = '/'): boolean { +export function deepExists(object: Object, path: string, joiner?: string = '/'): boolean { const keys = path.split(joiner); let i = 0; @@ -98,7 +86,7 @@ export function areObjectKeysContainedInOther(obj1 : Object, obj2: Object): bool * @param arr2 * @returns {boolean} */ -export function isArrayContainedInOther(arr1: Array, arr2: Array): boolean { +export function isArrayContainedInOther(arr1: Array<*>, arr2: Array<*>): boolean { if (!Array.isArray(arr1) || !Array.isArray(arr2)) { return false; } @@ -112,8 +100,8 @@ export function isArrayContainedInOther(arr1: Array, arr2: Array): boolean { * @param item * @returns {boolean} */ -export function isObject(item: any): boolean { - return (item && typeof item === 'object' && !Array.isArray(item) && item !== null); +export function isObject(item: mixed): boolean %checks { + return item ? (typeof item === 'object' && !Array.isArray(item) && item !== null) : false; } /** @@ -121,8 +109,8 @@ export function isObject(item: any): boolean { * @param item * @returns {*|boolean} */ -export function isFunction(item?: any): boolean { - return Boolean(item && typeof item === 'function'); +export function isFunction(item?: mixed): boolean %checks { + return item ? typeof item === 'function' : false; } /** @@ -130,20 +118,10 @@ export function isFunction(item?: any): boolean { * @param value * @return {boolean} */ -export function isString(value: any): boolean { +export function isString(value: mixed): boolean %checks { return typeof value === 'string'; } -/** - * Firestore field name/path validator. - * @param field - * @param paths - * @return {boolean} - */ -export function isValidFirestoreField(field, paths) { - return (paths ? REGEXP_FIELD_PATH : REGEXP_FIELD_NAME).test(field); -} - // platform checks export const isIOS = Platform.OS === 'ios'; export const isAndroid = Platform.OS === 'android'; @@ -167,7 +145,7 @@ export function tryJSONParse(string: string | null): any { * @param data * @returns {*} */ -export function tryJSONStringify(data: any): string | null { +export function tryJSONStringify(data: mixed): string | null { try { return JSON.stringify(data); } catch (jsonError) { diff --git a/package-lock.json b/package-lock.json index 685a8fcf..a4207e20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "3.0.6", + "version": "3.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -21,9 +21,9 @@ } }, "acorn": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz", - "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", + "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==", "dev": true }, "acorn-jsx": { @@ -44,19 +44,21 @@ } }, "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.3.0.tgz", + "integrity": "sha1-RBT/dKUIecII7l/cgm4ywwNUnto=", "dev": true, "requires": { "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" } }, "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", "dev": true }, "align-text": { @@ -84,20 +86,17 @@ "ansi-escapes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "anymatch": { "version": "1.3.2", @@ -128,6 +127,15 @@ "sprintf-js": "1.0.3" } }, + "aria-query": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-0.7.0.tgz", + "integrity": "sha512-/r2lHl09V3o74+2MLKEdewoj37YZqiQZnfen1O4iNlrOjUgeKuu1U2yF3iKh6HJxqF+OXkLMfQv65Z/cvxD6vA==", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7" + } + }, "arr-diff": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", @@ -155,6 +163,16 @@ "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", "dev": true }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.8.0" + } + }, "array-map": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", @@ -188,16 +206,6 @@ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, - "array.prototype.find": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz", - "integrity": "sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.8.0" - } - }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -222,15 +230,21 @@ "dev": true }, "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", "dev": true }, "async": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", - "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", "dev": true, "requires": { "lodash": "4.17.4" @@ -243,9 +257,9 @@ "dev": true }, "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", "dev": true }, "aws4": { @@ -254,6 +268,15 @@ "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", "dev": true }, + "axobject-query": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-0.1.0.tgz", + "integrity": "sha1-YvWdvFnJ+SQnWco0mWDnov48NsA=", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7" + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -842,16 +865,10 @@ "dev": true, "requires": { "babel-runtime": "6.26.0", - "core-js": "2.5.0", + "core-js": "2.5.1", "regenerator-runtime": "0.10.5" }, "dependencies": { - "core-js": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz", - "integrity": "sha1-VpwFCRi+ZIazg3VSAorgRmtxcIY=", - "dev": true - }, "regenerator-runtime": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", @@ -986,7 +1003,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, "requires": { "core-js": "2.5.0", "regenerator-runtime": "0.11.0" @@ -995,8 +1011,7 @@ "core-js": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz", - "integrity": "sha1-VpwFCRi+ZIazg3VSAorgRmtxcIY=", - "dev": true + "integrity": "sha1-VpwFCRi+ZIazg3VSAorgRmtxcIY=" } } }, @@ -1101,9 +1116,9 @@ "dev": true }, "big-integer": { - "version": "1.6.24", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.24.tgz", - "integrity": "sha1-HthNAYrDwccrMH5/fZQAjo7iAxE=", + "version": "1.6.25", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.25.tgz", + "integrity": "sha1-HeRan1dUKsIBIcaC+NZCIgo06CM=", "dev": true }, "body-parser": { @@ -1113,7 +1128,7 @@ "dev": true, "requires": { "bytes": "2.1.0", - "content-type": "1.0.2", + "content-type": "1.0.4", "debug": "2.2.0", "depd": "1.0.1", "http-errors": "1.3.1", @@ -1154,12 +1169,12 @@ "dev": true }, "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "4.2.0" } }, "bows": { @@ -1185,7 +1200,7 @@ "integrity": "sha1-1g1dzCDLptx+HymbNdPh+V2vuuY=", "dev": true, "requires": { - "big-integer": "1.6.24" + "big-integer": "1.6.25" } }, "brace-expansion": { @@ -1271,7 +1286,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, "requires": { "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", @@ -1322,8 +1336,7 @@ "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" }, "cliui": { "version": "2.1.0", @@ -1345,9 +1358,9 @@ } }, "clone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", - "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", "dev": true }, "clone-stats": { @@ -1368,6 +1381,21 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "colors": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", @@ -1390,12 +1418,12 @@ "dev": true }, "compressible": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.11.tgz", - "integrity": "sha1-FnGKdd4oPtjmBAQWJaIGRYZ5fYo=", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.12.tgz", + "integrity": "sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY=", "dev": true, "requires": { - "mime-db": "1.29.0" + "mime-db": "1.30.0" } }, "compression": { @@ -1406,7 +1434,7 @@ "requires": { "accepts": "1.2.13", "bytes": "2.1.0", - "compressible": "2.0.11", + "compressible": "2.0.12", "debug": "2.2.0", "on-headers": "1.0.1", "vary": "1.0.1" @@ -1457,7 +1485,7 @@ "bytes": "2.1.0", "compression": "1.5.2", "connect-timeout": "1.6.2", - "content-type": "1.0.2", + "content-type": "1.0.4", "cookie": "0.1.3", "cookie-parser": "1.3.5", "cookie-signature": "1.0.6", @@ -1469,11 +1497,11 @@ "finalhandler": "0.4.0", "fresh": "0.3.0", "http-errors": "1.3.1", - "method-override": "2.3.9", + "method-override": "2.3.10", "morgan": "1.6.1", "multiparty": "3.3.2", "on-headers": "1.0.1", - "parseurl": "1.3.1", + "parseurl": "1.3.2", "pause": "0.1.0", "qs": "4.0.0", "response-time": "2.3.2", @@ -1538,9 +1566,9 @@ "dev": true }, "content-type": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", - "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "dev": true }, "convert-source-map": { @@ -1571,10 +1599,20 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, + "copy-paste": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/copy-paste/-/copy-paste-1.3.0.tgz", + "integrity": "sha1-p+bEocKP3t8rCB5yuX3y75X0ce0=", + "dev": true, + "requires": { + "iconv-lite": "0.4.19", + "sync-exec": "0.6.2" + } + }, "core-js": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", + "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=" }, "core-util-is": { "version": "1.0.2", @@ -1589,12 +1627,12 @@ "dev": true }, "create-react-class": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.0.tgz", - "integrity": "sha1-q0SEl8JlZuHilBPogyB9V8/nvtQ=", + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.2.tgz", + "integrity": "sha1-zx7RXxKq1/FO9fLf4F5sQvke8Co=", "dev": true, "requires": { - "fbjs": "0.8.14", + "fbjs": "0.8.16", "loose-envify": "1.3.1", "object-assign": "4.1.1" } @@ -1610,12 +1648,23 @@ } }, "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", "dev": true, "requires": { - "boom": "2.10.1" + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "dev": true, + "requires": { + "hoek": "4.2.0" + } + } } }, "csrf": { @@ -1659,15 +1708,6 @@ "http-errors": "1.3.1" } }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "0.10.29" - } - }, "damerau-levenshtein": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", @@ -1681,20 +1721,12 @@ "dev": true, "requires": { "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "dateformat": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", - "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", "dev": true }, "debug": { @@ -1892,12 +1924,18 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "emoji-regex": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.5.1.tgz", + "integrity": "sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ==", + "dev": true + }, "encoding": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", "requires": { - "iconv-lite": "0.4.18" + "iconv-lite": "0.4.19" } }, "entities": { @@ -1906,6 +1944,27 @@ "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", "dev": true }, + "envinfo": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-3.9.1.tgz", + "integrity": "sha512-WDDzKLBbQT3PEhKzKRDABFyOxhoiQyHxGvwLtL3ONV68GWsPqeZ5fQKDEutRZ0mAZ5q40+gHOwwZYf1sh57m5g==", + "dev": true, + "requires": { + "copy-paste": "1.3.0", + "glob": "7.1.2", + "minimist": "1.2.0", + "os-name": "2.0.1", + "which": "1.3.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "enzyme": { "version": "2.9.1", "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-2.9.1.tgz", @@ -1920,7 +1979,7 @@ "object.assign": "4.0.4", "object.entries": "1.0.4", "object.values": "1.0.4", - "prop-types": "15.5.10", + "prop-types": "15.6.0", "uuid": "3.1.0" } }, @@ -1958,17 +2017,17 @@ "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", "dev": true, "requires": { - "mime-types": "2.1.16", + "mime-types": "2.1.17", "negotiator": "0.6.1" } }, "mime-types": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", - "integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM=", + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", "dev": true, "requires": { - "mime-db": "1.29.0" + "mime-db": "1.30.0" } }, "negotiator": { @@ -2003,76 +2062,6 @@ "is-symbol": "1.0.1" } }, - "es5-ext": { - "version": "0.10.29", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.29.tgz", - "integrity": "sha512-KXla9NXo5sdaEkGSmbFPYgjH6m75kxsthL6GDRSug/Y2OiMoYm0I9giL39j4cgmaFmAbkIFJ6gG+SGKnLSmOvA==", - "dev": true, - "requires": { - "es6-iterator": "2.0.1", - "es6-symbol": "3.1.1" - } - }, - "es6-iterator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", - "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.29", - "es6-symbol": "3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.29", - "es6-iterator": "2.0.1", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.29", - "es6-iterator": "2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.29" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.29", - "es6-iterator": "2.0.1", - "es6-symbol": "3.1.1" - } - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -2082,78 +2071,136 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.0", - "estraverse": "4.2.0" - } + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", - "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.11.0.tgz", + "integrity": "sha512-UWbhQpaKlm8h5x/VLwm0S1kheMrDj8jPwhnBMjr/Dlo3qqT7MvcN/UfKAR3E1N4lr4YNtOvS4m3hwsrVc/ky7g==", "dev": true, "requires": { + "ajv": "5.3.0", "babel-code-frame": "6.26.0", - "chalk": "1.1.3", + "chalk": "2.3.0", "concat-stream": "1.6.0", - "debug": "2.6.8", + "cross-spawn": "5.1.0", + "debug": "3.1.0", "doctrine": "2.0.0", - "escope": "3.6.0", - "espree": "3.5.0", + "eslint-scope": "3.7.1", + "espree": "3.5.2", "esquery": "1.0.0", "estraverse": "4.2.0", "esutils": "2.0.2", "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", "glob": "7.1.2", "globals": "9.18.0", - "ignore": "3.3.3", + "ignore": "3.3.7", "imurmurhash": "0.1.4", - "inquirer": "0.12.0", - "is-my-json-valid": "2.16.1", + "inquirer": "3.3.0", "is-resolvable": "1.0.0", - "js-yaml": "3.9.1", - "json-stable-stringify": "1.0.1", + "js-yaml": "3.10.0", + "json-stable-stringify-without-jsonify": "1.0.1", "levn": "0.3.0", "lodash": "4.17.4", + "minimatch": "3.0.4", "mkdirp": "0.5.1", "natural-compare": "1.4.0", "optionator": "0.8.2", "path-is-inside": "1.0.2", - "pluralize": "1.2.1", - "progress": "1.1.8", + "pluralize": "7.0.0", + "progress": "2.0.0", "require-uncached": "1.0.3", - "shelljs": "0.7.8", - "strip-bom": "3.0.0", + "semver": "5.4.1", + "strip-ansi": "4.0.0", "strip-json-comments": "2.0.1", - "table": "3.8.3", - "text-table": "0.2.0", - "user-home": "2.0.0" + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } } }, "eslint-config-airbnb": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-12.0.0.tgz", - "integrity": "sha1-qygrdWol8D0ErCZMJNZzoIqAMnA=", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-16.1.0.tgz", + "integrity": "sha512-zLyOhVWhzB/jwbz7IPSbkUuj7X2ox4PHXTcZkEmDqTvd0baJmJyuxlFPDlZOE/Y5bC+HQRaEkT3FoHo9wIdRiw==", "dev": true, "requires": { - "eslint-config-airbnb-base": "8.0.0" + "eslint-config-airbnb-base": "12.1.0" } }, "eslint-config-airbnb-base": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-8.0.0.tgz", - "integrity": "sha1-xelYpGmrivdq/waLQ9eE5a/nTKc=", - "dev": true + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.1.0.tgz", + "integrity": "sha512-/vjm0Px5ZCpmJqnjIzcFb9TKZrKWz0gnuG/7Gfkt0Db1ELJR51xkZth+t14rYdqWgX836XbuxtArbIHlVhbLBA==", + "dev": true, + "requires": { + "eslint-restricted-globals": "0.1.1" + } }, "eslint-import-resolver-node": { "version": "0.3.1", @@ -2176,18 +2223,18 @@ } }, "eslint-plugin-flowtype": { - "version": "2.35.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.35.0.tgz", - "integrity": "sha512-zjXGjOsHds8b84C0Ad3VViKh+sUA9PeXKHwPRlSLwwSX0v1iUJf/6IX7wxc+w2T2tnDH8PT6B/YgtcEuNI3ssA==", + "version": "2.39.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.39.1.tgz", + "integrity": "sha512-RiQv+7Z9QDJuzt+NO8sYgkLGT+h+WeCrxP7y8lI7wpU41x3x/2o3PGtHk9ck8QnA9/mlbNcy/hG0eKvmd7npaA==", "dev": true, "requires": { "lodash": "4.17.4" } }, "eslint-plugin-import": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.7.0.tgz", - "integrity": "sha512-HGYmpU9f/zJaQiKNQOVfHUh2oLWW3STBrCgH0sHTX1xtsxYlH1zjLh8FlQGEIdZSdTbUMaV36WaZ6ImXkenGxQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", + "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", "dev": true, "requires": { "builtin-modules": "1.1.1", @@ -2215,48 +2262,66 @@ } }, "eslint-plugin-jsx-a11y": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-2.2.3.tgz", - "integrity": "sha1-TjXLcbin23AqxBXIBuuOjZ6mxl0=", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.0.2.tgz", + "integrity": "sha1-ZZJ3p1iwNsMFp+ShMFfDAc075z8=", "dev": true, "requires": { + "aria-query": "0.7.0", + "array-includes": "3.0.3", + "ast-types-flow": "0.0.7", + "axobject-query": "0.1.0", "damerau-levenshtein": "1.0.4", - "jsx-ast-utils": "1.4.1", - "object-assign": "4.1.1" + "emoji-regex": "6.5.1", + "jsx-ast-utils": "1.4.1" } }, "eslint-plugin-react": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz", - "integrity": "sha1-xUNb6wZ3ThLH2y9qut3L+QDNP3g=", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.4.0.tgz", + "integrity": "sha512-tvjU9u3VqmW2vVuYnE8Qptq+6ji4JltjOjJ9u7VAOxVYkUkyBZWRvNYKbDv5fN+L6wiA+4we9+qQahZ0m63XEA==", "dev": true, "requires": { - "array.prototype.find": "2.0.4", - "doctrine": "1.5.0", + "doctrine": "2.0.0", "has": "1.0.1", - "jsx-ast-utils": "1.4.1", - "object.assign": "4.0.4" + "jsx-ast-utils": "2.0.1", + "prop-types": "15.6.0" }, "dependencies": { - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "jsx-ast-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz", + "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "array-includes": "3.0.3" } } } }, - "espree": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.0.tgz", - "integrity": "sha1-mDWGJb3QVYYeon4oZ+pyn69GPY0=", + "eslint-restricted-globals": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz", + "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=", + "dev": true + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { - "acorn": "5.1.1", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "espree": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", + "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", + "dev": true, + "requires": { + "acorn": "5.2.1", "acorn-jsx": "3.0.1" } }, @@ -2303,16 +2368,6 @@ "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", "dev": true }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.29" - } - }, "event-target-shim": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-1.1.1.tgz", @@ -2320,9 +2375,9 @@ "dev": true }, "exec-sh": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.0.tgz", - "integrity": "sha1-FPdd4/INKG75MwmbLOUKkDWc7xA=", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.1.tgz", + "integrity": "sha512-aLt95pexaugVtQerpmE51+4QfWrNc304uez7jvj6fWnN8GeEHpttB8F36n8N7uVhUMbH/1enbxQ9HImZ4w/9qg==", "dev": true, "requires": { "merge": "1.2.0" @@ -2364,7 +2419,7 @@ "debug": "2.2.0", "depd": "1.0.1", "on-headers": "1.0.1", - "parseurl": "1.3.1", + "parseurl": "1.3.2", "uid-safe": "2.0.0", "utils-merge": "1.0.0" }, @@ -2437,6 +2492,18 @@ "time-stamp": "1.1.0" } }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", @@ -2464,9 +2531,9 @@ } }, "fbjs": { - "version": "0.8.14", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.14.tgz", - "integrity": "sha1-0dviviVMNakeCfMfnNUKQLKg7Rw=", + "version": "0.8.16", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz", + "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=", "requires": { "core-js": "1.2.7", "isomorphic-fetch": "2.2.1", @@ -2474,7 +2541,14 @@ "object-assign": "4.1.1", "promise": "7.3.1", "setimmediate": "1.0.5", - "ua-parser-js": "0.7.14" + "ua-parser-js": "0.7.17" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + } } }, "fbjs-scripts": { @@ -2524,6 +2598,12 @@ "babel-plugin-transform-object-rest-spread": "6.26.0", "object-assign": "4.1.1" } + }, + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true } } }, @@ -2543,7 +2623,7 @@ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "requires": { - "flat-cache": "1.2.2", + "flat-cache": "1.3.0", "object-assign": "4.1.1" } }, @@ -2612,9 +2692,9 @@ } }, "flat-cache": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", - "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { "circular-json": "0.3.3", @@ -2624,9 +2704,9 @@ } }, "flow-bin": { - "version": "0.55.0", - "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.55.0.tgz", - "integrity": "sha1-kIPakye9jKtrQHbWPYXyJHp+rhs=", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.56.0.tgz", + "integrity": "sha1-zkMJIgOjRLqb9jwMq+ldlRRfbK0=", "dev": true }, "for-in": { @@ -2664,16 +2744,16 @@ "requires": { "asynckit": "0.4.0", "combined-stream": "1.0.5", - "mime-types": "2.1.16" + "mime-types": "2.1.17" }, "dependencies": { "mime-types": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", - "integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM=", + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", "dev": true, "requires": { - "mime-db": "1.29.0" + "mime-db": "1.30.0" } } } @@ -2701,6 +2781,910 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.8.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, "function-bind": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", @@ -2718,6 +3702,12 @@ "is-callable": "1.1.3" } }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "gauge": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", @@ -2731,21 +3721,6 @@ "lodash.padstart": "4.6.1" } }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } - }, "get-caller-file": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", @@ -2759,14 +3734,6 @@ "dev": true, "requires": { "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "glob": { @@ -2857,7 +3824,7 @@ "array-uniq": "1.0.3", "beeper": "1.1.1", "chalk": "1.1.3", - "dateformat": "2.0.0", + "dateformat": "2.2.0", "fancy-log": "1.3.0", "gulplog": "1.0.0", "has-gulplog": "0.1.0", @@ -2897,19 +3864,33 @@ } }, "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", "dev": true }, "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "dev": true, "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" + "ajv": "5.3.0", + "har-schema": "2.0.0" + }, + "dependencies": { + "ajv": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.3.0.tgz", + "integrity": "sha1-RBT/dKUIecII7l/cgm4ywwNUnto=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + } } }, "has": { @@ -2925,11 +3906,16 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, "has-gulplog": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", @@ -2946,21 +3932,21 @@ "dev": true }, "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", "dev": true, "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.1.0" } }, "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", "dev": true }, "home-or-tmp": { @@ -3000,41 +3986,35 @@ "dev": true, "requires": { "inherits": "2.0.3", - "statuses": "1.3.1" + "statuses": "1.4.0" } }, "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { - "assert-plus": "0.2.0", + "assert-plus": "1.0.0", "jsprim": "1.4.1", "sshpk": "1.13.1" } }, "iconv-lite": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", - "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==" + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, "ignore": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz", - "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", "dev": true }, "image-size": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.3.5.tgz", - "integrity": "sha1-gyQOqy+1sAsEqrjHSwRx6cunrYw=", - "dev": true - }, - "immutable": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", - "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.1.tgz", + "integrity": "sha512-lHMlI2MykfeHAQdtydQh4fTcBQVf4zLTA91w1euBe9rbmAfJ/iyzMh8H3KD9u1RldlHaMS3tmMV5TEe9BkmW9g==", "dev": true }, "imurmurhash": { @@ -3060,24 +4040,156 @@ "dev": true }, "inquirer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", + "ansi-escapes": "3.0.0", + "chalk": "2.3.0", + "cli-cursor": "2.1.0", "cli-width": "2.2.0", - "figures": "1.7.0", + "external-editor": "2.0.5", + "figures": "2.0.0", "lodash": "4.17.4", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", "through": "2.3.8" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "external-editor": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.5.tgz", + "integrity": "sha512-Msjo64WT5W+NhOpQXh0nOHm+n0RfU1QUwDnKYvJ8dEJ8zlwLrqXNTv5mSUTJpepf41PDJGyhueTw2vNZW+Fr/w==", + "dev": true, + "requires": { + "iconv-lite": "0.4.19", + "jschardet": "1.6.0", + "tmp": "0.0.33" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + } } }, "interpret": { @@ -3108,9 +4220,9 @@ "dev": true }, "is-buffer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", - "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "is-builtin-module": { @@ -3188,18 +4300,6 @@ "is-extglob": "1.0.0" } }, - "is-my-json-valid": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", @@ -3248,14 +4348,7 @@ "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" }, "is-regex": { "version": "1.0.4", @@ -3316,12 +4409,6 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "isemail": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", - "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=", - "dev": true - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3342,7 +4429,7 @@ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", "requires": { - "node-fetch": "1.7.2", + "node-fetch": "1.6.3", "whatwg-fetch": "2.0.3" } }, @@ -3353,34 +4440,25 @@ "dev": true }, "jest-docblock": { - "version": "20.0.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-20.0.3.tgz", - "integrity": "sha1-F76phDQswz2DxQ++FUXqDvqkRxI=", + "version": "20.1.0-delta.4", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-20.1.0-delta.4.tgz", + "integrity": "sha512-apbBKyQ8ET8XQbOnsjIYTvmo2+FRZIsxUkfy75IbG+SH9ILQLjEfPXq3B/iMRCGoTAeI8lwxUQoLKGbw0mrTCQ==", "dev": true }, "jest-haste-map": { - "version": "20.0.4", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-20.0.4.tgz", - "integrity": "sha1-ZT61XIic48Ah97lGk/IKQVm63wM=", + "version": "20.1.0-delta.4", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-20.1.0-delta.4.tgz", + "integrity": "sha512-L95f3nYoxUSzqzJdOq39ggklspwkqOq/FkzvH0SYhXdpv0c0kW8DXLovxfZy5FnK4rUyeVMBI9aNQ+TvZHKT3Q==", "dev": true, "requires": { "fb-watchman": "2.0.0", "graceful-fs": "4.1.11", - "jest-docblock": "20.0.3", + "jest-docblock": "20.1.0-delta.4", "micromatch": "2.3.11", - "sane": "1.6.0", - "worker-farm": "1.5.0" + "sane": "2.2.0", + "worker-farm": "1.5.2" }, "dependencies": { - "bser": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bser/-/bser-1.0.2.tgz", - "integrity": "sha1-OBEWlwsqbe6lZG3RXdcnhES1YWk=", - "dev": true, - "requires": { - "node-int64": "0.4.0" - } - }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", @@ -3388,54 +4466,32 @@ "dev": true }, "sane": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/sane/-/sane-1.6.0.tgz", - "integrity": "sha1-lhDEUjB6E10pwf3+JUcDQYDEZ3U=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-2.2.0.tgz", + "integrity": "sha512-OSJxhHO0CgPUw3lUm3GhfREAfza45smvEI9ozuFrxKG10GHVo0ryW9FK5VYlLvxj0SV7HVKHW0voYJIRu27GWg==", "dev": true, "requires": { "anymatch": "1.3.2", - "exec-sh": "0.2.0", - "fb-watchman": "1.9.2", + "exec-sh": "0.2.1", + "fb-watchman": "2.0.0", + "fsevents": "1.1.3", "minimatch": "3.0.4", "minimist": "1.2.0", "walker": "1.0.7", - "watch": "0.10.0" - }, - "dependencies": { - "fb-watchman": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-1.9.2.tgz", - "integrity": "sha1-okz0eCf4LTj7Waaa1wt247auc4M=", - "dev": true, - "requires": { - "bser": "1.0.2" - } - } + "watch": "0.18.0" } } } }, - "joi": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", - "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", - "dev": true, - "requires": { - "hoek": "2.16.3", - "isemail": "1.2.0", - "moment": "2.18.1", - "topo": "1.1.0" - } - }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" }, "js-yaml": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz", - "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", "dev": true, "requires": { "argparse": "1.0.9", @@ -3449,6 +4505,11 @@ "dev": true, "optional": true }, + "jschardet": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.6.0.tgz", + "integrity": "sha512-xYuhvQ7I9PDJIGBWev9xm0+SMSed3ZDBAmvVjbFR1ZRLAF+vlXcQu6cRI9uAlj81rzikElRVteehwV7DuX2ZmQ==" + }, "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", @@ -3461,6 +4522,12 @@ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, "json-stable-stringify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", @@ -3470,6 +4537,12 @@ "jsonify": "0.0.0" } }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -3497,12 +4570,6 @@ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -3513,14 +4580,6 @@ "extsprintf": "1.3.0", "json-schema": "0.2.3", "verror": "1.10.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "jsx-ast-utils": { @@ -3535,7 +4594,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "1.1.6" } }, "klaw": { @@ -3611,8 +4670,7 @@ "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" }, "lodash._basecopy": { "version": "3.0.1", @@ -3859,6 +4917,12 @@ "yallist": "2.1.2" } }, + "macos-release": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-1.1.0.tgz", + "integrity": "sha512-mmLbumEYMi5nXReB9js3WGsB8UE6cDBWyIO62Z4DNx6GbRhDxHNjA1MlzSpJ2S2KM1wyiPRA0d19uHWYYvMHjA==", + "dev": true + }, "makeerror": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", @@ -3880,22 +4944,40 @@ "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=", "dev": true }, - "method-override": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.9.tgz", - "integrity": "sha1-vRUfLONM8Bp2ykAKuVwBKxAtj3E=", + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", "dev": true, "requires": { - "debug": "2.6.8", + "readable-stream": "2.3.3" + } + }, + "method-override": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", + "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", + "dev": true, + "requires": { + "debug": "2.6.9", "methods": "1.1.2", - "parseurl": "1.3.1", - "vary": "1.1.1" + "parseurl": "1.3.2", + "vary": "1.1.2" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "vary": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", - "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true } } @@ -3906,6 +4988,159 @@ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", "dev": true }, + "metro-bundler": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/metro-bundler/-/metro-bundler-0.11.0.tgz", + "integrity": "sha512-z1b2HtOa1uJVrp5KOx9bvoYRPD8Gn5x+gyFTIGSev7hbDzyAmUoooFUf8yLAfyIVIb4TZGB+tjkn+Skmn41aNQ==", + "dev": true, + "requires": { + "absolute-path": "0.0.0", + "async": "2.6.0", + "babel-core": "6.26.0", + "babel-generator": "6.26.0", + "babel-plugin-external-helpers": "6.22.0", + "babel-preset-es2015-node": "6.1.1", + "babel-preset-fbjs": "2.1.4", + "babel-preset-react-native": "2.1.0", + "babel-register": "6.26.0", + "babylon": "6.18.0", + "chalk": "1.1.3", + "concat-stream": "1.6.0", + "core-js": "2.5.1", + "debug": "2.6.8", + "denodeify": "1.2.1", + "fbjs": "0.8.12", + "graceful-fs": "4.1.11", + "image-size": "0.6.1", + "jest-docblock": "20.1.0-chi.1", + "jest-haste-map": "20.1.0-chi.1", + "json-stable-stringify": "1.0.1", + "json5": "0.4.0", + "left-pad": "1.1.3", + "lodash": "4.17.4", + "merge-stream": "1.0.1", + "mime-types": "2.1.11", + "mkdirp": "0.5.1", + "request": "2.83.0", + "rimraf": "2.6.1", + "source-map": "0.5.7", + "temp": "0.8.3", + "throat": "4.1.0", + "uglify-js": "2.7.5", + "write-file-atomic": "1.3.4", + "xpipe": "1.0.5" + }, + "dependencies": { + "babel-preset-react-native": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-react-native/-/babel-preset-react-native-2.1.0.tgz", + "integrity": "sha1-kBPr2C2hyIECv1iIEP9Z4gnKK4o=", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-react-transform": "2.0.2", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-plugin-syntax-flow": "6.18.0", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-plugin-transform-object-assign": "6.22.0", + "babel-plugin-transform-object-rest-spread": "6.26.0", + "babel-plugin-transform-react-display-name": "6.25.0", + "babel-plugin-transform-react-jsx": "6.24.1", + "babel-plugin-transform-react-jsx-source": "6.22.0", + "babel-plugin-transform-regenerator": "6.26.0", + "react-transform-hmr": "1.0.4" + } + }, + "fbjs": { + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.12.tgz", + "integrity": "sha1-ELXZL3bUVXX9Y6IX1OoCvqL47QQ=", + "dev": true, + "requires": { + "core-js": "1.2.7", + "isomorphic-fetch": "2.2.1", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "promise": "7.3.1", + "setimmediate": "1.0.5", + "ua-parser-js": "0.7.17" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true + } + } + }, + "jest-docblock": { + "version": "20.1.0-chi.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-20.1.0-chi.1.tgz", + "integrity": "sha512-zX64LtNgTgphO06akqDxKQhVET3uwjZTRalqG2jJoWyEdSUYGp8yjjqicJ7rRu5ZbwnuaB8yqqP9Exu59oDNaA==", + "dev": true + }, + "jest-haste-map": { + "version": "20.1.0-chi.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-20.1.0-chi.1.tgz", + "integrity": "sha512-G5Bjy3NoSBOR4T5FGqu6VlUJk7BnGUfRXkPcU26HTE06j5T0HEnVoScUsP1+XHSSw0XKq84N2LquppHbg3buxg==", + "dev": true, + "requires": { + "fb-watchman": "2.0.0", + "graceful-fs": "4.1.11", + "jest-docblock": "20.1.0-chi.1", + "micromatch": "2.3.11", + "sane": "2.2.0", + "worker-farm": "1.5.2" + } + }, + "json5": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz", + "integrity": "sha1-BUNS5MTIDIbAkjh31EneF2pzLI0=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "sane": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-2.2.0.tgz", + "integrity": "sha512-OSJxhHO0CgPUw3lUm3GhfREAfza45smvEI9ozuFrxKG10GHVo0ryW9FK5VYlLvxj0SV7HVKHW0voYJIRu27GWg==", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "exec-sh": "0.2.1", + "fb-watchman": "2.0.0", + "fsevents": "1.1.3", + "minimatch": "3.0.4", + "minimist": "1.2.0", + "walker": "1.0.7", + "watch": "0.18.0" + } + } + } + }, "micromatch": { "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", @@ -3924,19 +5159,19 @@ "normalize-path": "2.1.1", "object.omit": "2.0.1", "parse-glob": "3.0.4", - "regex-cache": "0.4.3" + "regex-cache": "0.4.4" } }, "mime": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz", - "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", "dev": true }, "mime-db": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", - "integrity": "sha1-SNJtI1WJZRcErFkWygYAGRQmaHg=", + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", "dev": true }, "mime-types": { @@ -3956,6 +5191,11 @@ } } }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=" + }, "min-document": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", @@ -3989,12 +5229,6 @@ "minimist": "0.0.8" } }, - "moment": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", - "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=", - "dev": true - }, "morgan": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", @@ -4077,11 +5311,18 @@ } }, "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "dev": true, + "optional": true + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -4095,9 +5336,9 @@ "dev": true }, "node-fetch": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.2.tgz", - "integrity": "sha512-xZZUq2yDhKMIn/UgG5q//IZSNLJIwW2QxS14CNH5spuiXkITM2pUitjdq58yLSaU7m4M0wBNaM2Gh/ggY4YJig==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", + "integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=", "requires": { "encoding": "0.1.12", "is-stream": "1.1.0" @@ -4254,6 +5495,163 @@ "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", "dev": true }, + "opencollective": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/opencollective/-/opencollective-1.0.3.tgz", + "integrity": "sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE=", + "requires": { + "babel-polyfill": "6.23.0", + "chalk": "1.1.3", + "inquirer": "3.0.6", + "minimist": "1.2.0", + "node-fetch": "1.6.3", + "opn": "4.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "babel-polyfill": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", + "integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=", + "requires": { + "babel-runtime": "6.26.0", + "core-js": "2.5.1", + "regenerator-runtime": "0.10.5" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "2.0.0" + } + }, + "external-editor": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.5.tgz", + "integrity": "sha512-Msjo64WT5W+NhOpQXh0nOHm+n0RfU1QUwDnKYvJ8dEJ8zlwLrqXNTv5mSUTJpepf41PDJGyhueTw2vNZW+Fr/w==", + "requires": { + "iconv-lite": "0.4.19", + "jschardet": "1.6.0", + "tmp": "0.0.33" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "inquirer": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.0.6.tgz", + "integrity": "sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c=", + "requires": { + "ansi-escapes": "1.4.0", + "chalk": "1.1.3", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.0.5", + "figures": "2.0.0", + "lodash": "4.17.4", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx": "4.1.0", + "string-width": "2.1.1", + "strip-ansi": "3.0.1", + "through": "2.3.8" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "1.1.0" + } + }, + "opn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", + "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", + "requires": { + "object-assign": "4.1.1", + "pinkie-promise": "2.0.1" + } + }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "requires": { + "is-promise": "2.1.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "1.0.2" + } + } + } + }, "opn": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/opn/-/opn-3.0.3.tgz", @@ -4316,6 +5714,16 @@ "lcid": "1.0.0" } }, + "os-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-2.0.1.tgz", + "integrity": "sha1-uaOGNhwXrjohc27wWZQFyajF3F4=", + "dev": true, + "requires": { + "macos-release": "1.1.0", + "win-release": "1.1.1" + } + }, "os-shim": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", @@ -4325,8 +5733,7 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "p-limit": { "version": "1.1.0", @@ -4365,9 +5772,9 @@ } }, "parseurl": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", - "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", "dev": true }, "path-exists": { @@ -4419,9 +5826,9 @@ "dev": true }, "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, "pify": { @@ -4433,14 +5840,12 @@ "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, "requires": { "pinkie": "2.0.4" } @@ -4475,9 +5880,9 @@ } }, "pluralize": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, "prelude-ls": { @@ -4517,9 +5922,9 @@ "dev": true }, "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", "dev": true }, "promise": { @@ -4531,12 +5936,13 @@ } }, "prop-types": { - "version": "15.5.10", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", - "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz", + "integrity": "sha1-zq8IMCL8RrSjX2nhPvda7Q1jmFY=", "requires": { - "fbjs": "0.8.14", - "loose-envify": "1.3.1" + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" } }, "prr": { @@ -4600,7 +6006,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "1.1.6" } } } @@ -4611,7 +6017,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "1.1.5" + "is-buffer": "1.1.6" } } } @@ -4648,16 +6054,15 @@ } }, "react": { - "version": "15.6.1", - "resolved": "https://registry.npmjs.org/react/-/react-15.6.1.tgz", - "integrity": "sha1-uqhDTsZ4C96ZfNw4C3nNM7ljk98=", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/react/-/react-16.1.1.tgz", + "integrity": "sha512-FQfiFfk2z2Fk87OngNJHT05KyC9DOVn8LPeB7ZX+9u5+yU1JK6o5ozRlU3PeOMr0IFkWNvgn9jU8/IhRxR1F0g==", "dev": true, "requires": { - "create-react-class": "15.6.0", - "fbjs": "0.8.14", + "fbjs": "0.8.16", "loose-envify": "1.3.1", "object-assign": "4.1.1", - "prop-types": "15.5.10" + "prop-types": "15.6.0" } }, "react-clone-referenced-element": { @@ -4673,9 +6078,9 @@ "dev": true }, "react-devtools-core": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-2.5.0.tgz", - "integrity": "sha512-sLlDHiY+DoOnzEXdLwSGxob3MtiIwM54s6FBbVAc/iOorNd8Nv1aVUTsZpTnJXDYa8p5VPNdCR4ATQ0HcIBh+Q==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-2.5.2.tgz", + "integrity": "sha1-+XvsWvrl2TGNFneAZeDCFMTVcUw=", "dev": true, "requires": { "shell-quote": "1.6.1", @@ -4701,37 +6106,38 @@ } }, "react-dom": { - "version": "15.6.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.1.tgz", - "integrity": "sha1-LLDtQZEDjlPCCes6eaI+Kkz5lHA=", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.1.1.tgz", + "integrity": "sha512-q06jiwST8SEPAMIEkAsu7BgynEZtqF87VrTc70XsW7nxVhWEu2Y4MF5UfxxHQO/mNtQHQWP0YcFxmwm9oMrMaQ==", "dev": true, "requires": { - "fbjs": "0.8.14", + "fbjs": "0.8.16", "loose-envify": "1.3.1", "object-assign": "4.1.1", - "prop-types": "15.5.10" + "prop-types": "15.6.0" } }, "react-native": { - "version": "0.44.3", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.44.3.tgz", - "integrity": "sha1-BFUOHN/GGacS8/WWnWjNfC3EwHM=", + "version": "0.48.4", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.48.4.tgz", + "integrity": "sha1-8wXp/vBppbP2pyUN3VD2A88wqy0=", "dev": true, "requires": { "absolute-path": "0.0.0", "art": "0.10.1", - "async": "2.5.0", + "async": "2.6.0", "babel-core": "6.26.0", "babel-generator": "6.26.0", "babel-plugin-external-helpers": "6.22.0", "babel-plugin-syntax-trailing-function-commas": "6.22.0", "babel-plugin-transform-async-to-generator": "6.16.0", + "babel-plugin-transform-class-properties": "6.24.1", "babel-plugin-transform-flow-strip-types": "6.22.0", "babel-plugin-transform-object-rest-spread": "6.26.0", "babel-polyfill": "6.26.0", "babel-preset-es2015-node": "6.1.1", "babel-preset-fbjs": "2.1.4", - "babel-preset-react-native": "1.9.2", + "babel-preset-react-native": "2.1.0", "babel-register": "6.26.0", "babel-runtime": "6.26.0", "babel-traverse": "6.26.0", @@ -4743,44 +6149,46 @@ "commander": "2.11.0", "concat-stream": "1.6.0", "connect": "2.30.2", - "core-js": "2.5.0", + "core-js": "2.5.1", + "create-react-class": "15.6.2", "debug": "2.6.8", "denodeify": "1.2.1", + "envinfo": "3.9.1", + "errno": "0.1.4", "event-target-shim": "1.1.1", - "fbjs": "0.8.14", + "fbjs": "0.8.12", "fbjs-scripts": "0.7.1", "form-data": "2.3.1", "fs-extra": "1.0.0", "glob": "7.1.2", "graceful-fs": "4.1.11", - "image-size": "0.3.5", - "immutable": "3.7.6", - "imurmurhash": "0.1.4", - "inquirer": "0.12.0", - "jest-haste-map": "20.0.4", - "joi": "6.10.1", + "inquirer": "3.3.0", + "jest-haste-map": "20.1.0-delta.4", "json-stable-stringify": "1.0.1", "json5": "0.4.0", "left-pad": "1.1.3", "lodash": "4.17.4", - "mime": "1.3.6", + "merge-stream": "1.0.1", + "metro-bundler": "0.11.0", + "mime": "1.4.1", "mime-types": "2.1.11", "minimist": "1.2.0", "mkdirp": "0.5.1", - "node-fetch": "1.7.2", + "node-fetch": "1.6.3", "npmlog": "2.0.4", "opn": "3.0.3", "optimist": "0.6.1", "plist": "1.2.0", "pretty-format": "4.3.1", "promise": "7.3.1", + "prop-types": "15.6.0", "react-clone-referenced-element": "1.0.1", - "react-devtools-core": "2.5.0", + "react-devtools-core": "2.5.2", "react-timer-mixin": "0.13.3", "react-transform-hmr": "1.0.4", "rebound": "0.0.13", "regenerator-runtime": "0.9.6", - "request": "2.81.0", + "request": "2.83.0", "rimraf": "2.6.1", "sane": "1.4.1", "semver": "5.4.1", @@ -4788,23 +6196,167 @@ "source-map": "0.5.7", "stacktrace-parser": "0.1.4", "temp": "0.8.3", - "throat": "3.2.0", - "uglify-js": "2.7.5", + "throat": "4.1.0", "whatwg-fetch": "1.1.1", "wordwrap": "1.0.0", - "worker-farm": "1.5.0", "write-file-atomic": "1.3.4", - "ws": "1.1.4", + "ws": "1.1.5", "xcode": "0.9.3", "xmldoc": "0.4.0", "xpipe": "1.0.5", + "xtend": "4.0.1", "yargs": "6.6.0" }, "dependencies": { - "core-js": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz", - "integrity": "sha1-VpwFCRi+ZIazg3VSAorgRmtxcIY=", + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "babel-preset-react-native": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-react-native/-/babel-preset-react-native-2.1.0.tgz", + "integrity": "sha1-kBPr2C2hyIECv1iIEP9Z4gnKK4o=", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-react-transform": "2.0.2", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-plugin-syntax-flow": "6.18.0", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-plugin-transform-object-assign": "6.22.0", + "babel-plugin-transform-object-rest-spread": "6.26.0", + "babel-plugin-transform-react-display-name": "6.25.0", + "babel-plugin-transform-react-jsx": "6.24.1", + "babel-plugin-transform-react-jsx-source": "6.22.0", + "babel-plugin-transform-regenerator": "6.26.0", + "react-transform-hmr": "1.0.4" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "external-editor": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.5.tgz", + "integrity": "sha512-Msjo64WT5W+NhOpQXh0nOHm+n0RfU1QUwDnKYvJ8dEJ8zlwLrqXNTv5mSUTJpepf41PDJGyhueTw2vNZW+Fr/w==", + "dev": true, + "requires": { + "iconv-lite": "0.4.19", + "jschardet": "1.6.0", + "tmp": "0.0.33" + } + }, + "fbjs": { + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.12.tgz", + "integrity": "sha1-ELXZL3bUVXX9Y6IX1OoCvqL47QQ=", + "dev": true, + "requires": { + "core-js": "1.2.7", + "isomorphic-fetch": "2.2.1", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "promise": "7.3.1", + "setimmediate": "1.0.5", + "ua-parser-js": "0.7.17" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true + } + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.0", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.0.5", + "figures": "2.0.0", + "lodash": "4.17.4", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + }, + "dependencies": { + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + } + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "json5": { @@ -4819,12 +6371,89 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, "regenerator-runtime": { "version": "0.9.6", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz", "integrity": "sha1-0z65XQ0gAaS+OWWXB8UbDLcc4Ck=", "dev": true }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, "whatwg-fetch": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-1.1.1.tgz", @@ -4906,17 +6535,6 @@ "util-deprecate": "1.0.2" } }, - "readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "mute-stream": "0.0.5" - } - }, "rebound": { "version": "0.0.13", "resolved": "https://registry.npmjs.org/rebound/-/rebound-0.0.13.tgz", @@ -4933,16 +6551,15 @@ } }, "regenerate": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz", - "integrity": "sha1-0ZQcZ7rUN+G+dkM63Vs4X5WxkmA=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", "dev": true }, "regenerator-runtime": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", - "dev": true + "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==" }, "regenerator-transform": { "version": "0.10.1", @@ -4956,13 +6573,12 @@ } }, "regex-cache": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", - "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", "dev": true, "requires": { - "is-equal-shallow": "0.1.3", - "is-primitive": "2.0.0" + "is-equal-shallow": "0.1.3" } }, "regexpu-core": { @@ -4971,7 +6587,7 @@ "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", "dev": true, "requires": { - "regenerate": "1.3.2", + "regenerate": "1.3.3", "regjsgen": "0.2.0", "regjsparser": "0.1.5" } @@ -5033,61 +6649,48 @@ "dev": true }, "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", "dev": true, "requires": { - "aws-sign2": "0.6.0", + "aws-sign2": "0.7.0", "aws4": "1.6.0", "caseless": "0.12.0", "combined-stream": "1.0.5", "extend": "3.0.1", "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", + "form-data": "2.3.1", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.11", + "mime-types": "2.1.17", "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", + "performance-now": "2.1.0", + "qs": "6.5.1", "safe-buffer": "5.1.1", "stringstream": "0.0.5", - "tough-cookie": "2.3.2", + "tough-cookie": "2.3.3", "tunnel-agent": "0.6.0", "uuid": "3.1.0" }, "dependencies": { - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", "dev": true, "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.16" - }, - "dependencies": { - "mime-types": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", - "integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM=", - "dev": true, - "requires": { - "mime-db": "1.29.0" - } - } + "mime-db": "1.30.0" } }, "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", "dev": true } } @@ -5182,19 +6785,18 @@ "dev": true }, "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "once": "1.4.0" + "is-promise": "2.1.0" } }, "rx": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", - "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=", - "dev": true + "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" }, "rx-lite": { "version": "3.1.2", @@ -5202,6 +6804,15 @@ "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", "dev": true }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "3.1.2" + } + }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", @@ -5214,7 +6825,7 @@ "integrity": "sha1-iPdj10BA9fDCVrYWPbOZvxEKxxU=", "dev": true, "requires": { - "exec-sh": "0.2.0", + "exec-sh": "0.2.1", "fb-watchman": "1.9.2", "minimatch": "3.0.4", "minimist": "1.2.0", @@ -5245,6 +6856,12 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true + }, + "watch": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/watch/-/watch-0.10.0.tgz", + "integrity": "sha1-d3mLLaD5kQ1ZXxrOWwwiWFIfIdw=", + "dev": true } } }, @@ -5324,7 +6941,7 @@ "etag": "1.7.0", "fresh": "0.3.0", "ms": "0.7.2", - "parseurl": "1.3.1" + "parseurl": "1.3.2" }, "dependencies": { "ms": { @@ -5347,7 +6964,7 @@ "escape-html": "1.0.3", "http-errors": "1.3.1", "mime-types": "2.1.11", - "parseurl": "1.3.1" + "parseurl": "1.3.2" }, "dependencies": { "debug": { @@ -5374,7 +6991,7 @@ "dev": true, "requires": { "escape-html": "1.0.3", - "parseurl": "1.3.1", + "parseurl": "1.3.2", "send": "0.13.2" } }, @@ -5389,6 +7006,21 @@ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, "shell-quote": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", @@ -5412,6 +7044,11 @@ "rechoir": "0.6.2" } }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, "simple-plist": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-0.2.1.tgz", @@ -5455,10 +7092,21 @@ "dev": true }, "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } }, "slide": { "version": "1.1.6", @@ -5467,12 +7115,12 @@ "dev": true }, "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "4.2.0" } }, "source-map": { @@ -5547,14 +7195,6 @@ "getpass": "0.1.7", "jsbn": "0.1.1", "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "stacktrace-parser": { @@ -5564,9 +7204,9 @@ "dev": true }, "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", "dev": true }, "stream-buffers": { @@ -5610,15 +7250,6 @@ } } }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -5630,6 +7261,15 @@ "strip-ansi": "3.0.1" } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", @@ -5640,7 +7280,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -5660,20 +7299,26 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "sync-exec": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/sync-exec/-/sync-exec-0.6.2.tgz", + "integrity": "sha1-cX0izFPwzh3vVZQ2LzqJouu5EQU=", + "dev": true, + "optional": true }, "table": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", + "ajv": "5.3.0", + "ajv-keywords": "2.1.1", + "chalk": "2.3.0", "lodash": "4.17.4", - "slice-ansi": "0.0.4", + "slice-ansi": "1.0.0", "string-width": "2.1.1" }, "dependencies": { @@ -5683,6 +7328,26 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -5707,6 +7372,15 @@ "requires": { "ansi-regex": "3.0.0" } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } } } }, @@ -5735,16 +7409,15 @@ "dev": true }, "throat": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/throat/-/throat-3.2.0.tgz", - "integrity": "sha512-/EY8VpvlqJ+sFtLPeOgc8Pl7kQVOWv0woD87KTXVHPIAE842FGT+rokxIhe8xIUP1cfgrkt0as0vDLjDiMtr8w==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", "dev": true }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "2.0.3", @@ -5783,19 +7456,10 @@ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", "dev": true }, - "topo": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", - "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, "tough-cookie": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", - "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", "dev": true, "requires": { "punycode": "1.4.1" @@ -5851,16 +7515,16 @@ "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.16" + "mime-types": "2.1.17" }, "dependencies": { "mime-types": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", - "integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM=", + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", "dev": true, "requires": { - "mime-db": "1.29.0" + "mime-db": "1.30.0" } } } @@ -5872,9 +7536,9 @@ "dev": true }, "ua-parser-js": { - "version": "0.7.14", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.14.tgz", - "integrity": "sha1-EQ1T+kw/MmwSEpK76skE0uAzh8o=" + "version": "0.7.17", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", + "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==" }, "uglify-js": { "version": "2.7.5", @@ -5941,15 +7605,6 @@ "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=", "dev": true }, - "user-home": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -5999,14 +7654,6 @@ "assert-plus": "1.0.0", "core-util-is": "1.0.2", "extsprintf": "1.3.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "vhost": { @@ -6021,7 +7668,7 @@ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "1.0.2", + "clone": "1.0.3", "clone-stats": "0.0.1", "replace-ext": "0.0.1" } @@ -6036,10 +7683,22 @@ } }, "watch": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/watch/-/watch-0.10.0.tgz", - "integrity": "sha1-d3mLLaD5kQ1ZXxrOWwwiWFIfIdw=", - "dev": true + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz", + "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=", + "dev": true, + "requires": { + "exec-sh": "0.2.1", + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } }, "whatwg-fetch": { "version": "2.0.3", @@ -6061,6 +7720,15 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, + "win-release": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz", + "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", + "dev": true, + "requires": { + "semver": "5.4.1" + } + }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", @@ -6271,9 +7939,9 @@ "dev": true }, "worker-farm": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.5.0.tgz", - "integrity": "sha512-DHRiUggxtbruaTwnLDm2/BRDKZIoOYvrgYUj5Bam4fU6Gtvc0FaEyoswFPBjMXAweGW2H4BDNIpy//1yXXuaqQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.5.2.tgz", + "integrity": "sha512-XxiQ9kZN5n6mmnW+mFJ+wXjNNI/Nx4DIdaAKLX1Bn6LYBWlN/zaBhu34DQYPZ1AJobQuu67S2OfDdNSVULvXkQ==", "dev": true, "requires": { "errno": "0.1.4", @@ -6317,9 +7985,9 @@ } }, "ws": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.4.tgz", - "integrity": "sha1-V/QNA2gy5fUFVmKjl8Tedu1mv2E=", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", "dev": true, "requires": { "options": "0.0.6", diff --git a/package.json b/package.json index 620bdbc9..2b7eed60 100644 --- a/package.json +++ b/package.json @@ -75,13 +75,13 @@ "babel-preset-react-native": "^1.9.0", "debug": "^2.2.0", "enzyme": "^2.4.1", - "eslint": "^3.8.1", - "eslint-config-airbnb": "^12.0.0", - "eslint-plugin-flowtype": "^2.20.0", - "eslint-plugin-import": "^2.0.1", - "eslint-plugin-jsx-a11y": "^2.2.3", - "eslint-plugin-react": "^6.4.1", - "flow-bin": "^0.55.0", + "eslint": "^4.11.0", + "eslint-config-airbnb": "^16.1.0", + "eslint-plugin-flowtype": "^2.39.1", + "eslint-plugin-import": "^2.8.0", + "eslint-plugin-jsx-a11y": "^6.0.2", + "eslint-plugin-react": "^7.4.0", + "flow-bin": "^0.56.0", "react": "^16.0.0", "react-dom": "^16.0.0", "react-native": "^0.48.0", diff --git a/tests/ios/Podfile.lock b/tests/ios/Podfile.lock index 2d2e60bb..f6bb69d9 100644 --- a/tests/ios/Podfile.lock +++ b/tests/ios/Podfile.lock @@ -208,7 +208,7 @@ SPEC CHECKSUMS: nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3 Protobuf: 03eef2ee0b674770735cf79d9c4d3659cf6908e8 React: cf892fb84b7d06bf5fea7f328e554c6dcabe85ee - RNFirebase: a76befd482c5e84df7f69893358abda498ee9f76 + RNFirebase: 1b8adf4dfe740fbc4a69a147715c2edfd041eb92 yoga: 3abf02d6d9aeeb139b4c930eb1367feae690a35a PODFILE CHECKSUM: b5674be55653f5dda937c8b794d0479900643d45 diff --git a/tests/ios/ReactNativeFirebaseDemo.xcodeproj/project.pbxproj b/tests/ios/ReactNativeFirebaseDemo.xcodeproj/project.pbxproj index 1a7dddfc..c1c8a35d 100644 --- a/tests/ios/ReactNativeFirebaseDemo.xcodeproj/project.pbxproj +++ b/tests/ios/ReactNativeFirebaseDemo.xcodeproj/project.pbxproj @@ -1033,7 +1033,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; 6AE1012F46FF8A4D1D818A12 /* [CP] Copy Pods Resources */ = { From c4d77046236bba5f208579bca19b5d84a7ccfcf0 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 17 Nov 2017 11:08:04 +0000 Subject: [PATCH 04/56] [types] Missing firestore file --- lib/modules/firestore/Query.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/modules/firestore/Query.js b/lib/modules/firestore/Query.js index 912e4463..26bd0b22 100644 --- a/lib/modules/firestore/Query.js +++ b/lib/modules/firestore/Query.js @@ -2,11 +2,11 @@ * @flow * Query representation wrapper */ +import DocumentSnapshot from './DocumentSnapshot'; import QuerySnapshot from './QuerySnapshot'; import { buildNativeArray, buildTypeMap } from './utils/serialize'; import { firestoreAutoId, isFunction, isObject } from '../../utils'; -import type DocumentSnapshot from './DocumentSnapshot'; import type Firestore from './'; import type Path from './Path'; From f1d8bee5b027dc216987ab98b929f625618c424f Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 17 Nov 2017 11:22:10 +0000 Subject: [PATCH 05/56] [auth] Temp rename to allow capitalisation --- lib/modules/auth/{user.js => Usera.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/modules/auth/{user.js => Usera.js} (100%) diff --git a/lib/modules/auth/user.js b/lib/modules/auth/Usera.js similarity index 100% rename from lib/modules/auth/user.js rename to lib/modules/auth/Usera.js From 746faad0439ea8761787f8addf554732595910ec Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 17 Nov 2017 14:22:46 +0000 Subject: [PATCH 06/56] [types] Start on auth flow typings --- lib/firebase.js | 9 - lib/flow.js | 75 ++++-- lib/modules/auth/ConfirmationResult.js | 18 +- lib/modules/auth/PhoneAuthListener.js | 5 +- lib/modules/auth/{Usera.js => User.js} | 240 +++++++++--------- lib/modules/auth/index.js | 62 +++-- .../auth/providers/EmailAuthProvider.js | 8 +- .../auth/providers/FacebookAuthProvider.js | 8 +- .../auth/providers/GithubAuthProvider.js | 8 +- .../auth/providers/GoogleAuthProvider.js | 8 +- .../auth/providers/PhoneAuthProvider.js | 8 +- .../auth/providers/TwitterAuthProvider.js | 8 +- lib/modules/firestore/CollectionReference.js | 6 +- lib/modules/firestore/DocumentChange.js | 12 +- lib/modules/firestore/DocumentReference.js | 10 +- lib/modules/firestore/DocumentSnapshot.js | 19 +- lib/modules/firestore/Query.js | 10 +- lib/modules/firestore/QuerySnapshot.js | 14 +- lib/modules/firestore/WriteBatch.js | 4 +- lib/modules/firestore/utils/serialize.js | 17 +- 20 files changed, 296 insertions(+), 253 deletions(-) rename lib/modules/auth/{Usera.js => User.js} (52%) diff --git a/lib/firebase.js b/lib/firebase.js index 48df2287..917df680 100644 --- a/lib/firebase.js +++ b/lib/firebase.js @@ -24,15 +24,6 @@ import Utils, { statics as UtilsStatics } from './modules/utils'; const FirebaseCoreModule = NativeModules.RNFirebase; -export type FirebaseOptions = { - apiKey: string, - appId: string, - databaseURL: string, - messagingSenderId: string, - projectId: string, - storageBucket: string, -} - class FirebaseCore { _nativeEmitters: { [string]: NativeEventEmitter }; _nativeSubscriptions: { [string]: boolean }; diff --git a/lib/flow.js b/lib/flow.js index f5295758..71c478e8 100644 --- a/lib/flow.js +++ b/lib/flow.js @@ -1,20 +1,39 @@ /* eslint-disable */ -// declare module 'react-native' { -// // noinspection ES6ConvertVarToLetConst -// declare var exports: any; -// } +/* Core types */ +declare class FirebaseError { + message: string, + name: string, + code: string, + stack: string, + path: string, + details: string, + modifiers: string +}; -declare type AuthResultType = { +declare type FirebaseOptions = { + apiKey: string, + appId: string, + databaseURL: string, + messagingSenderId: string, + projectId: string, + storageBucket: string, +} + +/* Auth types */ + +declare type AuthResult = { authenticated: boolean, user: Object|null } | null; -declare type CredentialType = { +declare type AuthCredential = { providerId: string, token: string, secret: string }; +/* Database types */ + declare type DatabaseListener = { listenerId: number; eventName: string; @@ -31,6 +50,40 @@ declare type DatabaseModifier = { valueType?: string; }; +/* Firestore types */ + +declare type FirestoreNativeDocumentChange = { + document: FirestoreNativeDocumentSnapshot, + newIndex: number, + oldIndex: number, + type: string, +} + +declare type FirestoreNativeDocumentSnapshot = { + data: { [string]: FirestoreTypeMap }, + metadata: FirestoreSnapshotMetadata, + path: string, +} + +declare type FirestoreSnapshotMetadata = { + fromCache: boolean, + hasPendingWrites: boolean, +} + +declare type FirestoreQueryDirection = 'DESC' | 'desc' | 'ASC' | 'asc'; +declare type FirestoreQueryOperator = '<' | '<=' | '=' | '==' | '>' | '>='; + +declare type FirestoreTypeMap = { + type: 'array' | 'boolean' | 'date' | 'fieldvalue' | 'geopoint' | 'null' | 'number' | 'object' | 'reference' | 'string', + value: any, +} + +declare type FirestoreWriteOptions = { + merge?: boolean, +} + +/* Util types */ + declare type GoogleApiAvailabilityType = { status: number, isAvailable: boolean, @@ -38,13 +91,3 @@ declare type GoogleApiAvailabilityType = { hasResolution?: boolean, error?: string }; - -declare class FirebaseError { - message: string, - name: string, - code: string, - stack: string, - path: string, - details: string, - modifiers: string -}; diff --git a/lib/modules/auth/ConfirmationResult.js b/lib/modules/auth/ConfirmationResult.js index 0c1c09b3..a2b80b72 100644 --- a/lib/modules/auth/ConfirmationResult.js +++ b/lib/modules/auth/ConfirmationResult.js @@ -1,8 +1,12 @@ /** - * @url https://firebase.google.com/docs/reference/js/firebase.User + * @flow + * ConfirmationResult representation wrapper */ +import type Auth from './'; +import type User from './User'; + export default class ConfirmationResult { - _auth: Object; + _auth: Auth; _verificationId: string; /** @@ -10,7 +14,7 @@ export default class ConfirmationResult { * @param auth * @param verificationId The phone number authentication operation's verification ID. */ - constructor(auth: Object, verificationId: string) { + constructor(auth: Auth, verificationId: string) { this._auth = auth; this._verificationId = verificationId; } @@ -20,13 +24,11 @@ export default class ConfirmationResult { * @param verificationCode * @return {*} */ - confirm(verificationCode: string): Promise { - return this._auth._interceptUserValue( - this._auth._native._confirmVerificationCode(verificationCode) - ); + confirm(verificationCode: string): Promise { + return this._auth._interceptUserValue(this._auth._native._confirmVerificationCode(verificationCode)); } - get verificationId(): String | null { + get verificationId(): string | null { return this._verificationId; } } diff --git a/lib/modules/auth/PhoneAuthListener.js b/lib/modules/auth/PhoneAuthListener.js index 620ad7f1..170aa370 100644 --- a/lib/modules/auth/PhoneAuthListener.js +++ b/lib/modules/auth/PhoneAuthListener.js @@ -2,6 +2,8 @@ import INTERNALS from './../../internals'; import { generatePushID, isFunction, isAndroid, isIOS, isString, nativeToJSError } from './../../utils'; +import type Auth from './'; + type PhoneAuthSnapshot = { state: 'sent' | 'timeout' | 'verified' | 'error', verificationId: string, @@ -17,7 +19,6 @@ type PhoneAuthError = { }; export default class PhoneAuthListener { - _auth: Object; _timeout: number; _publicEvents: Object; @@ -34,7 +35,7 @@ export default class PhoneAuthListener { * @param phoneNumber * @param timeout */ - constructor(auth: Object, phoneNumber: string, timeout?: number) { + constructor(auth: Auth, phoneNumber: string, timeout?: number) { this._auth = auth; this._reject = null; this._resolve = null; diff --git a/lib/modules/auth/Usera.js b/lib/modules/auth/User.js similarity index 52% rename from lib/modules/auth/Usera.js rename to lib/modules/auth/User.js index 50cbb024..026ce93d 100644 --- a/lib/modules/auth/Usera.js +++ b/lib/modules/auth/User.js @@ -1,104 +1,144 @@ +/** + * @flow + * User representation wrapper + */ import INTERNALS from './../../internals'; -/** - * @url https://firebase.google.com/docs/reference/js/firebase.User - */ +import type Auth from './'; + +type NativeUser = { + displayName?: string, + email?: string, + emailVerified?: boolean, + isAnonymous?: boolean, + phoneNumber?: string, + photoURL?: string, + providerData: UserInfo[], + providerId: string, + uid: string, +} + +type UserInfo = { + displayName?: string, + email?: string, + phoneNumber?: string, + photoURL?: string, + providerId: string, + uid: string, +} + export default class User { + _auth: Auth; + _user: NativeUser; + /** * - * @param authClass Instance of Authentication class + * @param auth Instance of Authentication class * @param user user result object from native */ - constructor(authClass, userObj) { - this._auth = authClass; - this._user = userObj; - } - - /** - * INTERNALS - */ - - /** - * Returns a user property or null if does not exist - * @param prop - * @returns {*} - * @private - */ - _valueOrNull(prop) { - if (!Object.hasOwnProperty.call(this._user, prop)) return null; - return this._user[prop]; - } - - /** - * Returns a user property or false if does not exist - * @param prop - * @returns {*} - * @private - */ - _valueOrFalse(prop) { - if (!Object.hasOwnProperty.call(this._user, prop)) return false; - return this._user[prop]; + constructor(auth: Auth, user: NativeUser) { + this._auth = auth; + this._user = user; } /** * PROPERTIES */ - get displayName(): String | null { - return this._valueOrNull('displayName'); + get displayName(): ?string { + return this._user.displayName || null; } - get email(): String | null { - return this._valueOrNull('email'); + get email(): ?string { + return this._user.email || null; } - get emailVerified(): Boolean { - return this._valueOrNull('emailVerified'); + get emailVerified(): boolean { + return this._user.emailVerified || false; } - get isAnonymous(): Boolean { - return this._valueOrFalse('isAnonymous'); + get isAnonymous(): boolean { + return this._user.isAnonymous || false; } - get phoneNumber(): String | null { - return this._valueOrNull('phoneNumber'); + get phoneNumber(): ?string { + return this._user.phoneNumber || null; } - get photoURL(): String | null { - return this._valueOrNull('photoURL'); + get photoURL(): ?string { + return this._user.photoURL || null; } - get providerId() { - return this._valueOrNull('providerId'); + get providerData(): Array { + return this._user.providerData; } - get uid(): String { - return this._valueOrNull('uid'); + get providerId(): string { + return this._user.providerId; + } + + get uid(): string { + return this._user.uid; } - // noinspection ReservedWordAsName /** * METHODS */ - toJSON() { - return Object.assign({}, this._user); - } - /** * Delete the current user * @return {Promise} */ - delete(): Promise { - return this._auth._interceptUserValue(this._auth._native.delete()); + delete(): Promise { + return this._auth + ._interceptUndefinedUserValue(this._auth._native.delete()); + } + + /** + * get the token of current user + * @return {Promise} + */ + getIdToken(forceRefresh: boolean = false): Promise { + return this._auth._native.getToken(forceRefresh); } /** * * @param credential */ - linkWithCredential(credential: CredentialType) { - return this._auth._interceptUserValue(this._auth._native.link(credential.providerId, credential.token, credential.secret)); + linkWithCredential(credential: AuthCredential): Promise { + return this._auth + ._interceptUserValue(this._auth._native.link(credential.providerId, credential.token, credential.secret)); + } + + /** + * Re-authenticate a user with a third-party authentication provider + * @return {Promise} A promise resolved upon completion + */ + reauthenticateWithCredential(credential: AuthCredential): Promise { + return this._auth + ._interceptUndefinedUserValue(this._auth._native.reauthenticate(credential.providerId, credential.token, credential.secret)); + } + + /** + * Reload the current user + * @return {Promise} + */ + reload(): Promise { + return this._auth + ._interceptUndefinedUserValue(this._auth._native.reload()); + } + + /** + * Send verification email to current user. + */ + sendEmailVerification(): Promise { + return this._auth + ._interceptUndefinedUserValue(this._auth._native.sendEmailVerification()); + } + + toJSON(): Object { + return Object.assign({}, this._user); } /** @@ -106,69 +146,19 @@ export default class User { * @param providerId * @return {Promise.|*} */ - unlink(providerId: string) { + unlink(providerId: string): Promise { return this._auth._interceptUserValue(this._auth._native.unlink(providerId)); } - /** - * Re-authenticate a user with a third-party authentication provider - * @return {Promise} A promise resolved upon completion - */ - reauthenticateWithCredential(credential: CredentialType) { - return this._auth._interceptUserValue(this._auth._native.reauthenticate(credential.providerId, credential.token, credential.secret)); - } - - /** - * Reload the current user - * @return {Promise} - */ - reload(): Promise { - return this._auth._interceptUserValue(this._auth._native.reload()); - } - - /** - * get the token of current user - * @deprecated Deprecated getToken in favor of getIdToken. - * @return {Promise} - */ - getToken(forceRefresh: Boolean = false): Promise { - console.warn('Deprecated firebase.User.prototype.getToken in favor of firebase.User.prototype.getIdToken.'); - return this._auth._native.getToken(forceRefresh); - } - - /** - * get the token of current user - * @return {Promise} - */ - getIdToken(forceRefresh: Boolean = false): Promise { - return this._auth._native.getToken(forceRefresh); - } - - /** - * - * @returns {Array} - */ - get providerData(): Array { - return this._valueOrNull('providerData') || []; - } - /** * Update the current user's email * * @param {string} email The user's _new_ email * @return {Promise} A promise resolved upon completion */ - updateEmail(email: string): Promise { - return this._auth._interceptUserValue(this._auth._native.updateEmail(email)); - } - - /** - * Update the current user's profile - * @param {Object} updates An object containing the keys listed [here](https://firebase.google.com/docs/auth/ios/manage-users#update_a_users_profile) - * @return {Promise} - */ - updateProfile(updates: Object = {}): Promise { - return this._auth._interceptUserValue(this._auth._native.updateProfile(updates)); + updateEmail(email: string): Promise { + return this._auth + ._interceptUndefinedUserValue(this._auth._native.updateEmail(email)); } /** @@ -176,15 +166,29 @@ export default class User { * @param {string} password the new password * @return {Promise} */ - updatePassword(password: string): Promise { - return this._auth._interceptUserValue(this._auth._native.updatePassword(password)); + updatePassword(password: string): Promise { + return this._auth + ._interceptUndefinedUserValue(this._auth._native.updatePassword(password)); } /** - * Send verification email to current user. + * Update the current user's profile + * @param {Object} updates An object containing the keys listed [here](https://firebase.google.com/docs/auth/ios/manage-users#update_a_users_profile) + * @return {Promise} */ - sendEmailVerification(): Promise { - return this._auth._interceptUserValue(this._auth._native.sendEmailVerification()); + updateProfile(updates: Object = {}): Promise { + return this._auth + ._interceptUndefinedUserValue(this._auth._native.updateProfile(updates)); + } + + /** + * get the token of current user + * @deprecated Deprecated getToken in favor of getIdToken. + * @return {Promise} + */ + getToken(forceRefresh: boolean = false): Promise { + console.warn('Deprecated firebase.User.prototype.getToken in favor of firebase.User.prototype.getIdToken.'); + return this._auth._native.getToken(forceRefresh); } /** @@ -223,7 +227,7 @@ export default class User { throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('User', 'updatePhoneNumber')); } - get refreshToken() { + get refreshToken(): string { throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_PROPERTY('User', 'refreshToken')); } } diff --git a/lib/modules/auth/index.js b/lib/modules/auth/index.js index 378a23aa..fcd42b59 100644 --- a/lib/modules/auth/index.js +++ b/lib/modules/auth/index.js @@ -1,5 +1,8 @@ -// @flow -import User from './user'; +/** + * @flow + * Auth representation wrapper + */ +import User from './User'; import ModuleBase from './../../utils/ModuleBase'; import INTERNALS from './../../internals'; import ConfirmationResult from './ConfirmationResult'; @@ -14,16 +17,16 @@ import FacebookAuthProvider from './providers/FacebookAuthProvider'; import PhoneAuthListener from './PhoneAuthListener'; +import type FirebaseApp from '../../firebase-app'; + export default class Auth extends ModuleBase { static _NAMESPACE = 'auth'; static _NATIVE_MODULE = 'RNFirebaseAuth'; + _authResult: AuthResult | null; _user: User | null; - _native: Object; - _getAppEventName: Function; - _authResult: AuthResultType | null; - constructor(firebaseApp: Object, options: Object = {}) { + constructor(firebaseApp: FirebaseApp, options: Object = {}) { super(firebaseApp, options, true); this._user = null; this._authResult = null; @@ -31,21 +34,21 @@ export default class Auth extends ModuleBase { this.addListener( // sub to internal native event - this fans out to // public event name: onAuthStateChanged - this._getAppEventName('auth_state_changed'), + super._getAppEventName('auth_state_changed'), this._onInternalAuthStateChanged.bind(this), ); this.addListener( // sub to internal native event - this fans out to // public events based on event.type - this._getAppEventName('phone_auth_state_changed'), + super._getAppEventName('phone_auth_state_changed'), this._onInternalPhoneAuthStateChanged.bind(this), ); this.addListener( // sub to internal native event - this fans out to // public event name: onIdTokenChanged - this._getAppEventName('auth_id_token_changed'), + super._getAppEventName('auth_id_token_changed'), this._onInternalIdTokenChanged.bind(this), ); @@ -63,7 +66,7 @@ export default class Auth extends ModuleBase { this.emit(eventKey, event.state); } - _setAuthState(auth: AuthResultType) { + _setAuthState(auth: AuthResult) { this._authResult = auth; this._user = auth && auth.user ? new User(this, auth.user) : null; this.emit(this._getAppEventName('onUserChanged'), this._user); @@ -74,7 +77,7 @@ export default class Auth extends ModuleBase { * @param auth * @private */ - _onInternalAuthStateChanged(auth: AuthResultType) { + _onInternalAuthStateChanged(auth: AuthResult) { this._setAuthState(auth); this.emit(this._getAppEventName('onAuthStateChanged'), this._user); } @@ -85,7 +88,7 @@ export default class Auth extends ModuleBase { * @param emit * @private */ - _onInternalIdTokenChanged(auth: AuthResultType) { + _onInternalIdTokenChanged(auth: AuthResult) { this._setAuthState(auth); this.emit(this._getAppEventName('onIdTokenChanged'), this._user); } @@ -97,8 +100,8 @@ export default class Auth extends ModuleBase { * @returns {Promise.<*>} * @private */ - _interceptUserValue(promise) { - return promise.then((result) => { + _interceptUserValue(promise: Promise): Promise { + return promise.then((result: AuthResult) => { if (!result) this._setAuthState(null); else if (result.user) this._setAuthState(result); else if (result.uid) this._setAuthState({ authenticated: true, user: result }); @@ -106,6 +109,11 @@ export default class Auth extends ModuleBase { }); } + _interceptUndefinedUserValue(promise: Promise): Promise { + return this._interceptUserValue(promise) + .then(() => {}); + } + /* * WEB API */ @@ -174,15 +182,15 @@ export default class Auth extends ModuleBase { * Sign the current user out * @return {Promise} */ - signOut(): Promise { - return this._interceptUserValue(this._native.signOut()); + signOut(): Promise { + return this._interceptUndefinedUserValue(this._native.signOut()); } /** * Sign a user in anonymously * @return {Promise} A promise resolved upon completion */ - signInAnonymously(): Promise { + signInAnonymously(): Promise { return this._interceptUserValue(this._native.signInAnonymously()); } @@ -192,7 +200,7 @@ export default class Auth extends ModuleBase { * @param {string} password The user's password * @return {Promise} A promise indicating the completion */ - createUserWithEmailAndPassword(email: string, password: string): Promise { + createUserWithEmailAndPassword(email: string, password: string): Promise { return this._interceptUserValue(this._native.createUserWithEmailAndPassword(email, password)); } @@ -202,7 +210,7 @@ export default class Auth extends ModuleBase { * @param {string} password The user's password * @return {Promise} A promise that is resolved upon completion */ - signInWithEmailAndPassword(email: string, password: string): Promise { + signInWithEmailAndPassword(email: string, password: string): Promise { return this._interceptUserValue(this._native.signInWithEmailAndPassword(email, password)); } @@ -211,7 +219,7 @@ export default class Auth extends ModuleBase { * @param {string} customToken A self-signed custom auth token. * @return {Promise} A promise resolved upon completion */ - signInWithCustomToken(customToken: string): Promise { + signInWithCustomToken(customToken: string): Promise { return this._interceptUserValue(this._native.signInWithCustomToken(customToken)); } @@ -219,7 +227,7 @@ export default class Auth extends ModuleBase { * Sign the user in with a third-party authentication provider * @return {Promise} A promise resolved upon completion */ - signInWithCredential(credential: CredentialType): Promise { + signInWithCredential(credential: AuthCredential): Promise { return this._interceptUserValue( this._native.signInWithCredential( credential.providerId, credential.token, credential.secret, @@ -231,7 +239,7 @@ export default class Auth extends ModuleBase { * Asynchronously signs in using a phone number. * */ - signInWithPhoneNumber(phoneNumber: string): Promise { + signInWithPhoneNumber(phoneNumber: string): Promise { return this._native.signInWithPhoneNumber(phoneNumber).then((result) => { return new ConfirmationResult(this, result.verificationId); }); @@ -254,7 +262,7 @@ export default class Auth extends ModuleBase { * Send reset password instructions via email * @param {string} email The email to send password reset instructions */ - sendPasswordResetEmail(email: string): Promise { + sendPasswordResetEmail(email: string): Promise { return this._native.sendPasswordResetEmail(email); } @@ -266,7 +274,7 @@ export default class Auth extends ModuleBase { * @param newPassword * @return {Promise.} */ - confirmPasswordReset(code: string, newPassword: string): Promise { + confirmPasswordReset(code: string, newPassword: string): Promise { return this._native.confirmPasswordReset(code, newPassword); } @@ -277,7 +285,7 @@ export default class Auth extends ModuleBase { * @param code * @return {Promise.} */ - applyActionCode(code: string): Promise { + applyActionCode(code: string): Promise { return this._native.applyActionCode(code); } @@ -288,7 +296,7 @@ export default class Auth extends ModuleBase { * @param code * @return {Promise.|Promise} */ - checkActionCode(code: string): Promise { + checkActionCode(code: string): Promise { return this._native.checkActionCode(code); } @@ -296,7 +304,7 @@ export default class Auth extends ModuleBase { * Get the currently signed in user * @return {Promise} */ - getCurrentUser(): Promise { + getCurrentUser(): Promise { return this._interceptUserValue(this._native.getCurrentUser()); } diff --git a/lib/modules/auth/providers/EmailAuthProvider.js b/lib/modules/auth/providers/EmailAuthProvider.js index d4175aba..b995687f 100644 --- a/lib/modules/auth/providers/EmailAuthProvider.js +++ b/lib/modules/auth/providers/EmailAuthProvider.js @@ -1,3 +1,7 @@ +/** + * @flow + * EmailAuthProvider representation wrapper + */ const providerId = 'password'; export default class EmailAuthProvider { @@ -5,11 +9,11 @@ export default class EmailAuthProvider { throw new Error('`new EmailAuthProvider()` is not supported on the native Firebase SDKs.'); } - static get PROVIDER_ID() { + static get PROVIDER_ID(): string { return providerId; } - static credential(email, password) { + static credential(email: string, password: string): AuthCredential { return { token: email, secret: password, diff --git a/lib/modules/auth/providers/FacebookAuthProvider.js b/lib/modules/auth/providers/FacebookAuthProvider.js index c8abbc10..b60bf027 100644 --- a/lib/modules/auth/providers/FacebookAuthProvider.js +++ b/lib/modules/auth/providers/FacebookAuthProvider.js @@ -1,3 +1,7 @@ +/** + * @flow + * FacebookAuthProvider representation wrapper + */ const providerId = 'facebook.com'; export default class FacebookAuthProvider { @@ -5,11 +9,11 @@ export default class FacebookAuthProvider { throw new Error('`new FacebookAuthProvider()` is not supported on the native Firebase SDKs.'); } - static get PROVIDER_ID() { + static get PROVIDER_ID(): string { return providerId; } - static credential(token) { + static credential(token: string): AuthCredential { return { token, secret: '', diff --git a/lib/modules/auth/providers/GithubAuthProvider.js b/lib/modules/auth/providers/GithubAuthProvider.js index fbd84272..4500ce40 100644 --- a/lib/modules/auth/providers/GithubAuthProvider.js +++ b/lib/modules/auth/providers/GithubAuthProvider.js @@ -1,3 +1,7 @@ +/** + * @flow + * GithubAuthProvider representation wrapper + */ const providerId = 'github.com'; export default class GithubAuthProvider { @@ -5,11 +9,11 @@ export default class GithubAuthProvider { throw new Error('`new GithubAuthProvider()` is not supported on the native Firebase SDKs.'); } - static get PROVIDER_ID() { + static get PROVIDER_ID(): string { return providerId; } - static credential(token) { + static credential(token: string): AuthCredential { return { token, secret: '', diff --git a/lib/modules/auth/providers/GoogleAuthProvider.js b/lib/modules/auth/providers/GoogleAuthProvider.js index eda9f241..717aa0ce 100644 --- a/lib/modules/auth/providers/GoogleAuthProvider.js +++ b/lib/modules/auth/providers/GoogleAuthProvider.js @@ -1,3 +1,7 @@ +/** + * @flow + * EmailAuthProvider representation wrapper + */ const providerId = 'google.com'; export default class GoogleAuthProvider { @@ -5,11 +9,11 @@ export default class GoogleAuthProvider { throw new Error('`new GoogleAuthProvider()` is not supported on the native Firebase SDKs.'); } - static get PROVIDER_ID() { + static get PROVIDER_ID(): string { return providerId; } - static credential(token, secret) { + static credential(token: string, secret: string): AuthCredential { return { token, secret, diff --git a/lib/modules/auth/providers/PhoneAuthProvider.js b/lib/modules/auth/providers/PhoneAuthProvider.js index 5186f009..6ac1cc57 100644 --- a/lib/modules/auth/providers/PhoneAuthProvider.js +++ b/lib/modules/auth/providers/PhoneAuthProvider.js @@ -1,3 +1,7 @@ +/** + * @flow + * PhoneAuthProvider representation wrapper + */ const providerId = 'phone'; export default class PhoneAuthProvider { @@ -5,11 +9,11 @@ export default class PhoneAuthProvider { throw new Error('`new PhoneAuthProvider()` is not supported on the native Firebase SDKs.'); } - static get PROVIDER_ID() { + static get PROVIDER_ID(): string { return providerId; } - static credential(verificationId, code) { + static credential(verificationId: string, code: string): AuthCredential { return { token: verificationId, secret: code, diff --git a/lib/modules/auth/providers/TwitterAuthProvider.js b/lib/modules/auth/providers/TwitterAuthProvider.js index 15c0a2f6..7f6cf902 100644 --- a/lib/modules/auth/providers/TwitterAuthProvider.js +++ b/lib/modules/auth/providers/TwitterAuthProvider.js @@ -1,3 +1,7 @@ +/** + * @flow + * TwitterAuthProvider representation wrapper + */ const providerId = 'twitter.com'; export default class TwitterAuthProvider { @@ -5,11 +9,11 @@ export default class TwitterAuthProvider { throw new Error('`new TwitterAuthProvider()` is not supported on the native Firebase SDKs.'); } - static get PROVIDER_ID() { + static get PROVIDER_ID(): string { return providerId; } - static credential(token, secret) { + static credential(token: string, secret: string): AuthCredential { return { token, secret, diff --git a/lib/modules/firestore/CollectionReference.js b/lib/modules/firestore/CollectionReference.js index 9c46eda2..6a906be9 100644 --- a/lib/modules/firestore/CollectionReference.js +++ b/lib/modules/firestore/CollectionReference.js @@ -3,7 +3,7 @@ * CollectionReference representation wrapper */ import DocumentReference from './DocumentReference'; -import Query, { type Direction, type Operator } from './Query'; +import Query from './Query'; import { firestoreAutoId } from '../../utils'; import type Firestore from './'; @@ -75,7 +75,7 @@ export default class CollectionReference { return this._query.onSnapshot(onNext, onError); } - orderBy(fieldPath: string, directionStr?: Direction): Query { + orderBy(fieldPath: string, directionStr?: FirestoreQueryDirection): Query { return this._query.orderBy(fieldPath, directionStr); } @@ -87,7 +87,7 @@ export default class CollectionReference { return this._query.startAt(fieldValues); } - where(fieldPath: string, opStr: Operator, value: any): Query { + where(fieldPath: string, opStr: FirestoreQueryOperator, value: any): Query { return this._query.where(fieldPath, opStr, value); } } diff --git a/lib/modules/firestore/DocumentChange.js b/lib/modules/firestore/DocumentChange.js index b712aa7a..ffcda39d 100644 --- a/lib/modules/firestore/DocumentChange.js +++ b/lib/modules/firestore/DocumentChange.js @@ -2,18 +2,10 @@ * @flow * DocumentChange representation wrapper */ -import DocumentSnapshot, { type DocumentSnapshotNativeData } from './DocumentSnapshot'; +import DocumentSnapshot from './DocumentSnapshot'; import type Firestore from './'; - -export type DocumentChangeNativeData = { - document: DocumentSnapshotNativeData, - newIndex: number, - oldIndex: number, - type: string, -} - /** * @class DocumentChange */ @@ -23,7 +15,7 @@ export default class DocumentChange { _oldIndex: number; _type: string; - constructor(firestore: Firestore, nativeData: DocumentChangeNativeData) { + constructor(firestore: Firestore, nativeData: FirestoreNativeDocumentChange) { this._document = new DocumentSnapshot(firestore, nativeData.document); this._newIndex = nativeData.newIndex; this._oldIndex = nativeData.oldIndex; diff --git a/lib/modules/firestore/DocumentReference.js b/lib/modules/firestore/DocumentReference.js index b6a703ed..aff4d304 100644 --- a/lib/modules/firestore/DocumentReference.js +++ b/lib/modules/firestore/DocumentReference.js @@ -3,17 +3,13 @@ * DocumentReference representation wrapper */ import CollectionReference from './CollectionReference'; -import DocumentSnapshot, { type DocumentSnapshotNativeData } from './DocumentSnapshot'; +import DocumentSnapshot from './DocumentSnapshot'; import { buildNativeMap } from './utils/serialize'; import { firestoreAutoId, isFunction, isObject, isString } from '../../utils'; import type Firestore from './'; import type Path from './Path'; -export type WriteOptions = { - merge?: boolean, -} - type DocumentListenOptions = { includeMetadataChanges: boolean, } @@ -133,7 +129,7 @@ export default class DocumentReference { } const listenerId = firestoreAutoId(); - const listener = (nativeDocumentSnapshot: DocumentSnapshotNativeData) => { + const listener = (nativeDocumentSnapshot: FirestoreNativeDocumentSnapshot) => { const documentSnapshot = new DocumentSnapshot(this.firestore, nativeDocumentSnapshot); observer.next(documentSnapshot); }; @@ -160,7 +156,7 @@ export default class DocumentReference { return this._offDocumentSnapshot.bind(this, listenerId, listener); } - set(data: Object, writeOptions?: WriteOptions): Promise { + set(data: Object, writeOptions?: FirestoreWriteOptions): Promise { const nativeData = buildNativeMap(data); return this._firestore._native .documentSet(this.path, nativeData, writeOptions); diff --git a/lib/modules/firestore/DocumentSnapshot.js b/lib/modules/firestore/DocumentSnapshot.js index 35899c47..ab2bb378 100644 --- a/lib/modules/firestore/DocumentSnapshot.js +++ b/lib/modules/firestore/DocumentSnapshot.js @@ -4,30 +4,19 @@ */ import DocumentReference from './DocumentReference'; import Path from './Path'; -import { parseNativeMap, type TypeMap } from './utils/serialize'; +import { parseNativeMap } from './utils/serialize'; import type Firestore from './'; -export type SnapshotMetadata = { - fromCache: boolean, - hasPendingWrites: boolean, -} - -export type DocumentSnapshotNativeData = { - data: { [string]: TypeMap }, - metadata: SnapshotMetadata, - path: string, -} - /** * @class DocumentSnapshot */ export default class DocumentSnapshot { _data: Object | void; - _metadata: SnapshotMetadata; + _metadata: FirestoreSnapshotMetadata; _ref: DocumentReference; - constructor(firestore: Firestore, nativeData: DocumentSnapshotNativeData) { + constructor(firestore: Firestore, nativeData: FirestoreNativeDocumentSnapshot) { this._data = parseNativeMap(firestore, nativeData.data); this._metadata = nativeData.metadata; this._ref = new DocumentReference(firestore, Path.fromName(nativeData.path)); @@ -41,7 +30,7 @@ export default class DocumentSnapshot { return this._ref.id; } - get metadata(): SnapshotMetadata { + get metadata(): FirestoreSnapshotMetadata { return this._metadata; } diff --git a/lib/modules/firestore/Query.js b/lib/modules/firestore/Query.js index 26bd0b22..81561b47 100644 --- a/lib/modules/firestore/Query.js +++ b/lib/modules/firestore/Query.js @@ -10,14 +10,14 @@ import { firestoreAutoId, isFunction, isObject } from '../../utils'; import type Firestore from './'; import type Path from './Path'; -const DIRECTIONS = { +const DIRECTIONS: { [FirestoreQueryDirection]: string } = { ASC: 'ASCENDING', asc: 'ASCENDING', DESC: 'DESCENDING', desc: 'DESCENDING', }; -const OPERATORS = { +const OPERATORS: { [FirestoreQueryOperator]: string } = { '=': 'EQUAL', '==': 'EQUAL', '>': 'GREATER_THAN', @@ -26,7 +26,6 @@ const OPERATORS = { '<=': 'LESS_THAN_OR_EQUAL', }; -export type Direction = 'DESC' | 'desc' | 'ASC' | 'asc'; type FieldFilter = { fieldPath: string, operator: string, @@ -45,7 +44,6 @@ type QueryOptions = { startAfter?: any[], startAt?: any[], } -export type Operator = '<' | '<=' | '=' | '==' | '>' | '>='; type QueryListenOptions = { includeDocumentMetadataChanges: boolean, includeQueryMetadataChanges: boolean, @@ -234,7 +232,7 @@ export default class Query { return this._offCollectionSnapshot.bind(this, listenerId, listener); } - orderBy(fieldPath: string, directionStr?: Direction = 'asc'): Query { + orderBy(fieldPath: string, directionStr?: FirestoreQueryDirection = 'asc'): Query { // TODO: Validation // validate.isFieldPath('fieldPath', fieldPath); // validate.isOptionalFieldOrder('directionStr', directionStr); @@ -288,7 +286,7 @@ export default class Query { ); } - where(fieldPath: string, opStr: Operator, value: any): Query { + where(fieldPath: string, opStr: FirestoreQueryOperator, value: any): Query { // TODO: Validation // validate.isFieldPath('fieldPath', fieldPath); // validate.isFieldFilter('fieldFilter', opStr, value); diff --git a/lib/modules/firestore/QuerySnapshot.js b/lib/modules/firestore/QuerySnapshot.js index c7759b22..659815aa 100644 --- a/lib/modules/firestore/QuerySnapshot.js +++ b/lib/modules/firestore/QuerySnapshot.js @@ -2,16 +2,16 @@ * @flow * QuerySnapshot representation wrapper */ -import DocumentChange, { type DocumentChangeNativeData } from './DocumentChange'; -import DocumentSnapshot, { type DocumentSnapshotNativeData, type SnapshotMetadata } from './DocumentSnapshot'; +import DocumentChange from './DocumentChange'; +import DocumentSnapshot from './DocumentSnapshot'; import type Firestore from './'; import type Query from './Query'; type QuerySnapshotNativeData = { - changes: DocumentChangeNativeData[], - documents: DocumentSnapshotNativeData[], - metadata: SnapshotMetadata, + changes: FirestoreNativeDocumentChange[], + documents: FirestoreNativeDocumentSnapshot[], + metadata: FirestoreSnapshotMetadata, } /** @@ -20,7 +20,7 @@ type QuerySnapshotNativeData = { export default class QuerySnapshot { _changes: DocumentChange[]; _docs: DocumentSnapshot[]; - _metadata: SnapshotMetadata; + _metadata: FirestoreSnapshotMetadata; _query: Query; constructor(firestore: Firestore, query: Query, nativeData: QuerySnapshotNativeData) { @@ -42,7 +42,7 @@ export default class QuerySnapshot { return this._docs.length === 0; } - get metadata(): SnapshotMetadata { + get metadata(): FirestoreSnapshotMetadata { return this._metadata; } diff --git a/lib/modules/firestore/WriteBatch.js b/lib/modules/firestore/WriteBatch.js index 70771124..77318c3c 100644 --- a/lib/modules/firestore/WriteBatch.js +++ b/lib/modules/firestore/WriteBatch.js @@ -5,7 +5,7 @@ import { buildNativeMap } from './utils/serialize'; import { isObject, isString } from '../../utils'; -import type DocumentReference, { WriteOptions } from './DocumentReference'; +import type DocumentReference from './DocumentReference'; import type Firestore from './'; type DocumentWrite = { @@ -44,7 +44,7 @@ export default class WriteBatch { return this; } - set(docRef: DocumentReference, data: Object, writeOptions?: WriteOptions) { + set(docRef: DocumentReference, data: Object, writeOptions?: FirestoreWriteOptions) { // TODO: Validation // validate.isDocumentReference('docRef', docRef); // validate.isDocument('data', data); diff --git a/lib/modules/firestore/utils/serialize.js b/lib/modules/firestore/utils/serialize.js index 4657711c..74fd2697 100644 --- a/lib/modules/firestore/utils/serialize.js +++ b/lib/modules/firestore/utils/serialize.js @@ -10,18 +10,13 @@ import { typeOf } from '../../../utils'; import type Firestore from '../'; -export type TypeMap = { - type: 'array' | 'boolean' | 'date' | 'fieldvalue' | 'geopoint' | 'null' | 'number' | 'object' | 'reference' | 'string', - value: any, -} - /* * Functions that build up the data needed to represent * the different types available within Firestore * for transmission to the native side */ -export const buildNativeMap = (data: Object): { [string]: TypeMap } => { +export const buildNativeMap = (data: Object): { [string]: FirestoreTypeMap } => { const nativeData = {}; if (data) { Object.keys(data).forEach((key) => { @@ -34,7 +29,7 @@ export const buildNativeMap = (data: Object): { [string]: TypeMap } => { return nativeData; }; -export const buildNativeArray = (array: Object[]): TypeMap[] => { +export const buildNativeArray = (array: Object[]): FirestoreTypeMap[] => { const nativeArray = []; if (array) { array.forEach((value) => { @@ -47,7 +42,7 @@ export const buildNativeArray = (array: Object[]): TypeMap[] => { return nativeArray; }; -export const buildTypeMap = (value: any): TypeMap | null => { +export const buildTypeMap = (value: any): FirestoreTypeMap | null => { const type = typeOf(value); if (value === null || value === undefined) { return { @@ -108,7 +103,7 @@ export const buildTypeMap = (value: any): TypeMap | null => { * side and converts to the correct Firestore JS types */ -export const parseNativeMap = (firestore: Firestore, nativeData: { [string]: TypeMap }): Object | void => { +export const parseNativeMap = (firestore: Firestore, nativeData: { [string]: FirestoreTypeMap }): Object | void => { let data; if (nativeData) { data = {}; @@ -119,7 +114,7 @@ export const parseNativeMap = (firestore: Firestore, nativeData: { [string]: Typ return data; }; -const parseNativeArray = (firestore: Firestore, nativeArray: TypeMap[]): any[] => { +const parseNativeArray = (firestore: Firestore, nativeArray: FirestoreTypeMap[]): any[] => { const array = []; if (nativeArray) { nativeArray.forEach((typeMap) => { @@ -129,7 +124,7 @@ const parseNativeArray = (firestore: Firestore, nativeArray: TypeMap[]): any[] = return array; }; -const parseTypeMap = (firestore: Firestore, typeMap: TypeMap): any => { +const parseTypeMap = (firestore: Firestore, typeMap: FirestoreTypeMap): any => { const { type, value } = typeMap; if (type === 'null') { return null; From fbe73f5dcb09715d3bbc7e4e127ac508a9bd3efe Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 17 Nov 2017 16:17:27 +0000 Subject: [PATCH 07/56] [types] Get types properly exporting as part of the build --- .babelrc | 15 +- .flowconfig | 5 +- .gitignore | 2 +- index.js | 5 - index.d.ts => lib/index.d.ts | 0 lib/index.js | 8 + lib/modules/auth/PhoneAuthListener.js | 2 +- lib/modules/auth/User.js | 2 +- lib/modules/auth/index.js | 6 +- lib/modules/base.js | 21 - lib/{ => modules/core}/firebase-app.js | 30 +- lib/{ => modules/core}/firebase.js | 28 +- lib/modules/database/reference.js | 2 +- lib/modules/firestore/index.js | 4 +- lib/modules/utils/index.js | 7 +- lib/{ => types}/flow.js | 0 lib/utils/ModuleBase.js | 10 +- lib/{ => utils}/internals.js | 6 +- package-lock.json | 1231 ++++++++++-------------- package.json | 26 +- 20 files changed, 588 insertions(+), 822 deletions(-) delete mode 100644 index.js rename index.d.ts => lib/index.d.ts (100%) create mode 100644 lib/index.js delete mode 100644 lib/modules/base.js rename lib/{ => modules/core}/firebase-app.js (85%) rename lib/{ => modules/core}/firebase.js (89%) rename lib/{ => types}/flow.js (100%) rename lib/{ => utils}/internals.js (98%) diff --git a/.babelrc b/.babelrc index a9ce1369..5e935db9 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,16 @@ { - "presets": ["react-native"] + "env": { + "development": { + "presets": ["react-native"], + "plugins": [ + "transform-flow-strip-types" + ] + }, + "publish": { + "presets": ["react-native-syntax"], + "plugins": [ + "transform-flow-strip-types" + ] + } + } } diff --git a/.flowconfig b/.flowconfig index fb97021d..e3db9bc6 100644 --- a/.flowconfig +++ b/.flowconfig @@ -73,11 +73,14 @@ .*/node_modules/protobufjs/src/bower.json .*/node_modules/grpc/node_modules/protobufjs/src/bower.json +# Ignore dist folder +.*/dist/.* + [include] node_modules/fbjs/lib [libs] -lib/flow.js +lib/types/flow.js node_modules/react-native/Libraries/react-native/react-native-interface.js node_modules/react-native/flow node_modules/fbjs/flow/lib diff --git a/.gitignore b/.gitignore index f65faa29..7a868226 100644 --- a/.gitignore +++ b/.gitignore @@ -76,4 +76,4 @@ local.properties **/ios/Pods/** **/ios/ReactNativeFirebaseDemo.xcworkspace/ - +dist diff --git a/index.js b/index.js deleted file mode 100644 index ffcd3583..00000000 --- a/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import Firebase from './lib/firebase'; - -export const AdMob = require('./lib/modules/admob'); - -export default Firebase; diff --git a/index.d.ts b/lib/index.d.ts similarity index 100% rename from index.d.ts rename to lib/index.d.ts diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 00000000..0d65d53e --- /dev/null +++ b/lib/index.js @@ -0,0 +1,8 @@ +/** + * @flow + */ +import Firebase from './modules/core/firebase'; + +export const AdMob = require('./modules/admob'); + +export default Firebase; diff --git a/lib/modules/auth/PhoneAuthListener.js b/lib/modules/auth/PhoneAuthListener.js index 170aa370..0848b080 100644 --- a/lib/modules/auth/PhoneAuthListener.js +++ b/lib/modules/auth/PhoneAuthListener.js @@ -1,5 +1,5 @@ // @flow -import INTERNALS from './../../internals'; +import INTERNALS from '../../utils/internals'; import { generatePushID, isFunction, isAndroid, isIOS, isString, nativeToJSError } from './../../utils'; import type Auth from './'; diff --git a/lib/modules/auth/User.js b/lib/modules/auth/User.js index 026ce93d..2fc7616e 100644 --- a/lib/modules/auth/User.js +++ b/lib/modules/auth/User.js @@ -2,7 +2,7 @@ * @flow * User representation wrapper */ -import INTERNALS from './../../internals'; +import INTERNALS from '../../utils/internals'; import type Auth from './'; diff --git a/lib/modules/auth/index.js b/lib/modules/auth/index.js index fcd42b59..a13f0e91 100644 --- a/lib/modules/auth/index.js +++ b/lib/modules/auth/index.js @@ -3,8 +3,8 @@ * Auth representation wrapper */ import User from './User'; -import ModuleBase from './../../utils/ModuleBase'; -import INTERNALS from './../../internals'; +import ModuleBase from '../../utils/ModuleBase'; +import INTERNALS from '../../utils/internals'; import ConfirmationResult from './ConfirmationResult'; // providers @@ -17,7 +17,7 @@ import FacebookAuthProvider from './providers/FacebookAuthProvider'; import PhoneAuthListener from './PhoneAuthListener'; -import type FirebaseApp from '../../firebase-app'; +import type FirebaseApp from '../core/firebase-app'; export default class Auth extends ModuleBase { static _NAMESPACE = 'auth'; diff --git a/lib/modules/base.js b/lib/modules/base.js deleted file mode 100644 index f1ea818f..00000000 --- a/lib/modules/base.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @flow - */ - -// todo move out -export class ReferenceBase extends Base { - constructor(path: string) { - super(); - this.path = path || '/'; - } - - /** - * The last part of a Reference's path (after the last '/') - * The key of a root Reference is null. - * @type {String} - * {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#key} - */ - get key(): string | null { - return this.path === '/' ? null : this.path.substring(this.path.lastIndexOf('/') + 1); - } -} diff --git a/lib/firebase-app.js b/lib/modules/core/firebase-app.js similarity index 85% rename from lib/firebase-app.js rename to lib/modules/core/firebase-app.js index 3fb2f09b..efa40c39 100644 --- a/lib/firebase-app.js +++ b/lib/modules/core/firebase-app.js @@ -3,23 +3,21 @@ */ import { NativeModules } from 'react-native'; -import INTERNALS from './internals'; -import { isObject, isAndroid } from './utils'; +import INTERNALS from '../../utils/internals'; +import { isObject, isAndroid } from '../../utils'; -import AdMob, { statics as AdMobStatics } from './modules/admob'; -import Auth, { statics as AuthStatics } from './modules/auth'; -import Analytics from './modules/analytics'; -import Crash from './modules/crash'; -import Performance from './modules/perf'; -import RemoteConfig from './modules/config'; -import Storage, { statics as StorageStatics } from './modules/storage'; -import Database, { statics as DatabaseStatics } from './modules/database'; -import Messaging, { statics as MessagingStatics } from './modules/messaging'; -import Firestore, { statics as FirestoreStatics } from './modules/firestore'; -import Links, { statics as LinksStatics } from './modules/links'; -import Utils, { statics as UtilsStatics } from './modules/utils'; - -import type { FirebaseOptions } from './firebase'; +import AdMob, { statics as AdMobStatics } from '../admob'; +import Auth, { statics as AuthStatics } from '../auth'; +import Analytics from '../analytics'; +import Crash from '../crash'; +import Performance from '../perf'; +import RemoteConfig from '../config'; +import Storage, { statics as StorageStatics } from '../storage'; +import Database, { statics as DatabaseStatics } from '../database'; +import Messaging, { statics as MessagingStatics } from '../messaging'; +import Firestore, { statics as FirestoreStatics } from '../firestore'; +import Links, { statics as LinksStatics } from '../links'; +import Utils, { statics as UtilsStatics } from '../utils'; const FirebaseCoreModule = NativeModules.RNFirebase; diff --git a/lib/firebase.js b/lib/modules/core/firebase.js similarity index 89% rename from lib/firebase.js rename to lib/modules/core/firebase.js index 917df680..b9a036f9 100644 --- a/lib/firebase.js +++ b/lib/modules/core/firebase.js @@ -4,23 +4,23 @@ */ import { NativeModules, NativeEventEmitter } from 'react-native'; -import INTERNALS from './internals'; +import INTERNALS from '../../utils/internals'; import FirebaseApp from './firebase-app'; -import { isObject, isString } from './utils'; +import { isObject, isString } from '../../utils'; // module imports -import AdMob, { statics as AdMobStatics } from './modules/admob'; -import Auth, { statics as AuthStatics } from './modules/auth'; -import Analytics from './modules/analytics'; -import Crash from './modules/crash'; -import Performance from './modules/perf'; -import Links, { statics as LinksStatics } from './modules/links'; -import RemoteConfig from './modules/config'; -import Storage, { statics as StorageStatics } from './modules/storage'; -import Database, { statics as DatabaseStatics } from './modules/database'; -import Messaging, { statics as MessagingStatics } from './modules/messaging'; -import Firestore, { statics as FirestoreStatics } from './modules/firestore'; -import Utils, { statics as UtilsStatics } from './modules/utils'; +import AdMob, { statics as AdMobStatics } from '../admob'; +import Auth, { statics as AuthStatics } from '../auth'; +import Analytics from '../analytics'; +import Crash from '../crash'; +import Performance from '../perf'; +import Links, { statics as LinksStatics } from '../links'; +import RemoteConfig from '../config'; +import Storage, { statics as StorageStatics } from '../storage'; +import Database, { statics as DatabaseStatics } from '../database'; +import Messaging, { statics as MessagingStatics } from '../messaging'; +import Firestore, { statics as FirestoreStatics } from '../firestore'; +import Utils, { statics as UtilsStatics } from '../utils'; const FirebaseCoreModule = NativeModules.RNFirebase; diff --git a/lib/modules/database/reference.js b/lib/modules/database/reference.js index ffb1af9f..c5ff9e2c 100644 --- a/lib/modules/database/reference.js +++ b/lib/modules/database/reference.js @@ -17,7 +17,7 @@ import { generatePushID, } from './../../utils'; -import INTERNALS from './../../internals'; +import INTERNALS from '../../utils/internals'; // track all event registrations by path let listeners = 0; diff --git a/lib/modules/firestore/index.js b/lib/modules/firestore/index.js index 3161cd03..b1270c97 100644 --- a/lib/modules/firestore/index.js +++ b/lib/modules/firestore/index.js @@ -9,10 +9,10 @@ import FieldValue from './FieldValue'; import GeoPoint from './GeoPoint'; import Path from './Path'; import WriteBatch from './WriteBatch'; -import INTERNALS from './../../internals'; +import INTERNALS from '../../utils/internals'; import type DocumentSnapshot from './DocumentSnapshot'; -import type FirebaseApp from '../../firebase-app'; +import type FirebaseApp from '../core/firebase-app'; import type QuerySnapshot from './QuerySnapshot'; type CollectionSyncEvent = { diff --git a/lib/modules/utils/index.js b/lib/modules/utils/index.js index 942b6af1..4054dc93 100644 --- a/lib/modules/utils/index.js +++ b/lib/modules/utils/index.js @@ -3,9 +3,9 @@ import { NativeModules } from 'react-native'; // import { version as ReactVersion } from 'react'; // import ReactNativeVersion from 'react-native/Libraries/Core/ReactNativeVersion'; -import INTERNALS from './../../internals'; -import { isIOS } from './../../utils'; -import PACKAGE from './../../../package.json'; +import INTERNALS from '../../utils/internals'; +import { isIOS } from '../../utils'; +import PACKAGE from '../../../package.json'; const FirebaseCoreModule = NativeModules.RNFirebase; @@ -128,4 +128,3 @@ export const statics = { // 'react-native-firebase': PACKAGE.version, // }, }; - diff --git a/lib/flow.js b/lib/types/flow.js similarity index 100% rename from lib/flow.js rename to lib/types/flow.js diff --git a/lib/utils/ModuleBase.js b/lib/utils/ModuleBase.js index 12b548c1..bbb0042d 100644 --- a/lib/utils/ModuleBase.js +++ b/lib/utils/ModuleBase.js @@ -3,12 +3,12 @@ */ import { NativeModules } from 'react-native'; -import Log from '../utils/log'; -import INTERNALS from './../internals'; -import FirebaseCore from './../firebase'; -import { nativeWithApp } from './../utils'; +import Log from './log'; +import INTERNALS from './internals'; +import FirebaseCore from '../modules/core/firebase'; +import { nativeWithApp } from '../utils'; -import type FirebaseApp from '../firebase-app'; +import type FirebaseApp from '../modules/core/firebase-app'; const logs = {}; diff --git a/lib/internals.js b/lib/utils/internals.js similarity index 98% rename from lib/internals.js rename to lib/utils/internals.js index ef7f4998..87cd42b2 100644 --- a/lib/internals.js +++ b/lib/utils/internals.js @@ -3,9 +3,9 @@ */ import { Platform, NativeModules } from 'react-native'; -import EventEmitter from './utils/emitter/EventEmitter'; -import ModuleBase from './utils/ModuleBase'; -import SyncTree from './utils/SyncTree'; +import EventEmitter from './emitter/EventEmitter'; +import ModuleBase from './ModuleBase'; +import SyncTree from './SyncTree'; const DEFAULT_APP_NAME = Platform.OS === 'ios' ? '__FIRAPP_DEFAULT' : '[DEFAULT]'; diff --git a/package-lock.json b/package-lock.json index a4207e20..df11263f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", "dev": true, "requires": { - "mime-types": "2.1.11", + "mime-types": "2.1.17", "negotiator": "0.5.3" } }, @@ -61,17 +61,6 @@ "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", "dev": true }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" - } - }, "andlog": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/andlog/-/andlog-1.0.0.tgz", @@ -250,6 +239,12 @@ "lodash": "4.17.4" } }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -277,6 +272,29 @@ "ast-types-flow": "0.0.7" } }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "babel-polyfill": "6.26.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "chokidar": "1.7.0", + "commander": "2.11.0", + "convert-source-map": "1.5.0", + "fs-readdir-recursive": "1.1.0", + "glob": "7.1.2", + "lodash": "4.17.4", + "output-file-sync": "1.1.2", + "path-is-absolute": "1.0.1", + "slash": "1.0.0", + "source-map": "0.5.7", + "v8flags": "2.1.1" + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -533,6 +551,12 @@ "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", "dev": true }, + "babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", + "dev": true + }, "babel-plugin-syntax-flow": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", @@ -976,6 +1000,20 @@ "react-transform-hmr": "1.0.4" } }, + "babel-preset-react-native-syntax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/babel-preset-react-native-syntax/-/babel-preset-react-native-syntax-1.0.0.tgz", + "integrity": "sha1-5hq/Cmq3PiwN1QPuGtTwezAlNwU=", + "dev": true, + "requires": { + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-plugin-syntax-flow": "6.18.0", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0" + } + }, "babel-register": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", @@ -1116,9 +1154,15 @@ "dev": true }, "big-integer": { - "version": "1.6.25", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.25.tgz", - "integrity": "sha1-HeRan1dUKsIBIcaC+NZCIgo06CM=", + "version": "1.6.26", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.26.tgz", + "integrity": "sha1-OvFnL6Ytry1eyvrPblqg0l4Cwcg=", + "dev": true + }, + "binary-extensions": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.10.0.tgz", + "integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=", "dev": true }, "body-parser": { @@ -1200,7 +1244,7 @@ "integrity": "sha1-1g1dzCDLptx+HymbNdPh+V2vuuY=", "dev": true, "requires": { - "big-integer": "1.6.25" + "big-integer": "1.6.26" } }, "brace-expansion": { @@ -1225,9 +1269,9 @@ } }, "bser": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bser/-/bser-1.0.3.tgz", - "integrity": "sha1-1j2hnuFzMKDiYNKjRCKyGolSAxc=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", + "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", "dev": true, "requires": { "node-int64": "0.4.0" @@ -1261,9 +1305,9 @@ "dev": true }, "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, "caseless": { @@ -1272,16 +1316,6 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" - } - }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -1318,6 +1352,23 @@ "lodash.some": "4.6.0" } }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.1.3", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", @@ -1339,22 +1390,14 @@ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" }, "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - } + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" } }, "clone": { @@ -1638,12 +1681,13 @@ } }, "cross-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", - "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { "lru-cache": "4.1.1", + "shebang-command": "1.2.0", "which": "1.3.0" } }, @@ -1772,7 +1816,7 @@ "object-assign": "4.1.1", "pify": "2.3.0", "pinkie-promise": "2.0.1", - "rimraf": "2.6.1" + "rimraf": "2.6.2" } }, "delayed-stream": { @@ -2021,15 +2065,6 @@ "negotiator": "0.6.1" } }, - "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "dev": true, - "requires": { - "mime-db": "1.30.0" - } - }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", @@ -2383,6 +2418,21 @@ "merge": "1.2.0" } }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, "exit-hook": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", @@ -2517,17 +2567,6 @@ "dev": true, "requires": { "bser": "2.0.0" - }, - "dependencies": { - "bser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", - "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", - "dev": true, - "requires": { - "node-int64": "0.4.0" - } - } } }, "fbjs": { @@ -2552,59 +2591,19 @@ } }, "fbjs-scripts": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/fbjs-scripts/-/fbjs-scripts-0.7.1.tgz", - "integrity": "sha1-TxFeIY4kPjrdvw7dqsHjxi9wP6w=", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/fbjs-scripts/-/fbjs-scripts-0.8.1.tgz", + "integrity": "sha512-hTjqlua9YJupF8shbVRTq20xKPITnDmqBLBQyR9BttZYT+gxGeKboIzPC19T3Erp29Q0+jdMwjUiyTHR61q1Bw==", "dev": true, "requires": { "babel-core": "6.26.0", - "babel-preset-fbjs": "1.0.0", - "core-js": "1.2.7", - "cross-spawn": "3.0.1", + "babel-preset-fbjs": "2.1.4", + "core-js": "2.5.1", + "cross-spawn": "5.1.0", "gulp-util": "3.0.8", "object-assign": "4.1.1", "semver": "5.4.1", "through2": "2.0.3" - }, - "dependencies": { - "babel-preset-fbjs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-1.0.0.tgz", - "integrity": "sha1-yXLlybMB1OyeeXH0rsPhSsAXqLA=", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-syntax-flow": "6.18.0", - "babel-plugin-syntax-object-rest-spread": "6.13.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es3-member-expression-literals": "6.22.0", - "babel-plugin-transform-es3-property-literals": "6.22.0", - "babel-plugin-transform-flow-strip-types": "6.22.0", - "babel-plugin-transform-object-rest-spread": "6.26.0", - "object-assign": "4.1.1" - } - }, - "core-js": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", - "dev": true - } } }, "figures": { @@ -2709,6 +2708,110 @@ "integrity": "sha1-zkMJIgOjRLqb9jwMq+ldlRRfbK0=", "dev": true }, + "flow-copy-source": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/flow-copy-source/-/flow-copy-source-1.2.1.tgz", + "integrity": "sha512-C3T0OjBOOVd0LWg4wzE3seZOpqddSq5nxMD72iDrGdZ+7WsjbO4rUMEWp4mXErWesD3jPTATxk27HfQdMtZW6g==", + "dev": true, + "requires": { + "chokidar": "1.7.0", + "fs-extra": "3.0.1", + "glob": "7.1.2", + "kefir": "3.8.0", + "yargs": "8.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "3.0.1", + "universalify": "0.1.1" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "7.0.0" + } + } + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -2745,17 +2848,6 @@ "asynckit": "0.4.0", "combined-stream": "1.0.5", "mime-types": "2.1.17" - }, - "dependencies": { - "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "dev": true, - "requires": { - "mime-db": "1.30.0" - } - } } }, "fresh": { @@ -2775,6 +2867,12 @@ "klaw": "1.3.1" } }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3727,6 +3825,12 @@ "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", "dev": true }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -3814,6 +3918,12 @@ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, "gulp-util": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", @@ -3877,20 +3987,6 @@ "requires": { "ajv": "5.3.0", "har-schema": "2.0.0" - }, - "dependencies": { - "ajv": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.3.0.tgz", - "integrity": "sha1-RBT/dKUIecII7l/cgm4ywwNUnto=", - "dev": true, - "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" - } - } } }, "has": { @@ -4219,6 +4315,15 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.10.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -4440,47 +4545,23 @@ "dev": true }, "jest-docblock": { - "version": "20.1.0-delta.4", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-20.1.0-delta.4.tgz", - "integrity": "sha512-apbBKyQ8ET8XQbOnsjIYTvmo2+FRZIsxUkfy75IbG+SH9ILQLjEfPXq3B/iMRCGoTAeI8lwxUQoLKGbw0mrTCQ==", + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz", + "integrity": "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw==", "dev": true }, "jest-haste-map": { - "version": "20.1.0-delta.4", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-20.1.0-delta.4.tgz", - "integrity": "sha512-L95f3nYoxUSzqzJdOq39ggklspwkqOq/FkzvH0SYhXdpv0c0kW8DXLovxfZy5FnK4rUyeVMBI9aNQ+TvZHKT3Q==", + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-21.2.0.tgz", + "integrity": "sha512-5LhsY/loPH7wwOFRMs+PT4aIAORJ2qwgbpMFlbWbxfN0bk3ZCwxJ530vrbSiTstMkYLao6JwBkLhCJ5XbY7ZHw==", "dev": true, "requires": { "fb-watchman": "2.0.0", "graceful-fs": "4.1.11", - "jest-docblock": "20.1.0-delta.4", + "jest-docblock": "21.2.0", "micromatch": "2.3.11", "sane": "2.2.0", "worker-farm": "1.5.2" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "sane": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/sane/-/sane-2.2.0.tgz", - "integrity": "sha512-OSJxhHO0CgPUw3lUm3GhfREAfza45smvEI9ozuFrxKG10GHVo0ryW9FK5VYlLvxj0SV7HVKHW0voYJIRu27GWg==", - "dev": true, - "requires": { - "anymatch": "1.3.2", - "exec-sh": "0.2.1", - "fb-watchman": "2.0.0", - "fsevents": "1.1.3", - "minimatch": "3.0.4", - "minimist": "1.2.0", - "walker": "1.0.7", - "watch": "0.18.0" - } - } } }, "js-tokens": { @@ -4588,6 +4669,15 @@ "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", "dev": true }, + "kefir": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/kefir/-/kefir-3.8.0.tgz", + "integrity": "sha512-6jUL1maSYUDNbjKDbGCAcvjwIYpcevE4nDISN0yuow5flhLuQWLQPM/n9iUiz9QA8qa1SaD99SdL/AMzTQTVjw==", + "dev": true, + "requires": { + "symbol-observable": "1.0.4" + } + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -4606,12 +4696,6 @@ "graceful-fs": "4.1.11" } }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", @@ -4622,9 +4706,9 @@ } }, "left-pad": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.1.3.tgz", - "integrity": "sha1-YS9hwDPzqeCOk58crr7qQbbzGZo=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.2.0.tgz", + "integrity": "sha1-0wpzxrggHY99jnlWupYWCHpo4O4=", "dev": true }, "levn": { @@ -4893,12 +4977,6 @@ "lodash.escape": "3.2.0" } }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, "loose-envify": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", @@ -4938,6 +5016,15 @@ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, "merge": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", @@ -4989,9 +5076,9 @@ "dev": true }, "metro-bundler": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/metro-bundler/-/metro-bundler-0.11.0.tgz", - "integrity": "sha512-z1b2HtOa1uJVrp5KOx9bvoYRPD8Gn5x+gyFTIGSev7hbDzyAmUoooFUf8yLAfyIVIb4TZGB+tjkn+Skmn41aNQ==", + "version": "0.20.3", + "resolved": "https://registry.npmjs.org/metro-bundler/-/metro-bundler-0.20.3.tgz", + "integrity": "sha512-rKhIXSUEYbBUB9Ues30GYlcotM/4hPTmriBJGdNW5D+zdlxQUgJuPEo2Woo7khNM7xRG5tN7IRnMkKlzx43/Nw==", "dev": true, "requires": { "absolute-path": "0.0.0", @@ -5001,7 +5088,7 @@ "babel-plugin-external-helpers": "6.22.0", "babel-preset-es2015-node": "6.1.1", "babel-preset-fbjs": "2.1.4", - "babel-preset-react-native": "2.1.0", + "babel-preset-react-native": "4.0.0", "babel-register": "6.26.0", "babylon": "6.18.0", "chalk": "1.1.3", @@ -5009,38 +5096,49 @@ "core-js": "2.5.1", "debug": "2.6.8", "denodeify": "1.2.1", - "fbjs": "0.8.12", + "fbjs": "0.8.16", "graceful-fs": "4.1.11", "image-size": "0.6.1", - "jest-docblock": "20.1.0-chi.1", - "jest-haste-map": "20.1.0-chi.1", + "jest-docblock": "21.2.0", + "jest-haste-map": "21.2.0", "json-stable-stringify": "1.0.1", "json5": "0.4.0", - "left-pad": "1.1.3", + "left-pad": "1.2.0", "lodash": "4.17.4", "merge-stream": "1.0.1", "mime-types": "2.1.11", "mkdirp": "0.5.1", "request": "2.83.0", - "rimraf": "2.6.1", + "rimraf": "2.6.2", "source-map": "0.5.7", "temp": "0.8.3", "throat": "4.1.0", - "uglify-js": "2.7.5", + "uglify-es": "3.1.9", + "wordwrap": "1.0.0", "write-file-atomic": "1.3.4", "xpipe": "1.0.5" }, "dependencies": { + "babel-plugin-react-transform": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-react-transform/-/babel-plugin-react-transform-3.0.0.tgz", + "integrity": "sha512-4vJGddwPiHAOgshzZdGwYy4zRjjIr5SMY7gkOaCyIASjgpcsyLTlZNuB5rHOFoaTvGlhfo8/g4pobXPyHqm/3w==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, "babel-preset-react-native": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-react-native/-/babel-preset-react-native-2.1.0.tgz", - "integrity": "sha1-kBPr2C2hyIECv1iIEP9Z4gnKK4o=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/babel-preset-react-native/-/babel-preset-react-native-4.0.0.tgz", + "integrity": "sha512-Wfbo6x244nUbBxjr7hQaNFdjj7FDYU+TVT7cFVPEdVPI68vhN52iLvamm+ErhNdHq6M4j1cMT6AJBYx7Wzdr0g==", "dev": true, "requires": { "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-react-transform": "2.0.2", + "babel-plugin-react-transform": "3.0.0", "babel-plugin-syntax-async-functions": "6.13.0", "babel-plugin-syntax-class-properties": "6.13.0", + "babel-plugin-syntax-dynamic-import": "6.18.0", "babel-plugin-syntax-flow": "6.18.0", "babel-plugin-syntax-jsx": "6.18.0", "babel-plugin-syntax-trailing-function-commas": "6.22.0", @@ -5065,78 +5163,29 @@ "babel-plugin-transform-react-jsx": "6.24.1", "babel-plugin-transform-react-jsx-source": "6.22.0", "babel-plugin-transform-regenerator": "6.26.0", + "babel-template": "6.26.0", "react-transform-hmr": "1.0.4" } }, - "fbjs": { - "version": "0.8.12", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.12.tgz", - "integrity": "sha1-ELXZL3bUVXX9Y6IX1OoCvqL47QQ=", - "dev": true, - "requires": { - "core-js": "1.2.7", - "isomorphic-fetch": "2.2.1", - "loose-envify": "1.3.1", - "object-assign": "4.1.1", - "promise": "7.3.1", - "setimmediate": "1.0.5", - "ua-parser-js": "0.7.17" - }, - "dependencies": { - "core-js": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", - "dev": true - } - } - }, - "jest-docblock": { - "version": "20.1.0-chi.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-20.1.0-chi.1.tgz", - "integrity": "sha512-zX64LtNgTgphO06akqDxKQhVET3uwjZTRalqG2jJoWyEdSUYGp8yjjqicJ7rRu5ZbwnuaB8yqqP9Exu59oDNaA==", - "dev": true - }, - "jest-haste-map": { - "version": "20.1.0-chi.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-20.1.0-chi.1.tgz", - "integrity": "sha512-G5Bjy3NoSBOR4T5FGqu6VlUJk7BnGUfRXkPcU26HTE06j5T0HEnVoScUsP1+XHSSw0XKq84N2LquppHbg3buxg==", - "dev": true, - "requires": { - "fb-watchman": "2.0.0", - "graceful-fs": "4.1.11", - "jest-docblock": "20.1.0-chi.1", - "micromatch": "2.3.11", - "sane": "2.2.0", - "worker-farm": "1.5.2" - } - }, "json5": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz", "integrity": "sha1-BUNS5MTIDIbAkjh31EneF2pzLI0=", "dev": true }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "mime-db": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz", + "integrity": "sha1-oxtAcK2uon1zLqMzdApk0OyaZlk=", "dev": true }, - "sane": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/sane/-/sane-2.2.0.tgz", - "integrity": "sha512-OSJxhHO0CgPUw3lUm3GhfREAfza45smvEI9ozuFrxKG10GHVo0ryW9FK5VYlLvxj0SV7HVKHW0voYJIRu27GWg==", + "mime-types": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", + "integrity": "sha1-wlnEcb2oCKhdbNGTtDCl+uRHOzw=", "dev": true, "requires": { - "anymatch": "1.3.2", - "exec-sh": "0.2.1", - "fb-watchman": "2.0.0", - "fsevents": "1.1.3", - "minimatch": "3.0.4", - "minimist": "1.2.0", - "walker": "1.0.7", - "watch": "0.18.0" + "mime-db": "1.23.0" } } } @@ -5175,20 +5224,12 @@ "dev": true }, "mime-types": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", - "integrity": "sha1-wlnEcb2oCKhdbNGTtDCl+uRHOzw=", + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", "dev": true, "requires": { - "mime-db": "1.23.0" - }, - "dependencies": { - "mime-db": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz", - "integrity": "sha1-oxtAcK2uon1zLqMzdApk0OyaZlk=", - "dev": true - } + "mime-db": "1.30.0" } }, "mimic-fn": { @@ -5350,6 +5391,18 @@ "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", "dev": true }, + "node-notifier": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.1.2.tgz", + "integrity": "sha1-L6nhJgX6EACdRFSdb82KY93g5P8=", + "dev": true, + "requires": { + "growly": "1.3.0", + "semver": "5.4.1", + "shellwords": "0.1.1", + "which": "1.3.0" + } + }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -5371,6 +5424,15 @@ "remove-trailing-separator": "1.1.0" } }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, "npmlog": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", @@ -5735,6 +5797,23 @@ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "object-assign": "4.1.1" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, "p-limit": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", @@ -5798,6 +5877,12 @@ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, "path-parse": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", @@ -6118,63 +6203,43 @@ } }, "react-native": { - "version": "0.48.4", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.48.4.tgz", - "integrity": "sha1-8wXp/vBppbP2pyUN3VD2A88wqy0=", + "version": "0.50.3", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.50.3.tgz", + "integrity": "sha1-kSgr1TVsx9eUlpzcRDzHZDibmvQ=", "dev": true, "requires": { "absolute-path": "0.0.0", "art": "0.10.1", - "async": "2.6.0", "babel-core": "6.26.0", - "babel-generator": "6.26.0", - "babel-plugin-external-helpers": "6.22.0", "babel-plugin-syntax-trailing-function-commas": "6.22.0", "babel-plugin-transform-async-to-generator": "6.16.0", "babel-plugin-transform-class-properties": "6.24.1", "babel-plugin-transform-flow-strip-types": "6.22.0", "babel-plugin-transform-object-rest-spread": "6.26.0", - "babel-polyfill": "6.26.0", - "babel-preset-es2015-node": "6.1.1", - "babel-preset-fbjs": "2.1.4", - "babel-preset-react-native": "2.1.0", "babel-register": "6.26.0", "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", "base64-js": "1.2.1", - "bser": "1.0.3", "chalk": "1.1.3", "commander": "2.11.0", - "concat-stream": "1.6.0", "connect": "2.30.2", - "core-js": "2.5.1", "create-react-class": "15.6.2", "debug": "2.6.8", "denodeify": "1.2.1", "envinfo": "3.9.1", - "errno": "0.1.4", "event-target-shim": "1.1.1", - "fbjs": "0.8.12", - "fbjs-scripts": "0.7.1", - "form-data": "2.3.1", + "fbjs": "0.8.16", + "fbjs-scripts": "0.8.1", "fs-extra": "1.0.0", "glob": "7.1.2", "graceful-fs": "4.1.11", "inquirer": "3.3.0", - "jest-haste-map": "20.1.0-delta.4", - "json-stable-stringify": "1.0.1", - "json5": "0.4.0", - "left-pad": "1.1.3", "lodash": "4.17.4", - "merge-stream": "1.0.1", - "metro-bundler": "0.11.0", + "metro-bundler": "0.20.3", "mime": "1.4.1", - "mime-types": "2.1.11", "minimist": "1.2.0", "mkdirp": "0.5.1", "node-fetch": "1.6.3", + "node-notifier": "5.1.2", "npmlog": "2.0.4", "opn": "3.0.3", "optimist": "0.6.1", @@ -6185,275 +6250,30 @@ "react-clone-referenced-element": "1.0.1", "react-devtools-core": "2.5.2", "react-timer-mixin": "0.13.3", - "react-transform-hmr": "1.0.4", - "rebound": "0.0.13", "regenerator-runtime": "0.9.6", - "request": "2.83.0", - "rimraf": "2.6.1", - "sane": "1.4.1", + "rimraf": "2.6.2", "semver": "5.4.1", "shell-quote": "1.6.1", - "source-map": "0.5.7", "stacktrace-parser": "0.1.4", - "temp": "0.8.3", - "throat": "4.1.0", "whatwg-fetch": "1.1.1", - "wordwrap": "1.0.0", - "write-file-atomic": "1.3.4", "ws": "1.1.5", "xcode": "0.9.3", "xmldoc": "0.4.0", - "xpipe": "1.0.5", - "xtend": "4.0.1", - "yargs": "6.6.0" + "yargs": "9.0.1" }, "dependencies": { - "ansi-escapes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "babel-preset-react-native": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-react-native/-/babel-preset-react-native-2.1.0.tgz", - "integrity": "sha1-kBPr2C2hyIECv1iIEP9Z4gnKK4o=", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-react-transform": "2.0.2", - "babel-plugin-syntax-async-functions": "6.13.0", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-plugin-syntax-flow": "6.18.0", - "babel-plugin-syntax-jsx": "6.18.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-flow-strip-types": "6.22.0", - "babel-plugin-transform-object-assign": "6.22.0", - "babel-plugin-transform-object-rest-spread": "6.26.0", - "babel-plugin-transform-react-display-name": "6.25.0", - "babel-plugin-transform-react-jsx": "6.24.1", - "babel-plugin-transform-react-jsx-source": "6.22.0", - "babel-plugin-transform-regenerator": "6.26.0", - "react-transform-hmr": "1.0.4" - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "2.0.0" - } - }, - "external-editor": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.5.tgz", - "integrity": "sha512-Msjo64WT5W+NhOpQXh0nOHm+n0RfU1QUwDnKYvJ8dEJ8zlwLrqXNTv5mSUTJpepf41PDJGyhueTw2vNZW+Fr/w==", - "dev": true, - "requires": { - "iconv-lite": "0.4.19", - "jschardet": "1.6.0", - "tmp": "0.0.33" - } - }, - "fbjs": { - "version": "0.8.12", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.12.tgz", - "integrity": "sha1-ELXZL3bUVXX9Y6IX1OoCvqL47QQ=", - "dev": true, - "requires": { - "core-js": "1.2.7", - "isomorphic-fetch": "2.2.1", - "loose-envify": "1.3.1", - "object-assign": "4.1.1", - "promise": "7.3.1", - "setimmediate": "1.0.5", - "ua-parser-js": "0.7.17" - }, - "dependencies": { - "core-js": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", - "dev": true - } - } - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5" - } - }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, - "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.3.0", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.0.5", - "figures": "2.0.0", - "lodash": "4.17.4", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rx-lite": "4.0.8", - "rx-lite-aggregates": "4.0.8", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" - }, - "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - } - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "json5": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz", - "integrity": "sha1-BUNS5MTIDIbAkjh31EneF2pzLI0=", - "dev": true - }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "1.1.0" - } - }, "regenerator-runtime": { "version": "0.9.6", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz", "integrity": "sha1-0z65XQ0gAaS+OWWXB8UbDLcc4Ck=", "dev": true }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" - } - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "2.1.0" - } - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "1.0.2" - } - }, "whatwg-fetch": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-1.1.1.tgz", @@ -6535,11 +6355,17 @@ "util-deprecate": "1.0.2" } }, - "rebound": { - "version": "0.0.13", - "resolved": "https://registry.npmjs.org/rebound/-/rebound-0.0.13.tgz", - "integrity": "sha1-SiJSVMr32nVnl7GcWBe/enlB+sE=", - "dev": true + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + } }, "rechoir": { "version": "0.6.2", @@ -6678,15 +6504,6 @@ "uuid": "3.1.0" }, "dependencies": { - "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "dev": true, - "requires": { - "mime-db": "1.30.0" - } - }, "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", @@ -6760,19 +6577,10 @@ "onetime": "1.1.0" } }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "0.1.4" - } - }, "rimraf": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { "glob": "7.1.2" @@ -6820,48 +6628,26 @@ "dev": true }, "sane": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sane/-/sane-1.4.1.tgz", - "integrity": "sha1-iPdj10BA9fDCVrYWPbOZvxEKxxU=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-2.2.0.tgz", + "integrity": "sha512-OSJxhHO0CgPUw3lUm3GhfREAfza45smvEI9ozuFrxKG10GHVo0ryW9FK5VYlLvxj0SV7HVKHW0voYJIRu27GWg==", "dev": true, "requires": { + "anymatch": "1.3.2", "exec-sh": "0.2.1", - "fb-watchman": "1.9.2", + "fb-watchman": "2.0.0", + "fsevents": "1.1.3", "minimatch": "3.0.4", "minimist": "1.2.0", "walker": "1.0.7", - "watch": "0.10.0" + "watch": "0.18.0" }, "dependencies": { - "bser": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bser/-/bser-1.0.2.tgz", - "integrity": "sha1-OBEWlwsqbe6lZG3RXdcnhES1YWk=", - "dev": true, - "requires": { - "node-int64": "0.4.0" - } - }, - "fb-watchman": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-1.9.2.tgz", - "integrity": "sha1-okz0eCf4LTj7Waaa1wt247auc4M=", - "dev": true, - "requires": { - "bser": "1.0.2" - } - }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true - }, - "watch": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/watch/-/watch-0.10.0.tgz", - "integrity": "sha1-d3mLLaD5kQ1ZXxrOWwwiWFIfIdw=", - "dev": true } } }, @@ -6963,7 +6749,7 @@ "debug": "2.2.0", "escape-html": "1.0.3", "http-errors": "1.3.1", - "mime-types": "2.1.11", + "mime-types": "2.1.17", "parseurl": "1.3.2" }, "dependencies": { @@ -7001,6 +6787,12 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -7044,6 +6836,12 @@ "rechoir": "0.6.2" } }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -7290,6 +7088,12 @@ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -7301,6 +7105,12 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, + "symbol-observable": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", + "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=", + "dev": true + }, "sync-exec": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/sync-exec/-/sync-exec-0.6.2.tgz", @@ -7516,17 +7326,6 @@ "requires": { "media-typer": "0.3.0", "mime-types": "2.1.17" - }, - "dependencies": { - "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "dev": true, - "requires": { - "mime-db": "1.30.0" - } - } } }, "typedarray": { @@ -7540,44 +7339,24 @@ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==" }, - "uglify-js": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", - "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", + "uglify-es": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.1.9.tgz", + "integrity": "sha512-wVSiJKHDgDDFmxTVVvnbAH6IpamAFHYDI+5JvwPdaqIMnk8kRTX2JKwq1Fx7gb2+Jj5Dus8kzvIpKkWOMNU51w==", "dev": true, "requires": { - "async": "0.2.10", - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "commander": "2.11.0", + "source-map": "0.6.1" }, "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" - } } } }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true - }, "uid-safe": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", @@ -7593,6 +7372,12 @@ "integrity": "sha1-sHoualQagV/Go0zNRTO67DB8qGQ=", "dev": true }, + "universalify": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", + "dev": true + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -7605,6 +7390,12 @@ "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=", "dev": true }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -7629,6 +7420,15 @@ "integrity": "sha1-bIhtAqU9LUDc8l2RoXC0p7JblNA=", "dev": true }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, "validate-npm-package-license": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", @@ -7729,12 +7529,6 @@ "semver": "5.4.1" } }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, "wml": { "version": "0.0.82", "resolved": "https://registry.npmjs.org/wml/-/wml-0.0.82.tgz", @@ -7798,7 +7592,7 @@ "jsonfile": "2.4.0", "klaw": "1.3.1", "path-is-absolute": "1.0.1", - "rimraf": "2.6.1" + "rimraf": "2.6.2" } }, "inquirer": { @@ -8078,114 +7872,83 @@ "dev": true }, "yargs": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", - "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", "dev": true, "requires": { - "camelcase": "3.0.0", + "camelcase": "4.1.0", "cliui": "3.2.0", "decamelize": "1.2.0", "get-caller-file": "1.0.2", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", "require-directory": "2.1.1", "require-main-filename": "1.0.1", "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", "y18n": "3.2.1", - "yargs-parser": "4.2.1" + "yargs-parser": "7.0.0" }, "dependencies": { - "camelcase": { + "ansi-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" - } - }, - "strip-bom": { + "is-fullwidth-code-point": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "is-utf8": "0.2.1" + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true } } }, "yargs-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", - "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", "dev": true, "requires": { - "camelcase": "3.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - } + "camelcase": "4.1.0" } } } diff --git a/package.json b/package.json index 2b7eed60..ac77b3dd 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,28 @@ { "name": "react-native-firebase", - "version": "3.1.0", + "version": "3.1.1-alpha.4", "author": "Invertase (http://invertase.io)", "description": "A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Messaging (FCM), Remote Config, Storage and Performance.", - "main": "index", + "main": "dist/index.js", "scripts": { + "build": "npm run build-lib && npm run build-flow", + "build-flow": "flow-copy-source -i */__tests__* lib dist", + "build-lib": "BABEL_ENV=publish babel lib -d dist --ignore __tests__", + "clean": "rimraf dist/", "flow": "flow", "lint": "eslint ./src", - "dev": "npm run compile -- --watch", - "build": "./node_modules/.bin/babel --source-maps=true --out-dir=dist .", - "publish_pages": "gh-pages -d public/", - "docs-serve-local": "docsify serve docs", + "prepublish": "npm run clean && npm run build", + "postinstall": "opencollective postinstall", "test-cli": "node ./bin/test.js", "tests-packager": "cd tests && npm run start", "tests-npm-install": "cd tests && npm install", "tests-pod-install": "cd tests && npm run ios:pod:install", "tests-watch-start": "npm run test-cli watch init start", - "tests-watch-stop": "npm run test-cli watch stop", - "postinstall": "opencollective postinstall" + "tests-watch-stop": "npm run test-cli watch stop" }, + "files": [ + "dist" + ], "repository": { "type": "git", "url": "https://github.com/invertase/react-native-firebase.git" @@ -70,9 +74,11 @@ "fbjs": "*" }, "devDependencies": { + "babel-cli": "^6.26.0", "babel-eslint": "^7.0.0", "babel-jest": "^14.1.0", "babel-preset-react-native": "^1.9.0", + "babel-preset-react-native-syntax": "^1.0.0", "debug": "^2.2.0", "enzyme": "^2.4.1", "eslint": "^4.11.0", @@ -82,9 +88,11 @@ "eslint-plugin-jsx-a11y": "^6.0.2", "eslint-plugin-react": "^7.4.0", "flow-bin": "^0.56.0", + "flow-copy-source": "^1.2.1", "react": "^16.0.0", "react-dom": "^16.0.0", - "react-native": "^0.48.0", + "react-native": "^0.50.3", + "rimraf": "^2.6.2", "shelljs": "^0.7.8", "wml": "0.0.82" }, From 802c54ade8e6f2bde822066b2f9c77d074be7679 Mon Sep 17 00:00:00 2001 From: Akshet Pandey Date: Mon, 20 Nov 2017 16:58:55 -0800 Subject: [PATCH 08/56] [android][messaging] Handle SecuritException in cancelAllLocalNotifications --- .../invertase/firebase/messaging/RNFirebaseMessaging.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/io/invertase/firebase/messaging/RNFirebaseMessaging.java b/android/src/main/java/io/invertase/firebase/messaging/RNFirebaseMessaging.java index 87fa616e..bc6d1d7b 100644 --- a/android/src/main/java/io/invertase/firebase/messaging/RNFirebaseMessaging.java +++ b/android/src/main/java/io/invertase/firebase/messaging/RNFirebaseMessaging.java @@ -104,7 +104,13 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements L @ReactMethod public void cancelAllLocalNotifications() { - mRNFirebaseLocalMessagingHelper.cancelAllLocalNotifications(); + try { + mRNFirebaseLocalMessagingHelper.cancelAllLocalNotifications(); + } catch (SecurityException e) { + // In some devices/situations cancelAllLocalNotifications will throw a SecurityException + // We can safely ignore this error for now as the UX impact of this not working is minor. + Log.w(TAG, e.getMessage()); + } } @ReactMethod From ff95c21b9d7bd7dd3e17f8a837e7055634f2a1fa Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Thu, 23 Nov 2017 17:29:40 +0000 Subject: [PATCH 09/56] [typings] Continue work on flow --- .flowconfig | 1 - lib/modules/admob/index.js | 4 + lib/modules/analytics/index.js | 7 +- lib/modules/auth/User.js | 1 + lib/modules/auth/index.js | 6 + .../auth/providers/EmailAuthProvider.js | 2 + .../auth/providers/FacebookAuthProvider.js | 2 + .../auth/providers/GithubAuthProvider.js | 2 + .../auth/providers/GoogleAuthProvider.js | 2 + .../auth/providers/PhoneAuthProvider.js | 2 + .../auth/providers/TwitterAuthProvider.js | 2 + lib/modules/config/index.js | 2 + lib/modules/core/firebase-app.js | 74 ++++--- lib/modules/core/firebase.js | 73 ++++--- lib/modules/crash/index.js | 11 +- lib/modules/database/query.js | 4 +- lib/modules/database/reference.js | 13 +- lib/modules/firestore/CollectionReference.js | 1 + lib/modules/firestore/DocumentChange.js | 1 + lib/modules/firestore/DocumentReference.js | 1 + lib/modules/firestore/DocumentSnapshot.js | 1 + lib/modules/firestore/Query.js | 1 + lib/modules/firestore/QuerySnapshot.js | 1 + lib/modules/firestore/WriteBatch.js | 1 + lib/modules/firestore/index.js | 118 +++++------ lib/modules/firestore/utils/serialize.js | 1 + lib/modules/perf/index.js | 2 + lib/modules/utils/index.js | 15 +- lib/types/flow.js | 93 --------- lib/types/index.js | 187 ++++++++++++++++++ lib/utils/ModuleBase.js | 3 +- lib/utils/SyncTree.js | 8 +- lib/utils/internals.js | 8 +- package-lock.json | 2 +- package.json | 5 +- tests/ios/Podfile.lock | 4 +- 36 files changed, 429 insertions(+), 232 deletions(-) delete mode 100644 lib/types/flow.js create mode 100644 lib/types/index.js diff --git a/.flowconfig b/.flowconfig index e3db9bc6..c297a19a 100644 --- a/.flowconfig +++ b/.flowconfig @@ -80,7 +80,6 @@ node_modules/fbjs/lib [libs] -lib/types/flow.js node_modules/react-native/Libraries/react-native/react-native-interface.js node_modules/react-native/flow node_modules/fbjs/flow/lib diff --git a/lib/modules/admob/index.js b/lib/modules/admob/index.js index 9aa0c7b9..2ca393cb 100644 --- a/lib/modules/admob/index.js +++ b/lib/modules/admob/index.js @@ -1,3 +1,7 @@ +/** + * @flow + * AdMob representation wrapper + */ import ModuleBase from './../../utils/ModuleBase'; import Interstitial from './Interstitial'; diff --git a/lib/modules/analytics/index.js b/lib/modules/analytics/index.js index f468759f..a66927eb 100644 --- a/lib/modules/analytics/index.js +++ b/lib/modules/analytics/index.js @@ -1,4 +1,7 @@ -// @flow +/** + * @flow + * Analytics representation wrapper + */ import ModuleBase from './../../utils/ModuleBase'; const AlphaNumericUnderscore = /^[a-zA-Z0-9_]+$/; @@ -116,3 +119,5 @@ export default class Analytics extends ModuleBase { } } } + +export const statics = {}; diff --git a/lib/modules/auth/User.js b/lib/modules/auth/User.js index 2fc7616e..c15f4f5d 100644 --- a/lib/modules/auth/User.js +++ b/lib/modules/auth/User.js @@ -5,6 +5,7 @@ import INTERNALS from '../../utils/internals'; import type Auth from './'; +import type { AuthCredential } from '../../types'; type NativeUser = { displayName?: string, diff --git a/lib/modules/auth/index.js b/lib/modules/auth/index.js index a13f0e91..67abfe8a 100644 --- a/lib/modules/auth/index.js +++ b/lib/modules/auth/index.js @@ -17,8 +17,14 @@ import FacebookAuthProvider from './providers/FacebookAuthProvider'; import PhoneAuthListener from './PhoneAuthListener'; +import type { AuthCredential } from '../../types'; import type FirebaseApp from '../core/firebase-app'; +type AuthResult = { + authenticated: boolean, + user: Object|null +} | null; + export default class Auth extends ModuleBase { static _NAMESPACE = 'auth'; static _NATIVE_MODULE = 'RNFirebaseAuth'; diff --git a/lib/modules/auth/providers/EmailAuthProvider.js b/lib/modules/auth/providers/EmailAuthProvider.js index b995687f..a82e3ffc 100644 --- a/lib/modules/auth/providers/EmailAuthProvider.js +++ b/lib/modules/auth/providers/EmailAuthProvider.js @@ -2,6 +2,8 @@ * @flow * EmailAuthProvider representation wrapper */ +import type { AuthCredential } from '../../../types'; + const providerId = 'password'; export default class EmailAuthProvider { diff --git a/lib/modules/auth/providers/FacebookAuthProvider.js b/lib/modules/auth/providers/FacebookAuthProvider.js index b60bf027..b6e12ad4 100644 --- a/lib/modules/auth/providers/FacebookAuthProvider.js +++ b/lib/modules/auth/providers/FacebookAuthProvider.js @@ -2,6 +2,8 @@ * @flow * FacebookAuthProvider representation wrapper */ +import type { AuthCredential } from '../../../types'; + const providerId = 'facebook.com'; export default class FacebookAuthProvider { diff --git a/lib/modules/auth/providers/GithubAuthProvider.js b/lib/modules/auth/providers/GithubAuthProvider.js index 4500ce40..aa89701f 100644 --- a/lib/modules/auth/providers/GithubAuthProvider.js +++ b/lib/modules/auth/providers/GithubAuthProvider.js @@ -2,6 +2,8 @@ * @flow * GithubAuthProvider representation wrapper */ +import type { AuthCredential } from '../../../types'; + const providerId = 'github.com'; export default class GithubAuthProvider { diff --git a/lib/modules/auth/providers/GoogleAuthProvider.js b/lib/modules/auth/providers/GoogleAuthProvider.js index 717aa0ce..a9fde23b 100644 --- a/lib/modules/auth/providers/GoogleAuthProvider.js +++ b/lib/modules/auth/providers/GoogleAuthProvider.js @@ -2,6 +2,8 @@ * @flow * EmailAuthProvider representation wrapper */ +import type { AuthCredential } from '../../../types'; + const providerId = 'google.com'; export default class GoogleAuthProvider { diff --git a/lib/modules/auth/providers/PhoneAuthProvider.js b/lib/modules/auth/providers/PhoneAuthProvider.js index 6ac1cc57..fb2ce8cb 100644 --- a/lib/modules/auth/providers/PhoneAuthProvider.js +++ b/lib/modules/auth/providers/PhoneAuthProvider.js @@ -2,6 +2,8 @@ * @flow * PhoneAuthProvider representation wrapper */ +import type { AuthCredential } from '../../../types'; + const providerId = 'phone'; export default class PhoneAuthProvider { diff --git a/lib/modules/auth/providers/TwitterAuthProvider.js b/lib/modules/auth/providers/TwitterAuthProvider.js index 7f6cf902..0f2c6dad 100644 --- a/lib/modules/auth/providers/TwitterAuthProvider.js +++ b/lib/modules/auth/providers/TwitterAuthProvider.js @@ -2,6 +2,8 @@ * @flow * TwitterAuthProvider representation wrapper */ +import type { AuthCredential } from '../../../types'; + const providerId = 'twitter.com'; export default class TwitterAuthProvider { diff --git a/lib/modules/config/index.js b/lib/modules/config/index.js index a78f6a1d..07562a37 100644 --- a/lib/modules/config/index.js +++ b/lib/modules/config/index.js @@ -139,3 +139,5 @@ export default class RemoteConfig extends ModuleBase { this._native.setDefaultsFromResource(resource); } } + +export const statics = {}; diff --git a/lib/modules/core/firebase-app.js b/lib/modules/core/firebase-app.js index efa40c39..a582385b 100644 --- a/lib/modules/core/firebase-app.js +++ b/lib/modules/core/firebase-app.js @@ -8,38 +8,58 @@ import { isObject, isAndroid } from '../../utils'; import AdMob, { statics as AdMobStatics } from '../admob'; import Auth, { statics as AuthStatics } from '../auth'; -import Analytics from '../analytics'; -import Crash from '../crash'; -import Performance from '../perf'; -import RemoteConfig from '../config'; -import Storage, { statics as StorageStatics } from '../storage'; +import Analytics, { statics as AnalyticsStatics } from '../analytics'; +import Config, { statics as ConfigStatics } from '../config'; +import Crash, { statics as CrashStatics } from '../crash'; import Database, { statics as DatabaseStatics } from '../database'; -import Messaging, { statics as MessagingStatics } from '../messaging'; import Firestore, { statics as FirestoreStatics } from '../firestore'; import Links, { statics as LinksStatics } from '../links'; +import Messaging, { statics as MessagingStatics } from '../messaging'; +import Performance, { statics as PerformanceStatics } from '../perf'; +import Storage, { statics as StorageStatics } from '../storage'; import Utils, { statics as UtilsStatics } from '../utils'; +import type { + AdMobModule, + AnalyticsModule, + AuthModule, + ConfigModule, + CrashModule, + DatabaseModule, + FirebaseModule, + FirebaseModuleAndStatics, + FirebaseOptions, + FirebaseStatics, + FirestoreModule, + LinksModule, + MessagingModule, + PerformanceModule, + StorageModule, + UtilsModule, +} from '../../types'; + const FirebaseCoreModule = NativeModules.RNFirebase; + export default class FirebaseApp { _extendedProps: { [string] : boolean }; _initialized: boolean; _name: string; - _namespaces: { [string]: Object }; + _namespaces: { [string]: FirebaseModule }; _nativeInitialized: boolean; _options: FirebaseOptions; - admob: () => AdMob; - auth: () => Auth; - analytics: () => Analytics; - config: () => RemoteConfig; - crash: () => Crash; - database: () => Database; - firestore: () => Firestore; - links: () => Links; - messaging: () => Messaging; - perf: () => Performance; - storage: () => Storage; - utils: () => Utils; + admob: AdMobModule; + analytics: AnalyticsModule; + auth: AuthModule; + config: ConfigModule; + crash: CrashModule; + database: DatabaseModule; + firestore: FirestoreModule; + links: LinksModule; + messaging: MessagingModule; + perf: PerformanceModule; + storage: StorageModule; + utils: UtilsModule; constructor(name: string, options: FirebaseOptions) { this._name = name; @@ -52,15 +72,15 @@ export default class FirebaseApp { // modules this.admob = this._staticsOrModuleInstance(AdMobStatics, AdMob); + this.analytics = this._staticsOrModuleInstance(AnalyticsStatics, Analytics); this.auth = this._staticsOrModuleInstance(AuthStatics, Auth); - this.analytics = this._staticsOrModuleInstance({}, Analytics); - this.config = this._staticsOrModuleInstance({}, RemoteConfig); - this.crash = this._staticsOrModuleInstance({}, Crash); + this.config = this._staticsOrModuleInstance(ConfigStatics, Config); + this.crash = this._staticsOrModuleInstance(CrashStatics, Crash); this.database = this._staticsOrModuleInstance(DatabaseStatics, Database); this.firestore = this._staticsOrModuleInstance(FirestoreStatics, Firestore); this.links = this._staticsOrModuleInstance(LinksStatics, Links); this.messaging = this._staticsOrModuleInstance(MessagingStatics, Messaging); - this.perf = this._staticsOrModuleInstance({}, Performance); + this.perf = this._staticsOrModuleInstance(PerformanceStatics, Performance); this.storage = this._staticsOrModuleInstance(StorageStatics, Storage); this.utils = this._staticsOrModuleInstance(UtilsStatics, Utils); this._extendedProps = {}; @@ -171,8 +191,8 @@ export default class FirebaseApp { * @return {function()} * @private */ - _staticsOrModuleInstance(statics: Object = {}, InstanceClass: Class<*>) { - const getInstance = () => { + _staticsOrModuleInstance(statics: S, InstanceClass: Class): FirebaseModuleAndStatics { + const getInstance = (): M => { const _name = `_${InstanceClass._NAMESPACE}`; if (isAndroid && InstanceClass._NAMESPACE !== Utils._NAMESPACE && !INTERNALS.FLAGS.checkedPlayServices) { @@ -187,10 +207,8 @@ export default class FirebaseApp { return this._namespaces[_name]; }; - Object.assign(getInstance, statics, { + return Object.assign(getInstance, statics, { nativeModuleExists: !!NativeModules[InstanceClass._NATIVE_MODULE], }); - - return getInstance; } } diff --git a/lib/modules/core/firebase.js b/lib/modules/core/firebase.js index b9a036f9..37e055c6 100644 --- a/lib/modules/core/firebase.js +++ b/lib/modules/core/firebase.js @@ -11,34 +11,53 @@ import { isObject, isString } from '../../utils'; // module imports import AdMob, { statics as AdMobStatics } from '../admob'; import Auth, { statics as AuthStatics } from '../auth'; -import Analytics from '../analytics'; -import Crash from '../crash'; -import Performance from '../perf'; -import Links, { statics as LinksStatics } from '../links'; -import RemoteConfig from '../config'; -import Storage, { statics as StorageStatics } from '../storage'; +import Analytics, { statics as AnalyticsStatics } from '../analytics'; +import Config, { statics as ConfigStatics } from '../config'; +import Crash, { statics as CrashStatics } from '../crash'; import Database, { statics as DatabaseStatics } from '../database'; -import Messaging, { statics as MessagingStatics } from '../messaging'; import Firestore, { statics as FirestoreStatics } from '../firestore'; +import Links, { statics as LinksStatics } from '../links'; +import Messaging, { statics as MessagingStatics } from '../messaging'; +import Performance, { statics as PerformanceStatics } from '../perf'; +import Storage, { statics as StorageStatics } from '../storage'; import Utils, { statics as UtilsStatics } from '../utils'; +import type { + AdMobModule, + AnalyticsModule, + AuthModule, + ConfigModule, + CrashModule, + DatabaseModule, + FirebaseModule, + FirebaseModuleAndStatics, + FirebaseOptions, + FirebaseStatics, + FirestoreModule, + LinksModule, + MessagingModule, + PerformanceModule, + StorageModule, + UtilsModule, +} from '../../types'; + const FirebaseCoreModule = NativeModules.RNFirebase; class FirebaseCore { _nativeEmitters: { [string]: NativeEventEmitter }; _nativeSubscriptions: { [string]: boolean }; - admob: () => AdMob; - auth: () => Auth; - analytics: () => Analytics; - config: () => RemoteConfig; - crash: () => Crash; - database: () => Database; - firestore: () => Firestore; - links: () => Links; - messaging: () => Messaging; - perf: () => Performance; - storage: () => Storage; - utils: () => Utils; + admob: AdMobModule; + analytics: AnalyticsModule; + auth: AuthModule; + config: ConfigModule; + crash: CrashModule; + database: DatabaseModule; + firestore: FirestoreModule; + links: LinksModule; + messaging: MessagingModule; + perf: PerformanceModule; + storage: StorageModule; + utils: UtilsModule; constructor() { this._nativeEmitters = {}; @@ -52,15 +71,15 @@ class FirebaseCore { // modules this.admob = this._appNamespaceOrStatics(AdMobStatics, AdMob); + this.analytics = this._appNamespaceOrStatics(AnalyticsStatics, Analytics); this.auth = this._appNamespaceOrStatics(AuthStatics, Auth); - this.analytics = this._appNamespaceOrStatics({}, Analytics); - this.config = this._appNamespaceOrStatics({}, RemoteConfig); - this.crash = this._appNamespaceOrStatics({}, Crash); + this.config = this._appNamespaceOrStatics(ConfigStatics, Config); + this.crash = this._appNamespaceOrStatics(CrashStatics, Crash); this.database = this._appNamespaceOrStatics(DatabaseStatics, Database); this.firestore = this._appNamespaceOrStatics(FirestoreStatics, Firestore); this.links = this._appNamespaceOrStatics(LinksStatics, Links); this.messaging = this._appNamespaceOrStatics(MessagingStatics, Messaging); - this.perf = this._appNamespaceOrStatics(DatabaseStatics, Performance); + this.perf = this._appNamespaceOrStatics(PerformanceStatics, Performance); this.storage = this._appNamespaceOrStatics(StorageStatics, Storage); this.utils = this._appNamespaceOrStatics(UtilsStatics, Utils); } @@ -160,7 +179,7 @@ class FirebaseCore { * A (read-only) array of all initialized apps. * @return {Array} */ - get apps(): Array { + get apps(): Array { return Object.values(INTERNALS.APPS); } @@ -201,7 +220,7 @@ class FirebaseCore { * @return {function(FirebaseApp=)} * @private */ - _appNamespaceOrStatics(statics: Object = {}, InstanceClass: Class<*>): Function { + _appNamespaceOrStatics(statics: S, InstanceClass: Class): FirebaseModuleAndStatics { const namespace = InstanceClass._NAMESPACE; const getNamespace = (app?: FirebaseApp) => { @@ -216,11 +235,9 @@ class FirebaseCore { return INTERNALS.APPS[_app._name][namespace](_app); }; - Object.assign(getNamespace, statics, { + return Object.assign(getNamespace, statics, { nativeModuleExists: !!NativeModules[InstanceClass._NATIVE_MODULE], }); - - return getNamespace; } /** diff --git a/lib/modules/crash/index.js b/lib/modules/crash/index.js index 2fa2ad74..70a677e7 100644 --- a/lib/modules/crash/index.js +++ b/lib/modules/crash/index.js @@ -1,5 +1,10 @@ -// @flow -import ModuleBase from './../../utils/ModuleBase'; +/** + * @flow + * Crash Reporting representation wrapper + */ +import ModuleBase from '../../utils/ModuleBase'; + +import type { FirebaseError } from '../../types'; export default class Crash extends ModuleBase { static _NAMESPACE = 'crash'; @@ -71,3 +76,5 @@ export default class Crash extends ModuleBase { this._native.report(errorMessage); } } + +export const statics = {}; diff --git a/lib/modules/database/query.js b/lib/modules/database/query.js index ce1e41b0..9cd75760 100644 --- a/lib/modules/database/query.js +++ b/lib/modules/database/query.js @@ -3,7 +3,9 @@ */ import Reference from './reference.js'; -import { objectToUniqueId } from './../../utils'; +import { objectToUniqueId } from '../../utils'; + +import type { DatabaseModifier } from '../../types'; // todo doc methods diff --git a/lib/modules/database/reference.js b/lib/modules/database/reference.js index c5ff9e2c..afed604a 100644 --- a/lib/modules/database/reference.js +++ b/lib/modules/database/reference.js @@ -5,7 +5,7 @@ import Query from './query.js'; import Snapshot from './snapshot'; import Disconnect from './disconnect'; -import ReferenceBase from './../../utils/ReferenceBase'; +import ReferenceBase from '../../utils/ReferenceBase'; import { promiseOrCallback, @@ -15,10 +15,12 @@ import { tryJSONParse, tryJSONStringify, generatePushID, -} from './../../utils'; +} from '../../utils'; import INTERNALS from '../../utils/internals'; +import type { DatabaseModifier, FirebaseError } from '../../types'; + // track all event registrations by path let listeners = 0; @@ -35,6 +37,13 @@ const ReferenceEventTypes = { child_moved: 'child_moved', }; +type DatabaseListener = { + listenerId: number; + eventName: string; + successCallback: Function; + failureCallback?: Function; +} + /** * @typedef {String} ReferenceLocation - Path to location in the database, relative * to the root reference. Consists of a path where segments are separated by a diff --git a/lib/modules/firestore/CollectionReference.js b/lib/modules/firestore/CollectionReference.js index 6a906be9..7b0794bf 100644 --- a/lib/modules/firestore/CollectionReference.js +++ b/lib/modules/firestore/CollectionReference.js @@ -7,6 +7,7 @@ import Query from './Query'; import { firestoreAutoId } from '../../utils'; import type Firestore from './'; +import type { FirestoreQueryDirection, FirestoreQueryOperator } from '../../types'; import type Path from './Path'; import type QuerySnapshot from './QuerySnapshot'; diff --git a/lib/modules/firestore/DocumentChange.js b/lib/modules/firestore/DocumentChange.js index ffcda39d..c0656d0a 100644 --- a/lib/modules/firestore/DocumentChange.js +++ b/lib/modules/firestore/DocumentChange.js @@ -5,6 +5,7 @@ import DocumentSnapshot from './DocumentSnapshot'; import type Firestore from './'; +import type { FirestoreNativeDocumentChange } from '../../types'; /** * @class DocumentChange diff --git a/lib/modules/firestore/DocumentReference.js b/lib/modules/firestore/DocumentReference.js index aff4d304..b47c88c6 100644 --- a/lib/modules/firestore/DocumentReference.js +++ b/lib/modules/firestore/DocumentReference.js @@ -8,6 +8,7 @@ import { buildNativeMap } from './utils/serialize'; import { firestoreAutoId, isFunction, isObject, isString } from '../../utils'; import type Firestore from './'; +import type { FirestoreNativeDocumentSnapshot, FirestoreWriteOptions } from '../../types'; import type Path from './Path'; type DocumentListenOptions = { diff --git a/lib/modules/firestore/DocumentSnapshot.js b/lib/modules/firestore/DocumentSnapshot.js index ab2bb378..dc74fe4c 100644 --- a/lib/modules/firestore/DocumentSnapshot.js +++ b/lib/modules/firestore/DocumentSnapshot.js @@ -7,6 +7,7 @@ import Path from './Path'; import { parseNativeMap } from './utils/serialize'; import type Firestore from './'; +import type { FirestoreNativeDocumentSnapshot, FirestoreSnapshotMetadata } from '../../types'; /** * @class DocumentSnapshot diff --git a/lib/modules/firestore/Query.js b/lib/modules/firestore/Query.js index 81561b47..507399ff 100644 --- a/lib/modules/firestore/Query.js +++ b/lib/modules/firestore/Query.js @@ -8,6 +8,7 @@ import { buildNativeArray, buildTypeMap } from './utils/serialize'; import { firestoreAutoId, isFunction, isObject } from '../../utils'; import type Firestore from './'; +import type { FirestoreQueryDirection, FirestoreQueryOperator } from '../../types'; import type Path from './Path'; const DIRECTIONS: { [FirestoreQueryDirection]: string } = { diff --git a/lib/modules/firestore/QuerySnapshot.js b/lib/modules/firestore/QuerySnapshot.js index 659815aa..67d57f5e 100644 --- a/lib/modules/firestore/QuerySnapshot.js +++ b/lib/modules/firestore/QuerySnapshot.js @@ -6,6 +6,7 @@ import DocumentChange from './DocumentChange'; import DocumentSnapshot from './DocumentSnapshot'; import type Firestore from './'; +import type { FirestoreNativeDocumentChange, FirestoreNativeDocumentSnapshot, FirestoreSnapshotMetadata } from '../../types'; import type Query from './Query'; type QuerySnapshotNativeData = { diff --git a/lib/modules/firestore/WriteBatch.js b/lib/modules/firestore/WriteBatch.js index 77318c3c..6d687ac9 100644 --- a/lib/modules/firestore/WriteBatch.js +++ b/lib/modules/firestore/WriteBatch.js @@ -7,6 +7,7 @@ import { isObject, isString } from '../../utils'; import type DocumentReference from './DocumentReference'; import type Firestore from './'; +import type { FirestoreWriteOptions } from '../../types'; type DocumentWrite = { data?: Object, diff --git a/lib/modules/firestore/index.js b/lib/modules/firestore/index.js index b1270c97..8d463a20 100644 --- a/lib/modules/firestore/index.js +++ b/lib/modules/firestore/index.js @@ -31,10 +31,7 @@ type DocumentSyncEvent = { path: string, } -/** - * @class Firestore - */ -export default class Firestore extends ModuleBase { +class FirestoreInternalModule extends ModuleBase { static _NAMESPACE = 'firestore'; static _NATIVE_MODULE = 'RNFirebaseFirestore'; @@ -44,14 +41,14 @@ export default class Firestore extends ModuleBase { super(firebaseApp, options, true); this._referencePath = new Path([]); - this.addListener( + super.addListener( // sub to internal native event - this fans out to // public event name: onCollectionSnapshot super._getAppEventName('firestore_collection_sync_event'), this._onCollectionSyncEvent.bind(this), ); - this.addListener( + super.addListener( // sub to internal native event - this fans out to // public event name: onDocumentSnapshot super._getAppEventName('firestore_document_sync_event'), @@ -59,58 +56,6 @@ export default class Firestore extends ModuleBase { ); } - batch(): WriteBatch { - return new WriteBatch(this); - } - - /** - * - * @param collectionPath - * @returns {CollectionReference} - */ - collection(collectionPath: string): CollectionReference { - const path = this._referencePath.child(collectionPath); - if (!path.isCollection) { - throw new Error('Argument "collectionPath" must point to a collection.'); - } - - return new CollectionReference(this, path); - } - - /** - * - * @param documentPath - * @returns {DocumentReference} - */ - doc(documentPath: string): DocumentReference { - const path = this._referencePath.child(documentPath); - if (!path.isDocument) { - throw new Error('Argument "documentPath" must point to a document.'); - } - - return new DocumentReference(this, path); - } - - enablePersistence(): Promise { - throw new Error('Persistence is enabled by default on the Firestore SDKs'); - } - - runTransaction(): Promise { - throw new Error('firebase.firestore().runTransaction() coming soon'); - } - - setLogLevel(): void { - throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Firestore, 'setLogLevel')); - } - - settings(): void { - throw new Error('firebase.firestore().settings() coming soon'); - } - - /** - * INTERNALS - */ - /** * Internal collection sync listener * @param event @@ -138,6 +83,63 @@ export default class Firestore extends ModuleBase { } } +/** + * @class Firestore + */ +export default class Firestore extends FirestoreInternalModule { + constructor(firebaseApp: FirebaseApp, options: Object = {}) { + super(firebaseApp, options); + } + + batch(): WriteBatch { + return new WriteBatch(this); + } + + /** + * + * @param collectionPath + * @returns {CollectionReference} + */ + collection(collectionPath: string): CollectionReference { + const path = super._referencePath.child(collectionPath); + if (!path.isCollection) { + throw new Error('Argument "collectionPath" must point to a collection.'); + } + + return new CollectionReference(this, path); + } + + /** + * + * @param documentPath + * @returns {DocumentReference} + */ + doc(documentPath: string): DocumentReference { + const path = super._referencePath.child(documentPath); + if (!path.isDocument) { + throw new Error('Argument "documentPath" must point to a document.'); + } + + return new DocumentReference(this, path); + } + + enablePersistence(): Promise { + throw new Error('Persistence is enabled by default on the Firestore SDKs'); + } + + runTransaction(): Promise { + throw new Error('firebase.firestore().runTransaction() coming soon'); + } + + setLogLevel(): void { + throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Firestore, 'setLogLevel')); + } + + settings(): void { + throw new Error('firebase.firestore().settings() coming soon'); + } +} + export const statics = { FieldValue, GeoPoint, diff --git a/lib/modules/firestore/utils/serialize.js b/lib/modules/firestore/utils/serialize.js index 74fd2697..a3ae0c50 100644 --- a/lib/modules/firestore/utils/serialize.js +++ b/lib/modules/firestore/utils/serialize.js @@ -9,6 +9,7 @@ import Path from '../Path'; import { typeOf } from '../../../utils'; import type Firestore from '../'; +import type { FirestoreTypeMap } from '../../../types'; /* * Functions that build up the data needed to represent diff --git a/lib/modules/perf/index.js b/lib/modules/perf/index.js index 3d25ecfb..496ce59a 100644 --- a/lib/modules/perf/index.js +++ b/lib/modules/perf/index.js @@ -29,3 +29,5 @@ export default class PerformanceMonitoring extends ModuleBase { return new Trace(this, trace); } } + +export const statics = {}; diff --git a/lib/modules/utils/index.js b/lib/modules/utils/index.js index 4054dc93..c7325462 100644 --- a/lib/modules/utils/index.js +++ b/lib/modules/utils/index.js @@ -5,11 +5,20 @@ import { NativeModules } from 'react-native'; import INTERNALS from '../../utils/internals'; import { isIOS } from '../../utils'; +import ModuleBase from '../../utils/ModuleBase'; import PACKAGE from '../../../package.json'; const FirebaseCoreModule = NativeModules.RNFirebase; -export default class RNFirebaseUtils { +type GoogleApiAvailabilityType = { + status: number, + isAvailable: boolean, + isUserResolvableError?: boolean, + hasResolution?: boolean, + error?: string +} + +export default class RNFirebaseUtils extends ModuleBase { static _NAMESPACE = 'utils'; static _NATIVE_DISABLED = true; static _NATIVE_MODULE = 'RNFirebaseUtils'; @@ -105,7 +114,7 @@ export default class RNFirebaseUtils { * @android * @param bool */ - set errorOnMissingPlayServices(bool: Boolean) { + set errorOnMissingPlayServices(bool: boolean) { INTERNALS.OPTIONS.errorOnMissingPlayServices = bool; } @@ -114,7 +123,7 @@ export default class RNFirebaseUtils { * @android * @param bool */ - set promptOnMissingPlayServices(bool: Boolean) { + set promptOnMissingPlayServices(bool: boolean) { INTERNALS.OPTIONS.promptOnMissingPlayServices = bool; } } diff --git a/lib/types/flow.js b/lib/types/flow.js deleted file mode 100644 index 71c478e8..00000000 --- a/lib/types/flow.js +++ /dev/null @@ -1,93 +0,0 @@ -/* eslint-disable */ -/* Core types */ -declare class FirebaseError { - message: string, - name: string, - code: string, - stack: string, - path: string, - details: string, - modifiers: string -}; - -declare type FirebaseOptions = { - apiKey: string, - appId: string, - databaseURL: string, - messagingSenderId: string, - projectId: string, - storageBucket: string, -} - -/* Auth types */ - -declare type AuthResult = { - authenticated: boolean, - user: Object|null -} | null; - -declare type AuthCredential = { - providerId: string, - token: string, - secret: string -}; - -/* Database types */ - -declare type DatabaseListener = { - listenerId: number; - eventName: string; - successCallback: Function; - failureCallback?: Function; -}; - -declare type DatabaseModifier = { - type: 'orderBy' | 'limit' | 'filter'; - name?: string; - key?: string; - limit?: number; - value?: any; - valueType?: string; -}; - -/* Firestore types */ - -declare type FirestoreNativeDocumentChange = { - document: FirestoreNativeDocumentSnapshot, - newIndex: number, - oldIndex: number, - type: string, -} - -declare type FirestoreNativeDocumentSnapshot = { - data: { [string]: FirestoreTypeMap }, - metadata: FirestoreSnapshotMetadata, - path: string, -} - -declare type FirestoreSnapshotMetadata = { - fromCache: boolean, - hasPendingWrites: boolean, -} - -declare type FirestoreQueryDirection = 'DESC' | 'desc' | 'ASC' | 'asc'; -declare type FirestoreQueryOperator = '<' | '<=' | '=' | '==' | '>' | '>='; - -declare type FirestoreTypeMap = { - type: 'array' | 'boolean' | 'date' | 'fieldvalue' | 'geopoint' | 'null' | 'number' | 'object' | 'reference' | 'string', - value: any, -} - -declare type FirestoreWriteOptions = { - merge?: boolean, -} - -/* Util types */ - -declare type GoogleApiAvailabilityType = { - status: number, - isAvailable: boolean, - isUserResolvableError?: boolean, - hasResolution?: boolean, - error?: string -}; diff --git a/lib/types/index.js b/lib/types/index.js new file mode 100644 index 00000000..40b53a3a --- /dev/null +++ b/lib/types/index.js @@ -0,0 +1,187 @@ +/* @flow */ +import type AdMob from '../modules/admob'; +import { typeof statics as AdMobStatics } from '../modules/admob'; +import type Analytics from '../modules/analytics'; +import { typeof statics as AnalyticsStatics } from '../modules/analytics'; +import type Auth from '../modules/auth'; +import { typeof statics as AuthStatics } from '../modules/auth'; +import type Config from '../modules/config'; +import { typeof statics as ConfigStatics } from '../modules/config'; +import type Crash from '../modules/crash'; +import { typeof statics as CrashStatics } from '../modules/crash'; +import type Database from '../modules/database'; +import { typeof statics as DatabaseStatics } from '../modules/database'; +import type Firestore from '../modules/firestore'; +import { typeof statics as FirestoreStatics } from '../modules/firestore'; +import type Links from '../modules/links'; +import { typeof statics as LinksStatics } from '../modules/links'; +import type Messaging from '../modules/messaging'; +import { typeof statics as MessagingStatics } from '../modules/messaging'; +import type ModuleBase from '../utils/ModuleBase'; +import type Performance from '../modules/perf'; +import { typeof statics as PerformanceStatics } from '../modules/perf'; +import type Storage from '../modules/storage'; +import { typeof statics as StorageStatics } from '../modules/storage'; +import type Utils from '../modules/utils'; +import { typeof statics as UtilsStatics } from '../modules/utils'; + +/* Core types */ +export type FirebaseError = { + message: string, + name: string, + code: string, + stack: string, + path: string, + details: string, + modifiers: string +} + +export type FirebaseModule = $Subtype; + +export type FirebaseModuleName = 'admob' | 'analytics' | 'auth' | 'config' | 'crash' | 'database' + | 'firestore' | 'links' | 'messaging' | 'perf' | 'storage' | 'utils'; + +export type FirebaseOptions = { + apiKey: string, + appId: string, + databaseURL: string, + messagingSenderId: string, + projectId: string, + storageBucket: string, +} + +export type FirebaseModuleAndStatics = { + (): M, + nativeModuleExists: boolean, +} & S; + +export type FirebaseStatics = $Subtype; + +/* Admob types */ + +export type AdMobModule = { + (): AdMob, + nativeModuleExists: boolean, +} & AdMobStatics; + +/* Analytics types */ + +export type AnalyticsModule = { + (): Analytics, + nativeModuleExists: boolean, +} & AnalyticsStatics; + +/* Remote Config types */ + +export type ConfigModule = { + (): Config, + nativeModuleExists: boolean, +} & ConfigStatics; + +export type AuthCredential = { + providerId: string, + token: string, + secret: string +} + +/* Auth types */ + +export type AuthModule = { + (): Auth, + nativeModuleExists: boolean, +} & AuthStatics; + +/* Crash types */ + +export type CrashModule = { + (): Crash, + nativeModuleExists: boolean, +} & CrashStatics; + +/* Database types */ + +export type DatabaseModule = { + (): Database, + nativeModuleExists: boolean, +} & DatabaseStatics; + +export type DatabaseModifier = { + type: 'orderBy' | 'limit' | 'filter'; + name?: string; + key?: string; + limit?: number; + value?: any; + valueType?: string; +} + +/* Firestore types */ + +export type FirestoreModule = { + (): Firestore, + nativeModuleExists: boolean, +} & FirestoreStatics; + +export type FirestoreNativeDocumentChange = { + document: FirestoreNativeDocumentSnapshot, + newIndex: number, + oldIndex: number, + type: string, +} + +export type FirestoreNativeDocumentSnapshot = { + data: { [string]: FirestoreTypeMap }, + metadata: FirestoreSnapshotMetadata, + path: string, +} + +export type FirestoreSnapshotMetadata = { + fromCache: boolean, + hasPendingWrites: boolean, +} + +export type FirestoreQueryDirection = 'DESC' | 'desc' | 'ASC' | 'asc'; +export type FirestoreQueryOperator = '<' | '<=' | '=' | '==' | '>' | '>='; + +export type FirestoreTypeMap = { + type: 'array' | 'boolean' | 'date' | 'fieldvalue' | 'geopoint' | 'null' | 'number' | 'object' | 'reference' | 'string', + value: any, +} + +export type FirestoreWriteOptions = { + merge?: boolean, +} + +/* Links types */ + +export type LinksModule = { + (): Links, + nativeModuleExists: boolean, +} & LinksStatics; + +/* Messaging types */ + +export type MessagingModule = { + (): Messaging, + nativeModuleExists: boolean, +} & MessagingStatics; + +/* Performance types */ + +export type PerformanceModule = { + (): Performance, + nativeModuleExists: boolean, +} & PerformanceStatics; + +/* Storage types */ + +export type StorageModule = { + (): Storage, + nativeModuleExists: boolean, +} & StorageStatics; + +/* Utils types */ + +export type UtilsModule = { + (): Utils, + nativeModuleExists: boolean, +} & UtilsStatics; diff --git a/lib/utils/ModuleBase.js b/lib/utils/ModuleBase.js index bbb0042d..5bed12a6 100644 --- a/lib/utils/ModuleBase.js +++ b/lib/utils/ModuleBase.js @@ -9,6 +9,7 @@ import FirebaseCore from '../modules/core/firebase'; import { nativeWithApp } from '../utils'; import type FirebaseApp from '../modules/core/firebase-app'; +import type { FirebaseModuleName } from '../types'; const logs = {}; @@ -53,7 +54,7 @@ export default class ModuleBase { _namespace: string; _firebaseApp: FirebaseApp; _eventEmitter: Object; - static _NAMESPACE: string; + static _NAMESPACE: FirebaseModuleName; static _NATIVE_MODULE: string; /** diff --git a/lib/utils/SyncTree.js b/lib/utils/SyncTree.js index d8349ef4..6cd4acb1 100644 --- a/lib/utils/SyncTree.js +++ b/lib/utils/SyncTree.js @@ -3,10 +3,10 @@ */ import { NativeEventEmitter } from 'react-native'; -import INTERNALS from './../internals'; -import DatabaseSnapshot from './../modules/database/snapshot'; -import DatabaseReference from './../modules/database/reference'; -import { isString, nativeToJSError } from './../utils'; +import INTERNALS from './internals'; +import DatabaseSnapshot from '../modules/database/snapshot'; +import DatabaseReference from '../modules/database/reference'; +import { isString, nativeToJSError } from '../utils'; type Registration = { key: string, diff --git a/lib/utils/internals.js b/lib/utils/internals.js index 87cd42b2..efab8da1 100644 --- a/lib/utils/internals.js +++ b/lib/utils/internals.js @@ -7,6 +7,8 @@ import EventEmitter from './emitter/EventEmitter'; import ModuleBase from './ModuleBase'; import SyncTree from './SyncTree'; +import type FirebaseApp from '../modules/core/firebase-app'; + const DEFAULT_APP_NAME = Platform.OS === 'ios' ? '__FIRAPP_DEFAULT' : '[DEFAULT]'; const NAMESPACE_PODS = { @@ -53,6 +55,8 @@ const PLAY_SERVICES_CODES = { }, }; +const APPS: { [string]: FirebaseApp } = {}; + export default { // default options OPTIONS: { @@ -66,9 +70,7 @@ export default { }, // track all initialized firebase apps - APPS: { - [DEFAULT_APP_NAME]: null, - }, + APPS, STRINGS: { WARN_INITIALIZE_DEPRECATION: 'Deprecation: Calling \'initializeApp()\' for apps that are already initialised natively ' + diff --git a/package-lock.json b/package-lock.json index df11263f..ba380f04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "3.1.0", + "version": "3.1.1-alpha.11", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ac77b3dd..f3663876 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "3.1.1-alpha.4", + "version": "3.1.1-alpha.11", "author": "Invertase (http://invertase.io)", "description": "A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Messaging (FCM), Remote Config, Storage and Performance.", "main": "dist/index.js", @@ -20,9 +20,6 @@ "tests-watch-start": "npm run test-cli watch init start", "tests-watch-stop": "npm run test-cli watch stop" }, - "files": [ - "dist" - ], "repository": { "type": "git", "url": "https://github.com/invertase/react-native-firebase.git" diff --git a/tests/ios/Podfile.lock b/tests/ios/Podfile.lock index f6bb69d9..71d4438c 100644 --- a/tests/ios/Podfile.lock +++ b/tests/ios/Podfile.lock @@ -150,7 +150,7 @@ PODS: - React/Core - React/fishhook - React/RCTBlob - - RNFirebase (3.1.0): + - RNFirebase (3.1.1-alpha.11): - React - yoga (0.49.1.React) @@ -208,7 +208,7 @@ SPEC CHECKSUMS: nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3 Protobuf: 03eef2ee0b674770735cf79d9c4d3659cf6908e8 React: cf892fb84b7d06bf5fea7f328e554c6dcabe85ee - RNFirebase: 1b8adf4dfe740fbc4a69a147715c2edfd041eb92 + RNFirebase: e959075eb2f348c3586cd92973543b80e373b29c yoga: 3abf02d6d9aeeb139b4c930eb1367feae690a35a PODFILE CHECKSUM: b5674be55653f5dda937c8b794d0479900643d45 From 11e5bc2ae7214e798b8036c4a57a7c789c55da12 Mon Sep 17 00:00:00 2001 From: Salakar Date: Tue, 28 Nov 2017 07:41:37 +0000 Subject: [PATCH 10/56] [android][firestore] added `enableLogging(boolean)` method --- .../firebase/firestore/RNFirebaseFirestore.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestore.java b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestore.java index d89c3093..0d0ba858 100644 --- a/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestore.java +++ b/android/src/main/java/io/invertase/firebase/firestore/RNFirebaseFirestore.java @@ -10,7 +10,6 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; @@ -27,7 +26,6 @@ import java.util.List; import java.util.Map; import io.invertase.firebase.ErrorUtils; -import io.invertase.firebase.Utils; public class RNFirebaseFirestore extends ReactContextBaseJavaModule { @@ -42,6 +40,16 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule { /* * REACT NATIVE METHODS */ + + /** + * @param enabled + */ + @ReactMethod + public void enableLogging(Boolean enabled) { + FirebaseFirestore.setLoggingEnabled(enabled); + } + + @ReactMethod public void collectionGet(String appName, String path, ReadableArray filters, ReadableArray orders, ReadableMap options, final Promise promise) { From 54e904e22faa82745cd346c88881eff3100954c5 Mon Sep 17 00:00:00 2001 From: Salakar Date: Tue, 28 Nov 2017 07:41:55 +0000 Subject: [PATCH 11/56] [js][firestore] added `enableLogging(boolean)` method --- lib/modules/firestore/index.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/modules/firestore/index.js b/lib/modules/firestore/index.js index b1270c97..f18b6f75 100644 --- a/lib/modules/firestore/index.js +++ b/lib/modules/firestore/index.js @@ -2,6 +2,8 @@ * @flow * Firestore representation wrapper */ +import { NativeModules } from 'react-native'; + import ModuleBase from './../../utils/ModuleBase'; import CollectionReference from './CollectionReference'; import DocumentReference from './DocumentReference'; @@ -141,4 +143,9 @@ export default class Firestore extends ModuleBase { export const statics = { FieldValue, GeoPoint, + enableLogging(bool) { + if (NativeModules[Firestore._NATIVE_MODULE]) { + NativeModules[Firestore._NATIVE_MODULE].enableLogging(bool); + } + }, }; From 66fcbd5c243b8da3921fe4972576947f5dc09b15 Mon Sep 17 00:00:00 2001 From: Salakar Date: Tue, 28 Nov 2017 08:02:05 +0000 Subject: [PATCH 12/56] [ios][firestore] added `enableLogging(boolean)` method --- ios/RNFirebase/firestore/RNFirebaseFirestore.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ios/RNFirebase/firestore/RNFirebaseFirestore.m b/ios/RNFirebase/firestore/RNFirebaseFirestore.m index c9510f47..29d8646d 100644 --- a/ios/RNFirebase/firestore/RNFirebaseFirestore.m +++ b/ios/RNFirebase/firestore/RNFirebaseFirestore.m @@ -18,6 +18,10 @@ RCT_EXPORT_MODULE(); return self; } +RCT_EXPORT_METHOD(enableLogging:(BOOL) enabled) { + [FIRFirestore enableLogging:enabled]; +} + RCT_EXPORT_METHOD(collectionGet:(NSString *) appName path:(NSString *) path filters:(NSArray *) filters From 13c43f2efe960941dc659c0f8357c7201eaf70f9 Mon Sep 17 00:00:00 2001 From: Salakar Date: Tue, 28 Nov 2017 08:02:24 +0000 Subject: [PATCH 13/56] [tests][android] update sdks to 11.6.2 --- tests/android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/android/app/build.gradle b/tests/android/app/build.gradle index ea0afb68..83c93fac 100644 --- a/tests/android/app/build.gradle +++ b/tests/android/app/build.gradle @@ -72,7 +72,7 @@ android { } } -project.ext.firebaseVersion = '11.4.2' +project.ext.firebaseVersion = '11.6.2' dependencies { // compile(project(':react-native-firebase')) { From a94943bfc06b071370909d31597c6bc19e751765 Mon Sep 17 00:00:00 2001 From: Salakar Date: Tue, 28 Nov 2017 09:09:58 +0000 Subject: [PATCH 14/56] fix imports --- .../firebase/database/RNFirebaseDatabase.java | 25 ++++++++++++++----- lib/utils/SyncTree.js | 2 +- tests/src/firebase.js | 2 +- tests/src/tests/core/coreTests.js | 2 +- tests/src/tests/storage/storageTests.js | 2 +- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java b/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java index ef130caa..e9900a40 100644 --- a/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java +++ b/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java @@ -13,6 +13,7 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.google.firebase.FirebaseApp; +import com.google.firebase.database.DatabaseException; import com.google.firebase.database.Logger; import com.google.firebase.database.MutableData; import com.google.firebase.database.OnDisconnect; @@ -35,6 +36,7 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule { private static final String TAG = "RNFirebaseDatabase"; private boolean enableLogging = false; private HashMap references = new HashMap<>(); + private HashMap loggingLevelSet = new HashMap<>(); private SparseArray transactionHandlers = new SparseArray<>(); RNFirebaseDatabase(ReactApplicationContext reactContext) { @@ -89,6 +91,8 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule { enableLogging = enabled; List firebaseAppList = FirebaseApp.getApps(getReactApplicationContext()); for (FirebaseApp app : firebaseAppList) { + loggingLevelSet.put(app.getName(), enabled); + if (enableLogging) { FirebaseDatabase.getInstance(app).setLogLevel(Logger.Level.DEBUG); } else { @@ -488,12 +492,21 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule { FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance(firebaseApp); -// todo errors 'calls must be made before any other usage of database instance -// if (enableLogging) { -// firebaseDatabase.setLogLevel(Logger.Level.DEBUG); -// } else { -// firebaseDatabase.setLogLevel(Logger.Level.WARN); -// } + if (enableLogging && !loggingLevelSet.get(firebaseDatabase.getApp().getName())) { + try { + loggingLevelSet.put(firebaseDatabase.getApp().getName(), enableLogging); + firebaseDatabase.setLogLevel(Logger.Level.DEBUG); + } catch (DatabaseException dex) { + // do nothing - to catch 'calls to setLogLevel must be made for use of database' errors + } + } else if (!enableLogging && loggingLevelSet.get(firebaseDatabase.getApp().getName())) { + try { + loggingLevelSet.put(firebaseDatabase.getApp().getName(), enableLogging); + firebaseDatabase.setLogLevel(Logger.Level.WARN); + } catch (DatabaseException dex) { + // do nothing - to catch 'calls to setLogLevel must be made for use of database' errors + } + } return firebaseDatabase; } diff --git a/lib/utils/SyncTree.js b/lib/utils/SyncTree.js index d8349ef4..bf726889 100644 --- a/lib/utils/SyncTree.js +++ b/lib/utils/SyncTree.js @@ -3,7 +3,7 @@ */ import { NativeEventEmitter } from 'react-native'; -import INTERNALS from './../internals'; +import INTERNALS from './internals'; import DatabaseSnapshot from './../modules/database/snapshot'; import DatabaseReference from './../modules/database/reference'; import { isString, nativeToJSError } from './../utils'; diff --git a/tests/src/firebase.js b/tests/src/firebase.js index 22709803..033b438b 100644 --- a/tests/src/firebase.js +++ b/tests/src/firebase.js @@ -1,7 +1,7 @@ import { Platform } from 'react-native'; import firebase from 'firebase'; -import RNfirebase from './../firebase/firebase'; +import RNfirebase from './../firebase'; import DatabaseContents from './tests/support/DatabaseContents'; diff --git a/tests/src/tests/core/coreTests.js b/tests/src/tests/core/coreTests.js index cd25a62d..d96e5d78 100644 --- a/tests/src/tests/core/coreTests.js +++ b/tests/src/tests/core/coreTests.js @@ -1,7 +1,7 @@ import { Platform } from 'react-native'; import should from 'should'; -import RNFirebase from './../../../firebase/firebase'; +import RNFirebase from './../../../firebase'; const androidTestConfig = { // firebase android sdk completely ignores client id diff --git a/tests/src/tests/storage/storageTests.js b/tests/src/tests/storage/storageTests.js index 90d9d61a..2aa78578 100644 --- a/tests/src/tests/storage/storageTests.js +++ b/tests/src/tests/storage/storageTests.js @@ -1,4 +1,4 @@ -import RNfirebase from './../../../firebase/firebase'; +import RNfirebase from './../../../firebase'; function storageTests({ describe, it, firebase, tryCatch }) { describe('ref(:path)', () => { From 1f5231cfba9dca6c6a7e98bcdd9447b731889c75 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Tue, 28 Nov 2017 09:20:57 +0000 Subject: [PATCH 15/56] [tests] Fix incorrect imports --- tests/src/firebase.js | 2 +- tests/src/tests/core/coreTests.js | 2 +- tests/src/tests/storage/storageTests.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/src/firebase.js b/tests/src/firebase.js index 22709803..033b438b 100644 --- a/tests/src/firebase.js +++ b/tests/src/firebase.js @@ -1,7 +1,7 @@ import { Platform } from 'react-native'; import firebase from 'firebase'; -import RNfirebase from './../firebase/firebase'; +import RNfirebase from './../firebase'; import DatabaseContents from './tests/support/DatabaseContents'; diff --git a/tests/src/tests/core/coreTests.js b/tests/src/tests/core/coreTests.js index cd25a62d..d96e5d78 100644 --- a/tests/src/tests/core/coreTests.js +++ b/tests/src/tests/core/coreTests.js @@ -1,7 +1,7 @@ import { Platform } from 'react-native'; import should from 'should'; -import RNFirebase from './../../../firebase/firebase'; +import RNFirebase from './../../../firebase'; const androidTestConfig = { // firebase android sdk completely ignores client id diff --git a/tests/src/tests/storage/storageTests.js b/tests/src/tests/storage/storageTests.js index 90d9d61a..2aa78578 100644 --- a/tests/src/tests/storage/storageTests.js +++ b/tests/src/tests/storage/storageTests.js @@ -1,4 +1,4 @@ -import RNfirebase from './../../../firebase/firebase'; +import RNfirebase from './../../../firebase'; function storageTests({ describe, it, firebase, tryCatch }) { describe('ref(:path)', () => { From 5aa8435aff1e2a2d65cd2170ba8600745e21f4b7 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Tue, 28 Nov 2017 09:21:41 +0000 Subject: [PATCH 16/56] [firestore] Fix incorrect references --- lib/modules/firestore/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/modules/firestore/index.js b/lib/modules/firestore/index.js index 8d463a20..1ffd11c9 100644 --- a/lib/modules/firestore/index.js +++ b/lib/modules/firestore/index.js @@ -101,7 +101,7 @@ export default class Firestore extends FirestoreInternalModule { * @returns {CollectionReference} */ collection(collectionPath: string): CollectionReference { - const path = super._referencePath.child(collectionPath); + const path = this._referencePath.child(collectionPath); if (!path.isCollection) { throw new Error('Argument "collectionPath" must point to a collection.'); } @@ -115,7 +115,7 @@ export default class Firestore extends FirestoreInternalModule { * @returns {DocumentReference} */ doc(documentPath: string): DocumentReference { - const path = super._referencePath.child(documentPath); + const path = this._referencePath.child(documentPath); if (!path.isDocument) { throw new Error('Argument "documentPath" must point to a document.'); } From 99dfdfc982561d96e39b7e1c083c0b0138795e34 Mon Sep 17 00:00:00 2001 From: Salakar Date: Tue, 28 Nov 2017 12:27:38 +0000 Subject: [PATCH 17/56] [android][database] fix boolean issue --- .../io/invertase/firebase/database/RNFirebaseDatabase.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java b/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java index e9900a40..f02e0f8b 100644 --- a/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java +++ b/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java @@ -491,15 +491,16 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule { private FirebaseDatabase getDatabaseForApp(String appName) { FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance(firebaseApp); + Boolean logLevel = loggingLevelSet.get(firebaseDatabase.getApp().getName()); - if (enableLogging && !loggingLevelSet.get(firebaseDatabase.getApp().getName())) { + if (enableLogging && (logLevel == null || !logLevel)) { try { loggingLevelSet.put(firebaseDatabase.getApp().getName(), enableLogging); firebaseDatabase.setLogLevel(Logger.Level.DEBUG); } catch (DatabaseException dex) { // do nothing - to catch 'calls to setLogLevel must be made for use of database' errors } - } else if (!enableLogging && loggingLevelSet.get(firebaseDatabase.getApp().getName())) { + } else if (!enableLogging && (logLevel != null && logLevel)) { try { loggingLevelSet.put(firebaseDatabase.getApp().getName(), enableLogging); firebaseDatabase.setLogLevel(Logger.Level.WARN); From 961112a108981f7f115bef03b81d61491fb2978c Mon Sep 17 00:00:00 2001 From: Salakar Date: Tue, 28 Nov 2017 12:41:50 +0000 Subject: [PATCH 18/56] [internals] check _NATIVE_DISABLED before throwing native not found error --- lib/utils/ModuleBase.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/ModuleBase.js b/lib/utils/ModuleBase.js index 5bed12a6..0f89825a 100644 --- a/lib/utils/ModuleBase.js +++ b/lib/utils/ModuleBase.js @@ -74,7 +74,7 @@ export default class ModuleBase { // modules are now optionally part of build const nativeModule = NativeModules[this.constructor._NATIVE_MODULE]; - if (!nativeModule) { + if (!nativeModule && !this.constructor._NATIVE_DISABLED) { throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(this.constructor._NAMESPACE, this.constructor._NATIVE_MODULE)); } From d41c42e2888f8e0d0525d97f1d02a6cb9dffe9b6 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Tue, 28 Nov 2017 14:19:49 +0000 Subject: [PATCH 19/56] [analytics] Update to match flow typings and documentation --- .flowconfig | 3 +++ lib/modules/analytics/index.js | 18 ++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.flowconfig b/.flowconfig index c297a19a..b8353a70 100644 --- a/.flowconfig +++ b/.flowconfig @@ -76,6 +76,9 @@ # Ignore dist folder .*/dist/.* +# Ignore tests project +.*/tests/.* + [include] node_modules/fbjs/lib diff --git a/lib/modules/analytics/index.js b/lib/modules/analytics/index.js index a66927eb..cc842340 100644 --- a/lib/modules/analytics/index.js +++ b/lib/modules/analytics/index.js @@ -4,6 +4,8 @@ */ import ModuleBase from './../../utils/ModuleBase'; +import type FirebaseApp from '../core/firebase-app'; + const AlphaNumericUnderscore = /^[a-zA-Z0-9_]+$/; const ReservedEventNames = [ @@ -26,7 +28,7 @@ export default class Analytics extends ModuleBase { static _NAMESPACE = 'analytics'; static _NATIVE_MODULE = 'RNFirebaseAnalytics'; - constructor(firebaseApp: Object, options: Object = {}) { + constructor(firebaseApp: FirebaseApp, options: Object = {}) { super(firebaseApp, options); } @@ -55,7 +57,7 @@ export default class Analytics extends ModuleBase { // types are supported. String parameter values can be up to 36 characters long. The "firebase_" // prefix is reserved and should not be used for parameter names. - return this._native.logEvent(name, params); + this._native.logEvent(name, params); } /** @@ -63,7 +65,7 @@ export default class Analytics extends ModuleBase { * @param enabled */ setAnalyticsCollectionEnabled(enabled: boolean): void { - return this._native.setAnalyticsCollectionEnabled(enabled); + this._native.setAnalyticsCollectionEnabled(enabled); } /** @@ -72,7 +74,7 @@ export default class Analytics extends ModuleBase { * @param screenClassOverride */ setCurrentScreen(screenName: string, screenClassOverride: string): void { - return this._native.setCurrentScreen(screenName, screenClassOverride); + this._native.setCurrentScreen(screenName, screenClassOverride); } /** @@ -80,7 +82,7 @@ export default class Analytics extends ModuleBase { * @param milliseconds */ setMinimumSessionDuration(milliseconds: number = 10000): void { - return this._native.setMinimumSessionDuration(milliseconds); + this._native.setMinimumSessionDuration(milliseconds); } /** @@ -88,7 +90,7 @@ export default class Analytics extends ModuleBase { * @param milliseconds */ setSessionTimeoutDuration(milliseconds: number = 1800000): void { - return this._native.setSessionTimeoutDuration(milliseconds); + this._native.setSessionTimeoutDuration(milliseconds); } /** @@ -96,7 +98,7 @@ export default class Analytics extends ModuleBase { * @param id */ setUserId(id: string): void { - return this._native.setUserId(id); + this._native.setUserId(id); } /** @@ -105,7 +107,7 @@ export default class Analytics extends ModuleBase { * @param value */ setUserProperty(name: string, value: string): void { - return this._native.setUserProperty(name, value); + this._native.setUserProperty(name, value); } /** From 66a550b75574e7a4abf70915580da8626c009558 Mon Sep 17 00:00:00 2001 From: Salakar Date: Tue, 28 Nov 2017 14:47:36 +0000 Subject: [PATCH 20/56] [android][database] add enableLogging warning messages if called after db usage --- .../firebase/database/RNFirebaseDatabase.java | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java b/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java index f02e0f8b..59eb04d4 100644 --- a/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java +++ b/android/src/main/java/io/invertase/firebase/database/RNFirebaseDatabase.java @@ -1,6 +1,7 @@ package io.invertase.firebase.database; import android.os.AsyncTask; +import android.util.Log; import android.util.SparseArray; import com.facebook.react.bridge.Promise; @@ -92,11 +93,18 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule { List firebaseAppList = FirebaseApp.getApps(getReactApplicationContext()); for (FirebaseApp app : firebaseAppList) { loggingLevelSet.put(app.getName(), enabled); - - if (enableLogging) { - FirebaseDatabase.getInstance(app).setLogLevel(Logger.Level.DEBUG); - } else { - FirebaseDatabase.getInstance(app).setLogLevel(Logger.Level.WARN); + try { + if (enableLogging) { + FirebaseDatabase.getInstance(app).setLogLevel(Logger.Level.DEBUG); + } else { + FirebaseDatabase.getInstance(app).setLogLevel(Logger.Level.WARN); + } + } catch (DatabaseException dex) { + // do nothing - to catch 'calls to setLogLevel must be made for use of database' errors + // only occurs in dev after reloading or if user has actually incorrectly called it. + Log.w(TAG, "WARNING: enableLogging(bool) must be called before any other use of database(). \n" + + "If you are sure you've done this then this message can be ignored during development as \n" + + "RN reloads can cause false positives. APP: " + app.getName()); } } } @@ -499,6 +507,10 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule { firebaseDatabase.setLogLevel(Logger.Level.DEBUG); } catch (DatabaseException dex) { // do nothing - to catch 'calls to setLogLevel must be made for use of database' errors + // only occurs in dev after reloading or if user has actually incorrectly called it. + Log.w(TAG, "WARNING: enableLogging(bool) must be called before any other use of database(). \n" + + "If you are sure you've done this then this message can be ignored during development as \n" + + "RN reloads can cause false positives. APP: " + firebaseDatabase.getApp().getName()); } } else if (!enableLogging && (logLevel != null && logLevel)) { try { @@ -506,6 +518,10 @@ public class RNFirebaseDatabase extends ReactContextBaseJavaModule { firebaseDatabase.setLogLevel(Logger.Level.WARN); } catch (DatabaseException dex) { // do nothing - to catch 'calls to setLogLevel must be made for use of database' errors + // only occurs in dev after reloading or if user has actually incorrectly called it. + Log.w(TAG, "WARNING: enableLogging(bool) must be called before any other use of database(). \n" + + "If you are sure you've done this then this message can be ignored during development as \n" + + "RN reloads can cause false positives. APP: " + firebaseDatabase.getApp().getName()); } } From daa988e8d263e69100e52aa838720a291ca0daa1 Mon Sep 17 00:00:00 2001 From: Salakar Date: Tue, 28 Nov 2017 14:49:21 +0000 Subject: [PATCH 21/56] [tests] enableLogging on firestore + database --- tests/src/firebase.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/src/firebase.js b/tests/src/firebase.js index 033b438b..f51fb163 100644 --- a/tests/src/firebase.js +++ b/tests/src/firebase.js @@ -2,9 +2,11 @@ import { Platform } from 'react-native'; import firebase from 'firebase'; import RNfirebase from './../firebase'; - import DatabaseContents from './tests/support/DatabaseContents'; +RNfirebase.database.enableLogging(true); +RNfirebase.firestore.enableLogging(true); + const config = { apiKey: 'AIzaSyDnVqNhxU0Biit9nCo4RorAh5ulQQwko3E', authDomain: 'rnfirebase-b9ad4.firebaseapp.com', @@ -42,6 +44,8 @@ const instances = { another: RNfirebase.initializeApp(Platform.OS === 'ios' ? ios : android, 'anotherApp'), }; + + console.log('RNApps -->', RNfirebase.apps); // natively initialized apps are already available at app run time, From 08e6f00701940352ec852838cb657e8ba66c70c1 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Tue, 28 Nov 2017 16:26:25 +0000 Subject: [PATCH 22/56] 3.1.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index ba380f04..e901587a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "3.1.1-alpha.11", + "version": "3.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f3663876..03cf4200 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "3.1.1-alpha.11", + "version": "3.1.1", "author": "Invertase (http://invertase.io)", "description": "A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Messaging (FCM), Remote Config, Storage and Performance.", "main": "dist/index.js", From b702fafdfb288e278c5e41268463c0db3f1334ac Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 29 Nov 2017 09:07:12 +0000 Subject: [PATCH 23/56] [setup] Add postinstall build commands --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 03cf4200..49877138 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "flow": "flow", "lint": "eslint ./src", "prepublish": "npm run clean && npm run build", - "postinstall": "opencollective postinstall", + "postinstall": "npm run clean && npm run build && opencollective postinstall", "test-cli": "node ./bin/test.js", "tests-packager": "cd tests && npm run start", "tests-npm-install": "cd tests && npm install", From 453b69cbb9056b738100fc1dbee1516b5d0d670e Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 29 Nov 2017 09:14:06 +0000 Subject: [PATCH 24/56] [setup] Remove post install step --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 49877138..03cf4200 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "flow": "flow", "lint": "eslint ./src", "prepublish": "npm run clean && npm run build", - "postinstall": "npm run clean && npm run build && opencollective postinstall", + "postinstall": "opencollective postinstall", "test-cli": "node ./bin/test.js", "tests-packager": "cd tests && npm run start", "tests-npm-install": "cd tests && npm install", From c81a78601424500eed11948925a784704c05b845 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 29 Nov 2017 10:06:06 +0000 Subject: [PATCH 25/56] [setup] Make use of postinstall-build to build `dist` if required --- package-lock.json | 5 +++++ package.json | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index e901587a..e637199d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5970,6 +5970,11 @@ "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, + "postinstall-build": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postinstall-build/-/postinstall-build-5.0.1.tgz", + "integrity": "sha1-uRepB5smF42aJK9aXNjLSpkdEbk=" + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", diff --git a/package.json b/package.json index 03cf4200..8fdc90c4 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "flow": "flow", "lint": "eslint ./src", "prepublish": "npm run clean && npm run build", - "postinstall": "opencollective postinstall", + "postinstall": "postinstall-build dist && opencollective postinstall", "test-cli": "node ./bin/test.js", "tests-packager": "cd tests && npm run start", "tests-npm-install": "cd tests && npm install", @@ -96,6 +96,7 @@ "dependencies": { "bows": "^1.6.0", "opencollective": "^1.0.3", + "postinstall-build": "^5.0.1", "prop-types": "^15.6.0" }, "rnpm": { From 22ace9e3ed1a7e9a78a261739d3f7b75b7d12959 Mon Sep 17 00:00:00 2001 From: Marcel Friedrich Date: Sun, 3 Dec 2017 19:15:26 +0100 Subject: [PATCH 26/56] add smartbanner landscape for iOS --- .../java/io/invertase/firebase/admob/RNFirebaseAdMobUtils.java | 2 ++ ios/RNFirebase/admob/RNFirebaseAdMob.m | 2 ++ 2 files changed, 4 insertions(+) diff --git a/android/src/main/java/io/invertase/firebase/admob/RNFirebaseAdMobUtils.java b/android/src/main/java/io/invertase/firebase/admob/RNFirebaseAdMobUtils.java index 9cce8a0a..ec7b0ff1 100644 --- a/android/src/main/java/io/invertase/firebase/admob/RNFirebaseAdMobUtils.java +++ b/android/src/main/java/io/invertase/firebase/admob/RNFirebaseAdMobUtils.java @@ -142,6 +142,8 @@ class RNFirebaseAdMobUtils { return AdSize.LEADERBOARD; case "SMART_BANNER": return AdSize.SMART_BANNER; + case "SMART_BANNER_LANDSCAPE": + return AdSize.SMART_BANNER; } } } diff --git a/ios/RNFirebase/admob/RNFirebaseAdMob.m b/ios/RNFirebase/admob/RNFirebaseAdMob.m index f0bc4487..dbee154c 100644 --- a/ios/RNFirebase/admob/RNFirebaseAdMob.m +++ b/ios/RNFirebase/admob/RNFirebaseAdMob.m @@ -210,6 +210,8 @@ RCT_EXPORT_METHOD(clearInterstitial: return kGADAdSizeLeaderboard; } else if ([value isEqualToString:@"SMART_BANNER"]) { return kGADAdSizeSmartBannerPortrait; + } else if ([value isEqualToString:@"SMART_BANNER_LANDSCAPE"]) { + return kGADAdSizeSmartBannerLandscape; } else { return kGADAdSizeBanner; } From 19cec2cd8b2b8005e919451234b5895861597f5f Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Mon, 4 Dec 2017 12:07:41 +0000 Subject: [PATCH 27/56] Better flow config to remove unrelated errors --- .flowconfig | 121 +++++++++---------------- lib/modules/config/index.js | 23 ++++- lib/modules/crash/index.js | 3 +- lib/modules/database/disconnect.js | 10 +- lib/modules/database/index.js | 20 ++-- lib/modules/database/query.js | 9 +- lib/modules/database/reference.js | 41 ++++----- lib/modules/database/snapshot.js | 7 +- lib/modules/database/transaction.js | 7 +- lib/modules/links/index.js | 14 ++- lib/modules/messaging/RemoteMessage.js | 12 ++- lib/modules/messaging/index.js | 52 ++++++----- lib/modules/perf/Trace.js | 18 +++- lib/modules/perf/index.js | 17 ++-- lib/modules/storage/index.js | 31 ++++--- lib/modules/storage/reference.js | 32 ++++--- lib/modules/storage/task.js | 14 ++- lib/types/index.js | 1 + 18 files changed, 234 insertions(+), 198 deletions(-) diff --git a/.flowconfig b/.flowconfig index b8353a70..96622d4e 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,77 +1,37 @@ [ignore] +; We fork some components by platform +.*/*[.]android.js +; Ignore "BUCK" generated dirs +.*/node_modules/react-native/\.buckd/ -# Some modules have their own node_modules with overlap -.*/node_modules/node-haste/.* +; Ignore unexpected extra "@providesModule" +.*/node_modules/.*/node_modules/fbjs/.* +; Ignore duplicate module providers +; For RN Apps installed via npm, "Libraries" folder is inside +; "node_modules/react-native" but in the source repo it is in the root +.*/Libraries/react-native/React.js + +; Ignore polyfills +.*/Libraries/polyfills/.* # React Native problems -.*/node_modules/react-native/Libraries/Animated/src/AnimatedInterpolation.js -.*/node_modules/react-native/Libraries/Animated/src/Interpolation.js -.*/node_modules/react-native/Libraries/BugReporting/dumpReactTree.js -.*/node_modules/react-native/Libraries/CustomComponents/NavigationExperimental/NavigationHeader.js -.*/node_modules/react-native/Libraries/CustomComponents/NavigationExperimental/NavigationPagerStyleInterpolater.js -.*/node_modules/react-native/Libraries/Experimental/WindowedListView.js -.*/node_modules/react-native/Libraries/Image/Image.io.js -.*/node_modules/react-native/Libraries/NavigationExperimental/NavigationExperimental.js -.*/node_modules/react-native/Libraries/NavigationExperimental/NavigationHeaderStyleInterpolator.js -.*/node_modules/react-native/Libraries/Network/FormData.js -.*/node_modules/react-native/Libraries/ReactIOS/YellowBox.js - - - -# Ignore react and fbjs where there are overlaps, but don't ignore -# anything that react-native relies on -.*/node_modules/fbjs/lib/Map.js -.*/node_modules/fbjs/lib/ErrorUtils.js - -# Flow has a built-in definition for the 'react' module which we prefer to use -# over the currently-untyped source -.*/node_modules/react/react.js -.*/node_modules/react/lib/React.js -.*/node_modules/react/lib/ReactDOM.js - -.*/__mocks__/.* -.*/__tests__/.* - -.*/commoner/test/source/widget/share.js - -# Ignore commoner tests -.*/node_modules/commoner/test/.* - -# See https://github.com/facebook/flow/issues/442 -.*/react-tools/node_modules/commoner/lib/reader.js - -# Ignore jest -.*/node_modules/jest-cli/.* - -# Ignore Website -.*/website/.* - -# Ignore generators -.*/local-cli/generator.* - -# Ignore BUCK generated folders -.*\.buckd/ - -.*/node_modules/is-my-json-valid/test/.*\.json -.*/node_modules/iconv-lite/encodings/tables/.*\.json -.*/node_modules/y18n/test/.*\.json -.*/node_modules/spdx-license-ids/spdx-license-ids.json -.*/node_modules/spdx-exceptions/index.json -.*/node_modules/resolve/test/subdirs/node_modules/a/b/c/x.json -.*/node_modules/resolve/lib/core.json -.*/node_modules/jsonparse/samplejson/.*\.json -.*/node_modules/json5/test/.*\.json -.*/node_modules/ua-parser-js/test/.*\.json -.*/node_modules/builtin-modules/builtin-modules.json -.*/node_modules/binary-extensions/binary-extensions.json -.*/node_modules/url-regex/tlds.json -.*/node_modules/joi/.*\.json -.*/node_modules/isemail/.*\.json -.*/node_modules/tr46/.*\.json -.*/node_modules/protobufjs/src/bower.json -.*/node_modules/grpc/node_modules/protobufjs/src/bower.json +.*/node_modules/metro-bundler/src/DeltaBundler/DeltaCalculator.js.flow +.*/node_modules/metro-bundler/src/DeltaBundler/DeltaPatcher.js.flow +.*/node_modules/metro-bundler/src/node-haste/AssetResolutionCache.js.flow +.*/node_modules/metro-bundler/src/node-haste/DependencyGraph.js.flow +#.*/node_modules/react-native/Libraries/Animated/src/nodes/AnimatedStyle.js +#.*/node_modules/react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +#.*/node_modules/react-native/Libraries/Experimental/SwipeableRow/SwipeableFlatList.js +#.*/node_modules/react-native/Libraries/Experimental/SwipeableRow/SwipeableListView.js +#.*/node_modules/react-native/Libraries/Image/ImageBackground.js +#.*/node_modules/react-native/Libraries/Lists/FlatList.js +#.*/node_modules/react-native/Libraries/Lists/MetroListView.js +#.*/node_modules/react-native/Libraries/Lists/SectionList.js +#.*/node_modules/react-native/Libraries/Lists/ViewabilityHelper.js +#.*/node_modules/react-native/Libraries/Lists/VirtualizedList.js +#.*/node_modules/react-native/Libraries/Lists/VirtualizedSectionList.js # Ignore dist folder .*/dist/.* @@ -80,34 +40,37 @@ .*/tests/.* [include] -node_modules/fbjs/lib [libs] node_modules/react-native/Libraries/react-native/react-native-interface.js -node_modules/react-native/flow -node_modules/fbjs/flow/lib +node_modules/react-native/flow/ [options] module.system=haste -experimental.strict_type_args=true -unsafe.enable_getters_and_setters=true - -esproposal.class_static_fields=enable -esproposal.class_instance_fields=enable +emoji=true munge_underscores=false -module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' +module.file_ext=.js +module.file_ext=.jsx +module.file_ext=.json +module.file_ext=.native.js + suppress_type=$FlowIssue suppress_type=$FlowFixMe +suppress_type=$FlowFixMeProps +suppress_type=$FlowFixMeState suppress_type=$FixMe -suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-4]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-4]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy +suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError + +unsafe.enable_getters_and_setters=true [version] ^0.56.0 diff --git a/lib/modules/config/index.js b/lib/modules/config/index.js index 07562a37..999c838a 100644 --- a/lib/modules/config/index.js +++ b/lib/modules/config/index.js @@ -1,8 +1,19 @@ /** * @flow + * Remote Config representation wrapper */ import ModuleBase from './../../utils/ModuleBase'; +import type FirebaseApp from '../core/firebase-app'; + +type NativeValue = { + stringValue?: string, + numberValue?: number, + dataValue?: Object, + boolValue?: boolean, + source: 'remoteConfigSourceRemote' | 'remoteConfigSourceDefault' | ' remoteConfigSourceStatic', +} + /** * @class Config */ @@ -10,9 +21,11 @@ export default class RemoteConfig extends ModuleBase { static _NAMESPACE = 'config'; static _NATIVE_MODULE = 'RNFirebaseRemoteConfig'; - constructor(firebaseApp: Object, options: Object = {}) { + _developerModeEnabled: boolean; + + constructor(firebaseApp: FirebaseApp, options: Object = {}) { super(firebaseApp, options); - this.developerModeEnabled = false; + this._developerModeEnabled = false; } /** @@ -21,7 +34,7 @@ export default class RemoteConfig extends ModuleBase { * @returns {*} * @private */ - _nativeValueToJS(nativeValue) { + _nativeValueToJS(nativeValue: NativeValue) { return { source: nativeValue.source, val() { @@ -37,10 +50,10 @@ export default class RemoteConfig extends ModuleBase { * Enable Remote Config developer mode to allow for frequent refreshes of the cache */ enableDeveloperMode() { - if (!this.developerModeEnabled) { + if (!this._developerModeEnabled) { this.log.debug('Enabled developer mode'); this._native.enableDeveloperMode(); - this.developerModeEnabled = true; + this._developerModeEnabled = true; } } diff --git a/lib/modules/crash/index.js b/lib/modules/crash/index.js index 70a677e7..2844a65c 100644 --- a/lib/modules/crash/index.js +++ b/lib/modules/crash/index.js @@ -4,13 +4,14 @@ */ import ModuleBase from '../../utils/ModuleBase'; +import type FirebaseApp from '../core/firebase-app'; import type { FirebaseError } from '../../types'; export default class Crash extends ModuleBase { static _NAMESPACE = 'crash'; static _NATIVE_MODULE = 'RNFirebaseCrash'; - constructor(firebaseApp: Object, options: Object = {}) { + constructor(firebaseApp: FirebaseApp, options: Object = {}) { super(firebaseApp, options); } diff --git a/lib/modules/database/disconnect.js b/lib/modules/database/disconnect.js index 638f8c76..f1a37122 100644 --- a/lib/modules/database/disconnect.js +++ b/lib/modules/database/disconnect.js @@ -1,7 +1,10 @@ -/* @flow */ - +/** + * @flow + * Disconnect representation wrapper + */ import { typeOf } from './../../utils'; -import Reference from './reference'; +import type Database from './'; +import type Reference from './reference'; /** @@ -9,6 +12,7 @@ import Reference from './reference'; * @class Disconnect */ export default class Disconnect { + _database: Database; ref: Reference; path: string; diff --git a/lib/modules/database/index.js b/lib/modules/database/index.js index a73e59f8..ddcae474 100644 --- a/lib/modules/database/index.js +++ b/lib/modules/database/index.js @@ -8,6 +8,8 @@ import Reference from './reference'; import TransactionHandler from './transaction'; import ModuleBase from './../../utils/ModuleBase'; +import type FirebaseApp from '../core/firebase-app'; + /** * @class Database */ @@ -15,7 +17,11 @@ export default class Database extends ModuleBase { static _NAMESPACE = 'database'; static _NATIVE_MODULE = 'RNFirebaseDatabase'; - constructor(firebaseApp: Object, options: Object = {}) { + _offsetRef: Reference; + _serverTimeOffset: number; + _transactionHandler: TransactionHandler; + + constructor(firebaseApp: FirebaseApp, options: Object = {}) { super(firebaseApp, options, true); this._transactionHandler = new TransactionHandler(this); @@ -40,21 +46,21 @@ export default class Database extends ModuleBase { * * @return {number} */ - getServerTime() { + getServerTime(): number { return new Date(Date.now() + this._serverTimeOffset); } /** * */ - goOnline() { + goOnline(): void { this._native.goOnline(); } /** * */ - goOffline() { + goOffline(): void { this._native.goOffline(); } @@ -63,7 +69,7 @@ export default class Database extends ModuleBase { * @param path * @returns {Reference} */ - ref(path: string) { + ref(path: string): Reference { return new Reference(this, path); } } @@ -72,9 +78,9 @@ export const statics = { ServerValue: NativeModules.RNFirebaseDatabase ? { TIMESTAMP: NativeModules.RNFirebaseDatabase.serverValueTimestamp || { '.sv': 'timestamp' }, } : {}, - enableLogging(bool) { + enableLogging(enabled: boolean) { if (NativeModules[Database._NATIVE_MODULE]) { - NativeModules[Database._NATIVE_MODULE].enableLogging(bool); + NativeModules[Database._NATIVE_MODULE].enableLogging(enabled); } }, }; diff --git a/lib/modules/database/query.js b/lib/modules/database/query.js index 9cd75760..47192f22 100644 --- a/lib/modules/database/query.js +++ b/lib/modules/database/query.js @@ -1,11 +1,11 @@ /** * @flow + * Query representation wrapper */ - -import Reference from './reference.js'; import { objectToUniqueId } from '../../utils'; import type { DatabaseModifier } from '../../types'; +import type Reference from './reference.js'; // todo doc methods @@ -13,6 +13,7 @@ import type { DatabaseModifier } from '../../types'; * @class Query */ export default class Query { + _reference: Reference; modifiers: Array; constructor(ref: Reference, path: string, existingModifiers?: Array) { @@ -28,7 +29,7 @@ export default class Query { */ orderBy(name: string, key?: string) { this.modifiers.push({ - id: `orderBy-${name}:${key}`, + id: `orderBy-${name}:${key || ''}`, type: 'orderBy', name, key, @@ -63,7 +64,7 @@ export default class Query { */ filter(name: string, value: any, key?: string) { this.modifiers.push({ - id: `filter-${name}:${objectToUniqueId(value)}:${key}`, + id: `filter-${name}:${objectToUniqueId(value)}:${key || ''}`, type: 'filter', name, value, diff --git a/lib/modules/database/reference.js b/lib/modules/database/reference.js index befd514d..ee0f6283 100644 --- a/lib/modules/database/reference.js +++ b/lib/modules/database/reference.js @@ -1,7 +1,7 @@ /** * @flow + * Database Reference representation wrapper */ - import Query from './query.js'; import Snapshot from './snapshot'; import Disconnect from './disconnect'; @@ -20,6 +20,7 @@ import { import INTERNALS from '../../utils/internals'; import type { DatabaseModifier, FirebaseError } from '../../types'; +import type SyncTree from '../../utils/SyncTree'; // track all event registrations by path let listeners = 0; @@ -72,10 +73,10 @@ type DatabaseListener = { * @extends ReferenceBase */ export default class Reference extends ReferenceBase { - - _refListeners: { [listenerId: number]: DatabaseListener }; _database: Object; + _promise: ?Promise<*>; _query: Query; + _refListeners: { [listenerId: number]: DatabaseListener }; constructor(database: Object, path: string, existingModifiers?: Array) { super(path, database); @@ -96,7 +97,7 @@ export default class Reference extends ReferenceBase { * @param bool * @returns {*} */ - keepSynced(bool: boolean) { + keepSynced(bool: boolean): Promise { return this._database._native.keepSynced(this._getRefKey(), this.path, this._query.getModifiers(), bool); } @@ -108,7 +109,7 @@ export default class Reference extends ReferenceBase { * @param onComplete * @returns {Promise} */ - set(value: any, onComplete?: Function): Promise { + set(value: any, onComplete?: Function): Promise { return promiseOrCallback( this._database._native.set(this.path, this._serializeAnyType(value)), onComplete, @@ -123,7 +124,7 @@ export default class Reference extends ReferenceBase { * @param onComplete * @returns {Promise} */ - setPriority(priority: string | number | null, onComplete?: Function): Promise { + setPriority(priority: string | number | null, onComplete?: Function): Promise { const _priority = this._serializeAnyType(priority); return promiseOrCallback( @@ -141,7 +142,7 @@ export default class Reference extends ReferenceBase { * @param onComplete * @returns {Promise} */ - setWithPriority(value: any, priority: string | number | null, onComplete?: Function): Promise { + setWithPriority(value: any, priority: string | number | null, onComplete?: Function): Promise { const _value = this._serializeAnyType(value); const _priority = this._serializeAnyType(priority); @@ -159,7 +160,7 @@ export default class Reference extends ReferenceBase { * @param onComplete * @returns {Promise} */ - update(val: Object, onComplete?: Function): Promise { + update(val: Object, onComplete?: Function): Promise { const value = this._serializeObject(val); return promiseOrCallback( @@ -175,7 +176,7 @@ export default class Reference extends ReferenceBase { * @param onComplete * @return {Promise} */ - remove(onComplete?: Function): Promise { + remove(onComplete?: Function): Promise { return promiseOrCallback( this._database._native.remove(this.path), onComplete, @@ -196,16 +197,14 @@ export default class Reference extends ReferenceBase { applyLocally: boolean = false, ) { if (!isFunction(transactionUpdate)) { - return Promise.reject( - new Error('Missing transactionUpdate function argument.'), - ); + return Promise.reject(new Error('Missing transactionUpdate function argument.')); } return new Promise((resolve, reject) => { const onCompleteWrapper = (error, committed, snapshotData) => { if (isFunction(onComplete)) { - if (error) { - onComplete(error, committed, null); + if (error) { + onComplete(error, committed, null); } else { onComplete(null, committed, new Snapshot(this, snapshotData)); } @@ -259,7 +258,7 @@ export default class Reference extends ReferenceBase { * @param onComplete * @returns {*} */ - push(value: any, onComplete?: Function): Reference | Promise { + push(value: any, onComplete?: Function): Reference | Promise { if (value === null || value === undefined) { return new Reference(this._database, `${this.path}/${generatePushID(this._database._serverTimeOffset)}`); } @@ -492,7 +491,7 @@ export default class Reference extends ReferenceBase { * Access then method of promise if set * @return {*} */ - then(fnResolve, fnReject) { + then(fnResolve: (any) => any, fnReject: (any) => any) { if (isFunction(fnResolve) && this._promise && this._promise.then) { return this._promise.then.bind(this._promise)((result) => { this._promise = null; @@ -515,7 +514,7 @@ export default class Reference extends ReferenceBase { * Access catch method of promise if set * @return {*} */ - catch(fnReject) { + catch(fnReject: (any) => any) { if (isFunction(fnReject) && this._promise && this._promise.catch) { return this._promise.catch.bind(this._promise)((possibleErr) => { this._promise = null; @@ -535,7 +534,7 @@ export default class Reference extends ReferenceBase { * * @return {string} */ - _getRegistrationKey(eventType) { + _getRegistrationKey(eventType: string): string { return `$${this._database._appName}$/${this.path}$${this._query.queryIdentifier()}$${listeners}$${eventType}`; } @@ -546,7 +545,7 @@ export default class Reference extends ReferenceBase { * @return {string} * @private */ - _getRefKey() { + _getRefKey(): string { return `$${this._database._appName}$/${this.path}$${this._query.queryIdentifier()}`; } @@ -562,7 +561,7 @@ export default class Reference extends ReferenceBase { * @param promise * @private */ - _setThenable(promise) { + _setThenable(promise: Promise<*>) { this._promise = promise; } @@ -770,7 +769,7 @@ export default class Reference extends ReferenceBase { return this._syncTree.removeListenersForRegistrations(registrations); } - get _syncTree() { + get _syncTree(): SyncTree { return INTERNALS.SyncTree; } } diff --git a/lib/modules/database/snapshot.js b/lib/modules/database/snapshot.js index 6a117104..fa6c6c77 100644 --- a/lib/modules/database/snapshot.js +++ b/lib/modules/database/snapshot.js @@ -1,15 +1,16 @@ /** * @flow + * Snapshot representation wrapper */ -import Reference from './reference.js'; import { isObject, deepGet, deepExists } from './../../utils'; +import type Reference from './reference.js'; /** * @class DataSnapshot * @link https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot */ export default class Snapshot { - ref: Object; + ref: Reference; key: string; _value: any; @@ -138,7 +139,7 @@ export default class Snapshot { * @link https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot#toJSON * @returns {any} */ - toJSON(): any { + toJSON(): Object { return this.val(); } } diff --git a/lib/modules/database/transaction.js b/lib/modules/database/transaction.js index 4c1f4864..d84a1d26 100644 --- a/lib/modules/database/transaction.js +++ b/lib/modules/database/transaction.js @@ -2,6 +2,7 @@ * @flow * Database Transaction representation wrapper */ +import type Database from './'; let transactionId = 0; @@ -9,7 +10,11 @@ let transactionId = 0; * @class TransactionHandler */ export default class TransactionHandler { - constructor(database: Object) { + _database: Database; + _transactionListener: Function; + _transactions: { [string]: Object } + + constructor(database: Database) { this._transactions = {}; this._database = database; diff --git a/lib/modules/links/index.js b/lib/modules/links/index.js index 3f12df6a..68b332bb 100644 --- a/lib/modules/links/index.js +++ b/lib/modules/links/index.js @@ -1,6 +1,12 @@ +/** + * @flow + * Dynamic Links representation wrapper + */ import ModuleBase from './../../utils/ModuleBase'; import { areObjectKeysContainedInOther, isObject, isString } from './../../utils'; +import type FirebaseApp from '../core/firebase-app'; + const EVENT_TYPE = { Link: 'dynamic_link_received', }; @@ -59,11 +65,11 @@ export default class Links extends ModuleBase { static _NAMESPACE = 'links'; static _NATIVE_MODULE = 'RNFirebaseLinks'; - constructor(firebaseApp: Object, options: Object = {}) { + constructor(firebaseApp: FirebaseApp, options: Object = {}) { super(firebaseApp, options, true); } - get EVENT_TYPE() { + get EVENT_TYPE(): Object { return EVENT_TYPE; } @@ -71,7 +77,7 @@ export default class Links extends ModuleBase { * Returns the link that triggered application open * @returns {Promise.} */ - getInitialLink() { + getInitialLink(): Promise { return this._native.getInitialLink(); } @@ -90,7 +96,7 @@ export default class Links extends ModuleBase { * @param parameters * @returns {Promise.} */ - createDynamicLink(parameters: Object = {}): Promise { + createDynamicLink(parameters: Object = {}): Promise { try { checkForMandatoryParameters(parameters); validateParameters(parameters); diff --git a/lib/modules/messaging/RemoteMessage.js b/lib/modules/messaging/RemoteMessage.js index b44a6cbb..78472967 100644 --- a/lib/modules/messaging/RemoteMessage.js +++ b/lib/modules/messaging/RemoteMessage.js @@ -1,7 +1,13 @@ +/** + * @flow + * Remote message representation wrapper + */ import { isObject, generatePushID } from './../../utils'; export default class RemoteMessage { - constructor(sender: String) { + properties: Object; + + constructor(sender: string) { this.properties = { id: generatePushID(), ttl: 3600, @@ -17,7 +23,7 @@ export default class RemoteMessage { * @param ttl * @returns {RemoteMessage} */ - setTtl(ttl: Number): RemoteMessage { + setTtl(ttl: number): RemoteMessage { this.properties.ttl = ttl; return this; } @@ -74,7 +80,7 @@ export default class RemoteMessage { return this; } - toJSON() { + toJSON(): Object { return Object.assign({}, this.properties); } } diff --git a/lib/modules/messaging/index.js b/lib/modules/messaging/index.js index c06937bd..595ab402 100644 --- a/lib/modules/messaging/index.js +++ b/lib/modules/messaging/index.js @@ -1,7 +1,13 @@ +/** + * @flow + * Messaging representation wrapper + */ import { Platform, NativeModules } from 'react-native'; import ModuleBase from './../../utils/ModuleBase'; import RemoteMessage from './RemoteMessage'; +import type FirebaseApp from '../core/firebase-app'; + const EVENT_TYPE = { RefreshToken: 'messaging_token_refreshed', Notification: 'messaging_notification_received', @@ -75,23 +81,23 @@ export default class Messaging extends ModuleBase { static _NAMESPACE = 'messaging'; static _NATIVE_MODULE = 'RNFirebaseMessaging'; - constructor(firebaseApp: Object, options: Object = {}) { + constructor(firebaseApp: FirebaseApp, options: Object = {}) { super(firebaseApp, options, true); } - get EVENT_TYPE() { + get EVENT_TYPE(): Object { return EVENT_TYPE; } - get NOTIFICATION_TYPE() { + get NOTIFICATION_TYPE(): Object { return NOTIFICATION_TYPE; } - get REMOTE_NOTIFICATION_RESULT() { + get REMOTE_NOTIFICATION_RESULT(): Object { return REMOTE_NOTIFICATION_RESULT; } - get WILL_PRESENT_RESULT() { + get WILL_PRESENT_RESULT(): Object { return WILL_PRESENT_RESULT; } @@ -99,7 +105,7 @@ export default class Messaging extends ModuleBase { * Returns the notification that triggered application open * @returns {*} */ - getInitialNotification() { + getInitialNotification(): Promise { return this._native.getInitialNotification(); } @@ -107,7 +113,7 @@ export default class Messaging extends ModuleBase { * Returns the fcm token for the current device * @returns {*|Promise.} */ - getToken() { + getToken(): Promise { return this._native.getToken(); } @@ -115,7 +121,7 @@ export default class Messaging extends ModuleBase { * Reset Instance ID and revokes all tokens. * @returns {*|Promise.<*>} */ - deleteInstanceId() { + deleteInstanceId(): Promise { return this._native.deleteInstanceId(); } @@ -124,7 +130,7 @@ export default class Messaging extends ModuleBase { * @param notification * @returns {*} */ - createLocalNotification(notification: Object) { + createLocalNotification(notification: Object): Promise { const _notification = Object.assign({}, notification); _notification.id = _notification.id || new Date().getTime().toString(); _notification.local_notification = true; @@ -136,7 +142,7 @@ export default class Messaging extends ModuleBase { * @param notification * @returns {*} */ - scheduleLocalNotification(notification: Object) { + scheduleLocalNotification(notification: Object): Promise { const _notification = Object.assign({}, notification); if (!notification.id) return Promise.reject(new Error('An id is required to schedule a local notification.')); _notification.local_notification = true; @@ -147,7 +153,7 @@ export default class Messaging extends ModuleBase { * Returns an array of all scheduled notifications * @returns {Promise.} */ - getScheduledLocalNotifications() { + getScheduledLocalNotifications(): Promise { return this._native.getScheduledLocalNotifications(); } @@ -157,8 +163,8 @@ export default class Messaging extends ModuleBase { * @param id * @returns {*} */ - cancelLocalNotification(id: string) { - if (!id) return null; + cancelLocalNotification(id: string): Promise { + if (!id) return Promise.reject(new Error('Missing notification id')); if (id === '*') return this._native.cancelAllLocalNotifications(); return this._native.cancelLocalNotification(id); } @@ -169,8 +175,8 @@ export default class Messaging extends ModuleBase { * @param id * @returns {*} */ - removeDeliveredNotification(id: string) { - if (!id) return null; + removeDeliveredNotification(id: string): Promise { + if (!id) return Promise.reject(new Error('Missing notification id')); if (id === '*') return this._native.removeAllDeliveredNotifications(); return this._native.removeDeliveredNotification(id); } @@ -180,7 +186,7 @@ export default class Messaging extends ModuleBase { * @platforms ios * @returns {*|Promise.<*>} */ - requestPermissions() { + requestPermissions(): Promise { return this._native.requestPermissions(); } @@ -189,7 +195,7 @@ export default class Messaging extends ModuleBase { * Set notification count badge number * @param n */ - setBadgeNumber(n: number) { + setBadgeNumber(n: number): void { this._native.setBadgeNumber(n); } @@ -197,7 +203,7 @@ export default class Messaging extends ModuleBase { * set notification count badge number * @returns {Promise.} */ - getBadgeNumber() { + getBadgeNumber(): Promise { return this._native.getBadgeNumber(); } @@ -206,7 +212,7 @@ export default class Messaging extends ModuleBase { * @param listener * @returns {*} */ - onMessage(listener: Function): () => any { + onMessage(listener: (Object) => any): () => any { const rnListener = this._eventEmitter.addListener( EVENT_TYPE.Notification, async (event) => { @@ -229,7 +235,7 @@ export default class Messaging extends ModuleBase { * @param listener * @returns {*} */ - onTokenRefresh(listener: Function): () => any { + onTokenRefresh(listener: (string) => any): () => any { const rnListener = this._eventEmitter.addListener(EVENT_TYPE.RefreshToken, listener); return () => rnListener.remove(); } @@ -238,7 +244,7 @@ export default class Messaging extends ModuleBase { * Subscribe to a topic * @param topic */ - subscribeToTopic(topic: String) { + subscribeToTopic(topic: string): void { this._native.subscribeToTopic(topic); } @@ -246,7 +252,7 @@ export default class Messaging extends ModuleBase { * Unsubscribe from a topic * @param topic */ - unsubscribeFromTopic(topic: String) { + unsubscribeFromTopic(topic: string): void { this._native.unsubscribeFromTopic(topic); } @@ -254,7 +260,7 @@ export default class Messaging extends ModuleBase { * Send an upstream message * @param remoteMessage */ - send(remoteMessage: RemoteMessage) { + send(remoteMessage: RemoteMessage): Promise { if (!(remoteMessage instanceof RemoteMessage)) { throw new Error('messaging().send requires an instance of RemoteMessage as the first argument.'); } diff --git a/lib/modules/perf/Trace.js b/lib/modules/perf/Trace.js index 7ac258b0..5b5614b1 100644 --- a/lib/modules/perf/Trace.js +++ b/lib/modules/perf/Trace.js @@ -1,19 +1,27 @@ -export default class Trace { +/** + * @flow + * Trace representation wrapper + */ +import type PerformanceMonitoring from './'; - constructor(perf: Object, identifier: string) { +export default class Trace { + identifier: string; + perf: PerformanceMonitoring; + + constructor(perf: PerformanceMonitoring, identifier: string) { this.perf = perf; this.identifier = identifier; } - start() { + start(): void { this.perf._native.start(this.identifier); } - stop() { + stop(): void { this.perf._native.stop(this.identifier); } - incrementCounter(event: string) { + incrementCounter(event: string): void { this.perf._native.incrementCounter(this.identifier, event); } } diff --git a/lib/modules/perf/index.js b/lib/modules/perf/index.js index 496ce59a..81d3a5d1 100644 --- a/lib/modules/perf/index.js +++ b/lib/modules/perf/index.js @@ -1,14 +1,17 @@ -// @flow +/** + * @flow + * Performance monitoring representation wrapper + */ import Trace from './Trace'; import ModuleBase from '../../utils/ModuleBase'; +import type FirebaseApp from '../core/firebase-app'; + export default class PerformanceMonitoring extends ModuleBase { static _NAMESPACE = 'perf'; static _NATIVE_MODULE = 'RNFirebasePerformance'; - _native: Object; - - constructor(firebaseApp: Object, options: Object = {}) { + constructor(firebaseApp: FirebaseApp, options: Object = {}) { super(firebaseApp, options); } @@ -17,15 +20,15 @@ export default class PerformanceMonitoring extends ModuleBase { * @param enabled * @returns {*} */ - setPerformanceCollectionEnabled(enabled: boolean) { - return this._native.setPerformanceCollectionEnabled(enabled); + setPerformanceCollectionEnabled(enabled: boolean): void { + this._native.setPerformanceCollectionEnabled(enabled); } /** * Returns a new trace instance * @param trace */ - newTrace(trace: string): void { + newTrace(trace: string): Trace { return new Trace(this, trace); } } diff --git a/lib/modules/storage/index.js b/lib/modules/storage/index.js index eccfa45a..fdf5f520 100644 --- a/lib/modules/storage/index.js +++ b/lib/modules/storage/index.js @@ -1,22 +1,27 @@ -/* @flow */ +/** + * @flow + * Storage representation wrapper + */ import { NativeModules } from 'react-native'; import StorageRef from './reference'; import ModuleBase from './../../utils/ModuleBase'; +import type FirebaseApp from '../core/firebase-app'; + const FirebaseStorage = NativeModules.RNFirebaseStorage; export default class Storage extends ModuleBase { static _NAMESPACE = 'storage'; static _NATIVE_MODULE = 'RNFirebaseStorage'; + /** * * @param firebaseApp * @param options */ - constructor(firebaseApp: Object, options: Object = {}) { + constructor(firebaseApp: FirebaseApp, options: Object = {}) { super(firebaseApp, options, true); - this._subscriptions = {}; this.addListener( this._getAppEventName('storage_event'), @@ -55,7 +60,7 @@ export default class Storage extends ModuleBase { * @url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxOperationRetryTime * @param time The new maximum operation retry time in milliseconds. */ - setMaxOperationRetryTime(time: number) { + setMaxOperationRetryTime(time: number): void { this._native.setMaxOperationRetryTime(time); } @@ -64,7 +69,7 @@ export default class Storage extends ModuleBase { * @url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxUploadRetryTime * @param time The new maximum upload retry time in milliseconds. */ - setMaxUploadRetryTime(time: number) { + setMaxUploadRetryTime(time: number): void { this._native.setMaxUploadRetryTime(time); } @@ -73,14 +78,14 @@ export default class Storage extends ModuleBase { * @url N/A * @param time The new maximum download retry time in milliseconds. */ - setMaxDownloadRetryTime(time: number) { + setMaxDownloadRetryTime(time: number): void { this._native.setMaxDownloadRetryTime(time); } - /** ********** + /** * INTERNALS - ********** **/ - _getSubEventName(path, eventName) { + */ + _getSubEventName(path: string, eventName: string) { return this._getAppEventName(`${path}-${eventName}`); } @@ -93,18 +98,18 @@ export default class Storage extends ModuleBase { } _handleStorageError(err: Object) { - const { path, eventName } = event; - const body = event.body || {}; + const { path, eventName } = err; + const body = err.body || {}; this.log.debug('_handleStorageError ->', err); this.emit(this._getSubEventName(path, eventName), body); } - _addListener(path: string, eventName: string, cb: (evt: Object) => Object) { + _addListener(path: string, eventName: string, cb: (evt: Object) => Object): void { this.on(this._getSubEventName(path, eventName), cb); } - _removeListener(path: string, eventName: string, origCB: (evt: Object) => Object) { + _removeListener(path: string, eventName: string, origCB: (evt: Object) => Object): void { this.removeListener(this._getSubEventName(path, eventName), origCB); } } diff --git a/lib/modules/storage/reference.js b/lib/modules/storage/reference.js index 70f8af8e..d38c5d2a 100644 --- a/lib/modules/storage/reference.js +++ b/lib/modules/storage/reference.js @@ -1,14 +1,18 @@ -/* @flow */ - +/** + * @flow + * StorageReference representation wrapper + */ import ReferenceBase from '../../utils/ReferenceBase'; import StorageTask, { UPLOAD_TASK, DOWNLOAD_TASK } from './task'; -import Storage from './'; +import type Storage from './'; /** * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference */ export default class StorageReference extends ReferenceBase { + _storage: Storage; + constructor(storage: Storage, path: string) { super(path, storage); this._storage = storage; @@ -18,7 +22,7 @@ export default class StorageReference extends ReferenceBase { return this.path; } - toString(): String { + toString(): string { return `gs://${this._storage.app.options.storageBucket}${this.path}`; } @@ -27,24 +31,24 @@ export default class StorageReference extends ReferenceBase { * @param path * @returns {StorageReference} */ - child(path: string) { - return new StorageReference(this._module, `${this.path}/${path}`); + child(path: string): StorageReference { + return new StorageReference(this._storage, `${this.path}/${path}`); } /** * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#delete * @returns {Promise.|*} */ - delete(): Promise<*> { - return this._module._native.delete(this.path); + delete(): Promise { + return this._storage._native.delete(this.path); } /** * @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#getDownloadURL * @returns {Promise.|*} */ - getDownloadURL(): Promise { - return this._module._native.getDownloadURL(this.path); + getDownloadURL(): Promise { + return this._storage._native.getDownloadURL(this.path); } /** @@ -52,7 +56,7 @@ export default class StorageReference extends ReferenceBase { * @returns {Promise.|*} */ getMetadata(): Promise { - return this._module._native.getMetadata(this.path); + return this._storage._native.getMetadata(this.path); } /** @@ -61,7 +65,7 @@ export default class StorageReference extends ReferenceBase { * @returns {Promise.|*} */ updateMetadata(metadata: Object = {}): Promise { - return this._module._native.updateMetadata(this.path, metadata); + return this._storage._native.updateMetadata(this.path, metadata); } /** @@ -70,14 +74,14 @@ export default class StorageReference extends ReferenceBase { * @return {Promise} */ downloadFile(filePath: string): Promise { - return new StorageTask(DOWNLOAD_TASK, this._module._native.downloadFile(this.path, filePath), this); + return new StorageTask(DOWNLOAD_TASK, this._storage._native.downloadFile(this.path, filePath), this); } /** * Alias to putFile * @returns {StorageReference.putFile} */ - get put(): Function { + get put(): (Object, Object) => Promise { return this.putFile; } diff --git a/lib/modules/storage/task.js b/lib/modules/storage/task.js index 647a3b0c..e3906c23 100644 --- a/lib/modules/storage/task.js +++ b/lib/modules/storage/task.js @@ -1,7 +1,11 @@ -/* @flow */ +/** + * @flow + * UploadTask representation wrapper + */ import { statics as StorageStatics } from './'; import { isFunction } from './../../utils'; -import StorageReference from './reference'; +import type Storage from './'; +import type StorageReference from './reference'; export const UPLOAD_TASK = 'upload'; export const DOWNLOAD_TASK = 'download'; @@ -40,15 +44,15 @@ declare type NextOrObserverType = null | export default class StorageTask { type: typeof UPLOAD_TASK | typeof DOWNLOAD_TASK; ref: StorageReference; - storage: StorageReference.storage; - path: StorageReference.path; + storage: Storage; + path: string; then: () => Promise<*>; catch: () => Promise<*>; constructor(type: typeof UPLOAD_TASK | typeof DOWNLOAD_TASK, promise: Promise<*>, storageRef: StorageReference) { this.type = type; this.ref = storageRef; - this.storage = storageRef._module; + this.storage = storageRef._storage; this.path = storageRef.path; // 'proxy' original promise diff --git a/lib/types/index.js b/lib/types/index.js index 40b53a3a..48fb199d 100644 --- a/lib/types/index.js +++ b/lib/types/index.js @@ -106,6 +106,7 @@ export type DatabaseModule = { } & DatabaseStatics; export type DatabaseModifier = { + id: string; type: 'orderBy' | 'limit' | 'filter'; name?: string; key?: string; From 9845a51f1009e3901d6522dcb2ae1dd74a68b7ef Mon Sep 17 00:00:00 2001 From: Scott Adams Date: Mon, 4 Dec 2017 14:21:13 -0500 Subject: [PATCH 28/56] iOS Dynamic Links now 'Survive' installation. --- ios/RNFirebase/links/RNFirebaseLinks.m | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ios/RNFirebase/links/RNFirebaseLinks.m b/ios/RNFirebase/links/RNFirebaseLinks.m index 350eb25b..f7f580d4 100644 --- a/ios/RNFirebase/links/RNFirebaseLinks.m +++ b/ios/RNFirebase/links/RNFirebaseLinks.m @@ -16,6 +16,8 @@ static void sendDynamicLink(NSURL *url, id sender) { RCT_EXPORT_MODULE(); +static NSURL *installLink; + - (id)init { self = [super init]; if (self != nil) { @@ -51,6 +53,9 @@ RCT_EXPORT_MODULE(); } + (BOOL)handleLinkFromCustomSchemeURL:(NSURL *)url { + if(!installLink) { + installLink = url; + } FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url]; if (dynamicLink && dynamicLink.url) { @@ -124,7 +129,8 @@ RCT_EXPORT_METHOD(getInitialLink:(RCTPromiseResolveBlock)resolve rejecter:(RCTPr if (self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey]) { NSURL* url = (NSURL*)self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey]; [self handleInitialLinkFromCustomSchemeURL:url resolver:resolve rejecter:reject]; - + } else if(installLink) { + [self handleInitialLinkFromCustomSchemeURL:installLink resolver:resolve rejecter:reject]; } else { NSDictionary *userActivityDictionary = self.bridge.launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey]; From c9a8b4e1b1f252066c0a7f98f8e8b89477cee008 Mon Sep 17 00:00:00 2001 From: Michael Diarmid Date: Mon, 4 Dec 2017 22:54:45 +0000 Subject: [PATCH 29/56] Revert "iOS Dynamic Links now 'Survive' installation." --- ios/RNFirebase/links/RNFirebaseLinks.m | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ios/RNFirebase/links/RNFirebaseLinks.m b/ios/RNFirebase/links/RNFirebaseLinks.m index f7f580d4..350eb25b 100644 --- a/ios/RNFirebase/links/RNFirebaseLinks.m +++ b/ios/RNFirebase/links/RNFirebaseLinks.m @@ -16,8 +16,6 @@ static void sendDynamicLink(NSURL *url, id sender) { RCT_EXPORT_MODULE(); -static NSURL *installLink; - - (id)init { self = [super init]; if (self != nil) { @@ -53,9 +51,6 @@ static NSURL *installLink; } + (BOOL)handleLinkFromCustomSchemeURL:(NSURL *)url { - if(!installLink) { - installLink = url; - } FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url]; if (dynamicLink && dynamicLink.url) { @@ -129,8 +124,7 @@ RCT_EXPORT_METHOD(getInitialLink:(RCTPromiseResolveBlock)resolve rejecter:(RCTPr if (self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey]) { NSURL* url = (NSURL*)self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey]; [self handleInitialLinkFromCustomSchemeURL:url resolver:resolve rejecter:reject]; - } else if(installLink) { - [self handleInitialLinkFromCustomSchemeURL:installLink resolver:resolve rejecter:reject]; + } else { NSDictionary *userActivityDictionary = self.bridge.launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey]; From 4646c6723db15d2c73bd0901dc08a6db4332b2ab Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 6 Dec 2017 08:56:06 +0000 Subject: [PATCH 30/56] [typings] Make sure Typescript typings are copied correctly --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 8fdc90c4..50b51428 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,11 @@ "author": "Invertase (http://invertase.io)", "description": "A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Messaging (FCM), Remote Config, Storage and Performance.", "main": "dist/index.js", + "types": "dist.index.d.ts", "scripts": { "build": "npm run build-lib && npm run build-flow", "build-flow": "flow-copy-source -i */__tests__* lib dist", - "build-lib": "BABEL_ENV=publish babel lib -d dist --ignore __tests__", + "build-lib": "BABEL_ENV=publish babel lib -d dist --ignore __tests__ --copy-files", "clean": "rimraf dist/", "flow": "flow", "lint": "eslint ./src", From f96e673683d9f090afb8a30c453341a6f448dd0d Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 6 Dec 2017 08:59:00 +0000 Subject: [PATCH 31/56] [typings] Fix incorrect path --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 50b51428..813c3530 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "author": "Invertase (http://invertase.io)", "description": "A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Messaging (FCM), Remote Config, Storage and Performance.", "main": "dist/index.js", - "types": "dist.index.d.ts", + "types": "dist/index.d.ts", "scripts": { "build": "npm run build-lib && npm run build-flow", "build-flow": "flow-copy-source -i */__tests__* lib dist", From e697f116417491a1905835ba92cda19ea1a7a89a Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 6 Dec 2017 16:42:21 +0000 Subject: [PATCH 32/56] [typings] Fix some admob type issues --- lib/modules/admob/index.js | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/lib/modules/admob/index.js b/lib/modules/admob/index.js index 2ca393cb..c044646b 100644 --- a/lib/modules/admob/index.js +++ b/lib/modules/admob/index.js @@ -16,11 +16,22 @@ import EventTypes, { RewardedVideoEventTypes, } from './EventTypes'; +import type FirebaseApp from '../core/firebase-app'; + +type NativeEvent = { + adUnit: string, + payload: Object, + type: string, +} + export default class AdMob extends ModuleBase { static _NAMESPACE = 'admob'; static _NATIVE_MODULE = 'RNFirebaseAdMob'; - constructor(firebaseApp: Object, options: Object = {}) { + _appId: ?string; + _initialized: boolean; + + constructor(firebaseApp: FirebaseApp, options: Object = {}) { super(firebaseApp, options, true); this._initialized = false; @@ -30,7 +41,7 @@ export default class AdMob extends ModuleBase { this._eventEmitter.addListener('rewarded_video_event', this._onRewardedVideoEvent.bind(this)); } - _onInterstitialEvent(event) { + _onInterstitialEvent(event: NativeEvent): void { const { adUnit } = event; const jsEventType = `interstitial_${adUnit}`; @@ -41,7 +52,7 @@ export default class AdMob extends ModuleBase { this.emit(jsEventType, event); } - _onRewardedVideoEvent(event) { + _onRewardedVideoEvent(event: NativeEvent): void { const { adUnit } = event; const jsEventType = `rewarded_video_${adUnit}`; @@ -52,7 +63,7 @@ export default class AdMob extends ModuleBase { this.emit(jsEventType, event); } - initialize(appId: string) { + initialize(appId: string): void { if (this._initialized) { this.log.warn('AdMob has already been initialized!'); } else { @@ -62,7 +73,7 @@ export default class AdMob extends ModuleBase { } } - openDebugMenu() { + openDebugMenu(): void { if (!this._initialized) { this.log.warn('AdMob needs to be initialized before opening the dev menu!'); } else { @@ -71,11 +82,11 @@ export default class AdMob extends ModuleBase { } } - interstitial(adUnit: string) { + interstitial(adUnit: string): Interstitial { return new Interstitial(this, adUnit); } - rewarded(adUnit: string) { + rewarded(adUnit: string): RewardedVideo { return new RewardedVideo(this, adUnit); } From efeb24d168d40ea638b9f63e63f9fc290d889fdc Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 6 Dec 2017 17:25:17 +0000 Subject: [PATCH 33/56] [crashlytics] Add first version of crashlytics functionality --- android/build.gradle | 7 ++ .../crashlytics/RNFirebaseCrashlytics.java | 65 ++++++++++++++++ .../RNFirebaseCrashlyticsPackage.java | 39 ++++++++++ ios/RNFirebase.xcodeproj/project.pbxproj | 22 ++++++ .../crashlytics/RNFirebaseCrashlytics.h | 19 +++++ .../crashlytics/RNFirebaseCrashlytics.m | 47 +++++++++++ lib/modules/core/firebase-app.js | 6 ++ lib/modules/core/firebase.js | 6 ++ lib/modules/fabric/crashlytics/index.js | 77 +++++++++++++++++++ lib/types/index.js | 17 +++- tests/android/app/build.gradle | 4 + .../MainApplication.java | 2 + tests/android/build.gradle | 6 +- tests/ios/Podfile | 3 +- tests/ios/Podfile.lock | 13 +++- .../project.pbxproj | 17 +++- .../src/tests/crashlytics/crashlyticsTests.js | 52 +++++++++++++ tests/src/tests/crashlytics/index.js | 10 +++ tests/src/tests/index.js | 2 + 19 files changed, 406 insertions(+), 8 deletions(-) create mode 100644 android/src/main/java/io/invertase/firebase/fabric/crashlytics/RNFirebaseCrashlytics.java create mode 100644 android/src/main/java/io/invertase/firebase/fabric/crashlytics/RNFirebaseCrashlyticsPackage.java create mode 100644 ios/RNFirebase/fabric/crashlytics/RNFirebaseCrashlytics.h create mode 100644 ios/RNFirebase/fabric/crashlytics/RNFirebaseCrashlytics.m create mode 100644 lib/modules/fabric/crashlytics/index.js create mode 100644 tests/src/tests/crashlytics/crashlyticsTests.js create mode 100644 tests/src/tests/crashlytics/index.js diff --git a/android/build.gradle b/android/build.gradle index adf070f2..eb0e53c3 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -2,9 +2,13 @@ buildscript { ext.firebaseVersion = '11.4.2' repositories { jcenter() + maven { + url 'https://maven.fabric.io/public' + } } dependencies { classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'io.fabric.tools:gradle:1.24.4' } } @@ -91,4 +95,7 @@ dependencies { compile "com.google.firebase:firebase-ads:$firebaseVersion" compile "com.google.firebase:firebase-firestore:$firebaseVersion" compile "com.google.firebase:firebase-invites:$firebaseVersion" + compile('com.crashlytics.sdk.android:crashlytics:2.7.1@aar') { + transitive = true + } } diff --git a/android/src/main/java/io/invertase/firebase/fabric/crashlytics/RNFirebaseCrashlytics.java b/android/src/main/java/io/invertase/firebase/fabric/crashlytics/RNFirebaseCrashlytics.java new file mode 100644 index 00000000..f70a4732 --- /dev/null +++ b/android/src/main/java/io/invertase/firebase/fabric/crashlytics/RNFirebaseCrashlytics.java @@ -0,0 +1,65 @@ +package io.invertase.firebase.fabric.crashlytics; + +import android.util.Log; + +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; + +import com.crashlytics.android.Crashlytics; + + +public class RNFirebaseCrashlytics extends ReactContextBaseJavaModule { + + private static final String TAG = "RNFirebaseCrashlytics"; + + public RNFirebaseCrashlytics(ReactApplicationContext reactContext) { + super(reactContext); + Log.d(TAG, "New instance"); + } + + @Override + public String getName() { + return TAG; + } + + @ReactMethod + public void crash() { + Crashlytics.getInstance().crash(); + } + + @ReactMethod + public void log(final String message) { + Crashlytics.log(message); + } + + @ReactMethod + public void recordError(final int code, final String domain) { + Crashlytics.logException(new Exception(code + ": " + domain)); + } + + @ReactMethod + public void setBoolValue(final String key, final boolean boolValue) { + Crashlytics.setBool(key, boolValue); + } + + @ReactMethod + public void setFloatValue(final String key, final float floatValue) { + Crashlytics.setFloat(key, floatValue); + } + + @ReactMethod + public void setIntValue(final String key, final int intValue) { + Crashlytics.setInt(key, intValue); + } + + @ReactMethod + public void setStringValue(final String key, final String stringValue) { + Crashlytics.setString(key, stringValue); + } + + @ReactMethod + public void setUserIdentifier(String userId) { + Crashlytics.setUserIdentifier(userId); + } +} diff --git a/android/src/main/java/io/invertase/firebase/fabric/crashlytics/RNFirebaseCrashlyticsPackage.java b/android/src/main/java/io/invertase/firebase/fabric/crashlytics/RNFirebaseCrashlyticsPackage.java new file mode 100644 index 00000000..404f722a --- /dev/null +++ b/android/src/main/java/io/invertase/firebase/fabric/crashlytics/RNFirebaseCrashlyticsPackage.java @@ -0,0 +1,39 @@ +package io.invertase.firebase.fabric.crashlytics; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.ViewManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@SuppressWarnings("unused") +public class RNFirebaseCrashlyticsPackage implements ReactPackage { + public RNFirebaseCrashlyticsPackage() { + } + + /** + * @param reactContext react application context that can be used to create modules + * @return list of native modules to register with the newly created catalyst instance + */ + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + modules.add(new RNFirebaseCrashlytics(reactContext)); + + return modules; + } + + /** + * @param reactContext + * @return a list of view managers that should be registered with {@link UIManagerModule} + */ + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } +} diff --git a/ios/RNFirebase.xcodeproj/project.pbxproj b/ios/RNFirebase.xcodeproj/project.pbxproj index 9fba5805..cb5b930a 100644 --- a/ios/RNFirebase.xcodeproj/project.pbxproj +++ b/ios/RNFirebase.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 8323CF071F6FBD870071420B /* NativeExpressComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 8323CF011F6FBD870071420B /* NativeExpressComponent.m */; }; 8323CF081F6FBD870071420B /* RNFirebaseAdMobBannerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8323CF031F6FBD870071420B /* RNFirebaseAdMobBannerManager.m */; }; 8323CF091F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8323CF051F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.m */; }; + 833693131FD824EF00AA806B /* RNFirebaseCrashlytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 833693121FD824EF00AA806B /* RNFirebaseCrashlytics.m */; }; 8376F7141F7C149100D45A85 /* RNFirebaseFirestoreDocumentReference.m in Sources */ = {isa = PBXBuildFile; fileRef = 8376F70E1F7C149000D45A85 /* RNFirebaseFirestoreDocumentReference.m */; }; 8376F7151F7C149100D45A85 /* RNFirebaseFirestore.m in Sources */ = {isa = PBXBuildFile; fileRef = 8376F7101F7C149000D45A85 /* RNFirebaseFirestore.m */; }; 8376F7161F7C149100D45A85 /* RNFirebaseFirestoreCollectionReference.m in Sources */ = {isa = PBXBuildFile; fileRef = 8376F7111F7C149000D45A85 /* RNFirebaseFirestoreCollectionReference.m */; }; @@ -57,6 +58,8 @@ 8323CF031F6FBD870071420B /* RNFirebaseAdMobBannerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseAdMobBannerManager.m; sourceTree = ""; }; 8323CF041F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseAdMobNativeExpressManager.h; sourceTree = ""; }; 8323CF051F6FBD870071420B /* RNFirebaseAdMobNativeExpressManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseAdMobNativeExpressManager.m; sourceTree = ""; }; + 833693111FD824EF00AA806B /* RNFirebaseCrashlytics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNFirebaseCrashlytics.h; path = RNFirebase/fabric/crashlytics/RNFirebaseCrashlytics.h; sourceTree = SOURCE_ROOT; }; + 833693121FD824EF00AA806B /* RNFirebaseCrashlytics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNFirebaseCrashlytics.m; path = RNFirebase/fabric/crashlytics/RNFirebaseCrashlytics.m; sourceTree = SOURCE_ROOT; }; 8376F70E1F7C149000D45A85 /* RNFirebaseFirestoreDocumentReference.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseFirestoreDocumentReference.m; sourceTree = ""; }; 8376F70F1F7C149000D45A85 /* RNFirebaseFirestore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFirebaseFirestore.h; sourceTree = ""; }; 8376F7101F7C149000D45A85 /* RNFirebaseFirestore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFirebaseFirestore.m; sourceTree = ""; }; @@ -124,6 +127,7 @@ 58B511D21A9E6C8500147676 = { isa = PBXGroup; children = ( + 8336930F1FD80DE800AA806B /* fabric */, BA84AE541FA9E59800E79390 /* storage */, 17AF4F681F59CDBF00C02336 /* links */, 839D914D1EF3E20A0077C7C8 /* admob */, @@ -144,6 +148,23 @@ ); sourceTree = ""; }; + 8336930F1FD80DE800AA806B /* fabric */ = { + isa = PBXGroup; + children = ( + 833693101FD80DF500AA806B /* crashlytics */, + ); + path = fabric; + sourceTree = ""; + }; + 833693101FD80DF500AA806B /* crashlytics */ = { + isa = PBXGroup; + children = ( + 833693111FD824EF00AA806B /* RNFirebaseCrashlytics.h */, + 833693121FD824EF00AA806B /* RNFirebaseCrashlytics.m */, + ); + path = crashlytics; + sourceTree = ""; + }; 8376F70D1F7C141500D45A85 /* firestore */ = { isa = PBXGroup; children = ( @@ -328,6 +349,7 @@ 8376F7141F7C149100D45A85 /* RNFirebaseFirestoreDocumentReference.m in Sources */, 839D916F1EF3E20B0077C7C8 /* RNFirebaseAnalytics.m in Sources */, 839D91711EF3E20B0077C7C8 /* RNFirebaseRemoteConfig.m in Sources */, + 833693131FD824EF00AA806B /* RNFirebaseCrashlytics.m in Sources */, D950369E1D19C77400F7094D /* RNFirebase.m in Sources */, 839D91731EF3E20B0077C7C8 /* RNFirebaseDatabase.m in Sources */, BA84AE571FA9E59800E79390 /* RNFirebaseStorage.m in Sources */, diff --git a/ios/RNFirebase/fabric/crashlytics/RNFirebaseCrashlytics.h b/ios/RNFirebase/fabric/crashlytics/RNFirebaseCrashlytics.h new file mode 100644 index 00000000..c529237a --- /dev/null +++ b/ios/RNFirebase/fabric/crashlytics/RNFirebaseCrashlytics.h @@ -0,0 +1,19 @@ +#ifndef RNFirebaseCrashlytics_h +#define RNFirebaseCrashlytics_h +#import + +#if __has_include() +#import + +@interface RNFirebaseCrashlytics : NSObject { + +} + +@end + +#else +@interface RNFirebaseCrashlytics : NSObject +@end +#endif + +#endif diff --git a/ios/RNFirebase/fabric/crashlytics/RNFirebaseCrashlytics.m b/ios/RNFirebase/fabric/crashlytics/RNFirebaseCrashlytics.m new file mode 100644 index 00000000..393f77a1 --- /dev/null +++ b/ios/RNFirebase/fabric/crashlytics/RNFirebaseCrashlytics.m @@ -0,0 +1,47 @@ +#import "RNFirebaseCrashlytics.h" + +#if __has_include() +#import + +@implementation RNFirebaseCrashlytics +RCT_EXPORT_MODULE(); + +RCT_EXPORT_METHOD(crash) { + [[Crashlytics sharedInstance] crash]; +} + +RCT_EXPORT_METHOD(log:(NSString *)message) { + CLS_LOG(@"%@", message); +} + +RCT_EXPORT_METHOD(recordError:(nonnull NSNumber *)code domain:(NSString *)domain) { + NSError *error = [NSError errorWithDomain:domain code:[code integerValue] userInfo:nil]; + [CrashlyticsKit recordError:error]; +} + +RCT_EXPORT_METHOD(setBoolValue:(NSString *)key boolValue:(BOOL *)boolValue) { + [CrashlyticsKit setBoolValue:boolValue forKey:key]; +} + +RCT_EXPORT_METHOD(setFloatValue:(NSString *)key floatValue:(nonnull NSNumber *)floatValue) { + [CrashlyticsKit setFloatValue:[floatValue floatValue] forKey:key]; +} + +RCT_EXPORT_METHOD(setIntValue:(NSString *)key intValue:(nonnull NSNumber *)intValue) { + [CrashlyticsKit setIntValue:[intValue integerValue] forKey:key]; +} + +RCT_EXPORT_METHOD(setStringValue:(NSString *)key stringValue:(NSString *)stringValue) { + [CrashlyticsKit setObjectValue:stringValue forKey:key]; +} + +RCT_EXPORT_METHOD(setUserIdentifier:(NSString *)userId) { + [CrashlyticsKit setUserIdentifier:userId]; +} + +@end + +#else +@implementation RNFirebaseCrashlytics +@end +#endif diff --git a/lib/modules/core/firebase-app.js b/lib/modules/core/firebase-app.js index a582385b..686a0bed 100644 --- a/lib/modules/core/firebase-app.js +++ b/lib/modules/core/firebase-app.js @@ -11,6 +11,7 @@ import Auth, { statics as AuthStatics } from '../auth'; import Analytics, { statics as AnalyticsStatics } from '../analytics'; import Config, { statics as ConfigStatics } from '../config'; import Crash, { statics as CrashStatics } from '../crash'; +import Crashlytics, { statics as CrashlyticsStatics } from '../fabric/crashlytics'; import Database, { statics as DatabaseStatics } from '../database'; import Firestore, { statics as FirestoreStatics } from '../firestore'; import Links, { statics as LinksStatics } from '../links'; @@ -26,6 +27,7 @@ import type { ConfigModule, CrashModule, DatabaseModule, + FabricModule, FirebaseModule, FirebaseModuleAndStatics, FirebaseOptions, @@ -54,6 +56,7 @@ export default class FirebaseApp { config: ConfigModule; crash: CrashModule; database: DatabaseModule; + fabric: FabricModule; firestore: FirestoreModule; links: LinksModule; messaging: MessagingModule; @@ -77,6 +80,9 @@ export default class FirebaseApp { this.config = this._staticsOrModuleInstance(ConfigStatics, Config); this.crash = this._staticsOrModuleInstance(CrashStatics, Crash); this.database = this._staticsOrModuleInstance(DatabaseStatics, Database); + this.fabric = { + crashlytics: this._staticsOrModuleInstance(CrashlyticsStatics, Crashlytics), + }; this.firestore = this._staticsOrModuleInstance(FirestoreStatics, Firestore); this.links = this._staticsOrModuleInstance(LinksStatics, Links); this.messaging = this._staticsOrModuleInstance(MessagingStatics, Messaging); diff --git a/lib/modules/core/firebase.js b/lib/modules/core/firebase.js index 37e055c6..cbe83b90 100644 --- a/lib/modules/core/firebase.js +++ b/lib/modules/core/firebase.js @@ -14,6 +14,7 @@ import Auth, { statics as AuthStatics } from '../auth'; import Analytics, { statics as AnalyticsStatics } from '../analytics'; import Config, { statics as ConfigStatics } from '../config'; import Crash, { statics as CrashStatics } from '../crash'; +import Crashlytics, { statics as CrashlyticsStatics } from '../fabric/crashlytics'; import Database, { statics as DatabaseStatics } from '../database'; import Firestore, { statics as FirestoreStatics } from '../firestore'; import Links, { statics as LinksStatics } from '../links'; @@ -29,6 +30,7 @@ import type { ConfigModule, CrashModule, DatabaseModule, + FabricModule, FirebaseModule, FirebaseModuleAndStatics, FirebaseOptions, @@ -52,6 +54,7 @@ class FirebaseCore { config: ConfigModule; crash: CrashModule; database: DatabaseModule; + fabric: FabricModule; firestore: FirestoreModule; links: LinksModule; messaging: MessagingModule; @@ -76,6 +79,9 @@ class FirebaseCore { this.config = this._appNamespaceOrStatics(ConfigStatics, Config); this.crash = this._appNamespaceOrStatics(CrashStatics, Crash); this.database = this._appNamespaceOrStatics(DatabaseStatics, Database); + this.fabric = { + crashlytics: this._appNamespaceOrStatics(CrashlyticsStatics, Crashlytics), + }; this.firestore = this._appNamespaceOrStatics(FirestoreStatics, Firestore); this.links = this._appNamespaceOrStatics(LinksStatics, Links); this.messaging = this._appNamespaceOrStatics(MessagingStatics, Messaging); diff --git a/lib/modules/fabric/crashlytics/index.js b/lib/modules/fabric/crashlytics/index.js new file mode 100644 index 00000000..6ab1d9f9 --- /dev/null +++ b/lib/modules/fabric/crashlytics/index.js @@ -0,0 +1,77 @@ +/** + * @flow + * Crash Reporting representation wrapper + */ +import ModuleBase from '../../../utils/ModuleBase'; + +import type FirebaseApp from '../../core/firebase-app'; + +export default class Crashlytics extends ModuleBase { + static _NAMESPACE = 'crashlytics'; + static _NATIVE_MODULE = 'RNFirebaseCrashlytics'; + + constructor(firebaseApp: FirebaseApp, options: Object = {}) { + super(firebaseApp, options); + } + + /** + * Forces a crash. Useful for testing your application is set up correctly. + */ + crash(): void { + this._native.crash(); + } + + /** + * Logs a message that will appear in any subsequent crash reports. + * @param {string} message + */ + log(message: string): void { + this._native.log(message); + } + + /** + * Logs a non fatal exception. + * @param {string} code + * @param {string} message + */ + recordError(code: number, message: string): void { + this._native.recordError(code, message); + } + + /** + * Set a boolean value to show alongside any subsequent crash reports. + */ + setBoolValue(key: string, value: boolean): void { + this._native.setBoolValue(key, value); + } + + /** + * Set a float value to show alongside any subsequent crash reports. + */ + setFloatValue(key: string, value: number): void { + this._native.setFloatValue(key, value); + } + + /** + * Set an integer value to show alongside any subsequent crash reports. + */ + setIntValue(key: string, value: number): void { + this._native.setIntValue(key, value); + } + + /** + * Set a string value to show alongside any subsequent crash reports. + */ + setStringValue(key: string, value: string): void { + this._native.setStringValue(key, value); + } + + /** + * Set the user ID to show alongside any subsequent crash reports. + */ + setUserIdentifier(userId: string): void { + this._native.setUserIdentifier(userId); + } +} + +export const statics = {}; diff --git a/lib/types/index.js b/lib/types/index.js index 48fb199d..deded1cb 100644 --- a/lib/types/index.js +++ b/lib/types/index.js @@ -9,6 +9,8 @@ import type Config from '../modules/config'; import { typeof statics as ConfigStatics } from '../modules/config'; import type Crash from '../modules/crash'; import { typeof statics as CrashStatics } from '../modules/crash'; +import type Crashlytics from '../modules/fabric/crashlytics'; +import { typeof statics as CrashlyticsStatics } from '../modules/fabric/crashlytics'; import type Database from '../modules/database'; import { typeof statics as DatabaseStatics } from '../modules/database'; import type Firestore from '../modules/firestore'; @@ -38,8 +40,9 @@ export type FirebaseError = { export type FirebaseModule = $Subtype; -export type FirebaseModuleName = 'admob' | 'analytics' | 'auth' | 'config' | 'crash' | 'database' - | 'firestore' | 'links' | 'messaging' | 'perf' | 'storage' | 'utils'; +export type FirebaseModuleName = 'admob' | 'analytics' | 'auth' | 'config' | 'crash' + | 'crashlytics' | 'database' | 'firestore' | 'links' | 'messaging' | 'perf' | 'storage' + | 'utils'; export type FirebaseOptions = { apiKey: string, @@ -115,6 +118,16 @@ export type DatabaseModifier = { valueType?: string; } +/* Fabric types */ +export type CrashlyticsModule = { + (): Crashlytics, + nativeModuleExists: boolean, +} & CrashlyticsStatics; + +export type FabricModule = { + crashlytics: CrashlyticsModule, +} + /* Firestore types */ export type FirestoreModule = { diff --git a/tests/android/app/build.gradle b/tests/android/app/build.gradle index 83c93fac..3889b642 100644 --- a/tests/android/app/build.gradle +++ b/tests/android/app/build.gradle @@ -1,5 +1,6 @@ apply plugin: "com.android.application" apply plugin: "com.google.firebase.firebase-perf" +apply plugin: 'io.fabric' import com.android.build.OutputFile @@ -93,6 +94,9 @@ dependencies { compile "com.google.firebase:firebase-storage:$firebaseVersion" compile "com.google.firebase:firebase-firestore:$firebaseVersion" compile "com.google.firebase:firebase-invites:$firebaseVersion" + compile('com.crashlytics.sdk.android:crashlytics:2.7.1@aar') { + transitive = true + } compile "com.android.support:appcompat-v7:26.0.1" compile "com.facebook.react:react-native:+" // From node_modules } diff --git a/tests/android/app/src/main/java/com/reactnativefirebasedemo/MainApplication.java b/tests/android/app/src/main/java/com/reactnativefirebasedemo/MainApplication.java index e74da522..1385efd0 100644 --- a/tests/android/app/src/main/java/com/reactnativefirebasedemo/MainApplication.java +++ b/tests/android/app/src/main/java/com/reactnativefirebasedemo/MainApplication.java @@ -10,6 +10,7 @@ import io.invertase.firebase.auth.RNFirebaseAuthPackage; import io.invertase.firebase.config.RNFirebaseRemoteConfigPackage; import io.invertase.firebase.crash.RNFirebaseCrashPackage; import io.invertase.firebase.database.RNFirebaseDatabasePackage; +import io.invertase.firebase.fabric.crashlytics.RNFirebaseCrashlyticsPackage; import io.invertase.firebase.firestore.RNFirebaseFirestorePackage; import io.invertase.firebase.links.RNFirebaseLinksPackage; import io.invertase.firebase.messaging.RNFirebaseMessagingPackage; @@ -43,6 +44,7 @@ public class MainApplication extends Application implements ReactApplication { new RNFirebaseAuthPackage(), new RNFirebaseRemoteConfigPackage(), new RNFirebaseCrashPackage(), + new RNFirebaseCrashlyticsPackage(), new RNFirebaseDatabasePackage(), new RNFirebaseFirestorePackage(), new RNFirebaseLinksPackage(), diff --git a/tests/android/build.gradle b/tests/android/build.gradle index 32ba1492..2043c3f7 100644 --- a/tests/android/build.gradle +++ b/tests/android/build.gradle @@ -3,11 +3,15 @@ buildscript { repositories { jcenter() + maven { + url 'https://maven.fabric.io/public' + } } dependencies { classpath 'com.android.tools.build:gradle:2.3.3' - classpath 'com.google.gms:google-services:3.1.1' + classpath 'com.google.gms:google-services:3.1.2' classpath 'com.google.firebase:firebase-plugins:1.1.1' + classpath 'io.fabric.tools:gradle:1.24.4' } } diff --git a/tests/ios/Podfile b/tests/ios/Podfile index d471bdd1..980cd7c7 100644 --- a/tests/ios/Podfile +++ b/tests/ios/Podfile @@ -30,7 +30,8 @@ target 'ReactNativeFirebaseDemo' do pod 'Firebase/RemoteConfig' pod 'Firebase/Storage' pod 'Firebase/Performance' - + pod 'Fabric', '~> 1.7.2' + pod 'Crashlytics', '~> 3.9.3' pod 'RNFirebase', :path => './../../' diff --git a/tests/ios/Podfile.lock b/tests/ios/Podfile.lock index 71d4438c..f140bddf 100644 --- a/tests/ios/Podfile.lock +++ b/tests/ios/Podfile.lock @@ -5,6 +5,9 @@ PODS: - BoringSSL/Implementation (9.0): - BoringSSL/Interface (= 9.0) - BoringSSL/Interface (9.0) + - Crashlytics (3.9.3): + - Fabric (~> 1.7.2) + - Fabric (1.7.2) - Firebase/AdMob (4.3.0): - Firebase/Core - Google-Mobile-Ads-SDK (= 7.24.1) @@ -150,11 +153,13 @@ PODS: - React/Core - React/fishhook - React/RCTBlob - - RNFirebase (3.1.1-alpha.11): + - RNFirebase (3.1.1): - React - yoga (0.49.1.React) DEPENDENCIES: + - Crashlytics (~> 3.9.3) + - Fabric (~> 1.7.2) - Firebase/AdMob - Firebase/Auth - Firebase/Core @@ -184,6 +189,8 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: BoringSSL: 19083b821ef3ae0f758fae15482e183003b1e265 + Crashlytics: dbb07d01876c171c5ccbdf7826410380189e452c + Fabric: 9cd6a848efcf1b8b07497e0b6a2e7d336353ba15 Firebase: 83283761a1ef6dc9846e03d08059f51421afbd65 FirebaseAnalytics: 722b53c7b32bfc7806b06e0093a2f5180d4f2c5a FirebaseAuth: d7f047fbeab98062b98ea933b8d934e0fb1190e2 @@ -208,9 +215,9 @@ SPEC CHECKSUMS: nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3 Protobuf: 03eef2ee0b674770735cf79d9c4d3659cf6908e8 React: cf892fb84b7d06bf5fea7f328e554c6dcabe85ee - RNFirebase: e959075eb2f348c3586cd92973543b80e373b29c + RNFirebase: 30522211772f22affff6f3a61981110852d2668b yoga: 3abf02d6d9aeeb139b4c930eb1367feae690a35a -PODFILE CHECKSUM: b5674be55653f5dda937c8b794d0479900643d45 +PODFILE CHECKSUM: a5e2256012836120598e7daba7320d085400ecbb COCOAPODS: 1.2.1 diff --git a/tests/ios/ReactNativeFirebaseDemo.xcodeproj/project.pbxproj b/tests/ios/ReactNativeFirebaseDemo.xcodeproj/project.pbxproj index c1c8a35d..0c7128d5 100644 --- a/tests/ios/ReactNativeFirebaseDemo.xcodeproj/project.pbxproj +++ b/tests/ios/ReactNativeFirebaseDemo.xcodeproj/project.pbxproj @@ -636,6 +636,7 @@ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, C015646CE8F8CB4B578CE178 /* [CP] Embed Pods Frameworks */, 6AE1012F46FF8A4D1D818A12 /* [CP] Copy Pods Resources */, + 8336933B1FD8559A00AA806B /* Fabric */, ); buildRules = ( ); @@ -1043,7 +1044,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-ReactNativeFirebaseDemo/Pods-ReactNativeFirebaseDemo-resources.sh", - "$PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle", + $PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle, ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1054,6 +1055,20 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ReactNativeFirebaseDemo/Pods-ReactNativeFirebaseDemo-resources.sh\"\n"; showEnvVarsInLog = 0; }; + 8336933B1FD8559A00AA806B /* Fabric */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = Fabric; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Fabric/run\""; + }; C015646CE8F8CB4B578CE178 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/tests/src/tests/crashlytics/crashlyticsTests.js b/tests/src/tests/crashlytics/crashlyticsTests.js new file mode 100644 index 00000000..0ab89822 --- /dev/null +++ b/tests/src/tests/crashlytics/crashlyticsTests.js @@ -0,0 +1,52 @@ +export default function addTests({ describe, it, firebase }) { + describe('Crashlytics', () => { + it('log: it should log without error', () => { + return new Promise((resolve) => { + firebase.native.fabric.crashlytics().log('Test log'); + resolve(); + }); + }); + + it('recordError: it should record an error without error', () => { + return new Promise((resolve) => { + firebase.native.fabric.crashlytics().recordError(1234, 'Test error'); + resolve(); + }); + }); + + it('setBoolValue: it should set a boolean value without error', () => { + return new Promise((resolve) => { + firebase.native.fabric.crashlytics().setBoolValue('boolKey', true); + resolve(); + }); + }); + + it('setFloatValue: it should set a float value without error', () => { + return new Promise((resolve) => { + firebase.native.fabric.crashlytics().setFloatValue('floatKey', 1.23); + resolve(); + }); + }); + + it('setIntValue: it should set an integer value without error', () => { + return new Promise((resolve) => { + firebase.native.fabric.crashlytics().setIntValue('intKey', 123); + resolve(); + }); + }); + + it('setStringValue: it should set a string value without error', () => { + return new Promise((resolve) => { + firebase.native.fabric.crashlytics().setStringValue('stringKey', 'test'); + resolve(); + }); + }); + + it('setUserIdentifier: it should set the user ID without error', () => { + return new Promise((resolve) => { + firebase.native.fabric.crashlytics().setUserIdentifier('1234'); + resolve(); + }); + }); + }); +} diff --git a/tests/src/tests/crashlytics/index.js b/tests/src/tests/crashlytics/index.js new file mode 100644 index 00000000..89f6a038 --- /dev/null +++ b/tests/src/tests/crashlytics/index.js @@ -0,0 +1,10 @@ +import firebase from '../../firebase'; +import TestSuite from '../../../lib/TestSuite'; +import crashlyticsTests from './crashlyticsTests'; + +const suite = new TestSuite('Crashlytics', 'firebase.fabric.crashlytics()', firebase); + +// bootstrap tests +suite.addTests(crashlyticsTests); + +export default suite; diff --git a/tests/src/tests/index.js b/tests/src/tests/index.js index 1dbf53c6..0522195b 100644 --- a/tests/src/tests/index.js +++ b/tests/src/tests/index.js @@ -1,6 +1,7 @@ import { setSuiteStatus, setTestStatus } from '../actions/TestActions'; import analytics from './analytics'; import crash from './crash'; +import crashlytics from './crashlytics'; import core from './core'; import database from './database'; import messaging from './messaging'; @@ -23,6 +24,7 @@ const testSuiteInstances = [ config, core, crash, + crashlytics, database, firestore, messaging, From b099d13730711ac02d2a49e96f40f7cad54a20fe Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Thu, 7 Dec 2017 11:06:27 +0000 Subject: [PATCH 34/56] [firestore][tests] Add another test case for #568 --- .../firestore/collectionReferenceTests.js | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/src/tests/firestore/collectionReferenceTests.js b/tests/src/tests/firestore/collectionReferenceTests.js index dc7eb3cc..47fe4d88 100644 --- a/tests/src/tests/firestore/collectionReferenceTests.js +++ b/tests/src/tests/firestore/collectionReferenceTests.js @@ -804,6 +804,41 @@ function collectionReferenceTests({ describe, it, context, firebase, before, aft unsubscribe(); }); + + it('gets called correctly when combined with where', async () => { + const collectionRef = collectionTests.where('baz', '==', true).orderBy('daz'); + const newDocValue = { ...COL_1, daz: 678 }; + + const callback = sinon.spy(); + + // Test + + let unsubscribe; + await new Promise((resolve2) => { + unsubscribe = collectionRef.onSnapshot((snapshot) => { + callback(snapshot.docs.map(doc => doc.data().daz)); + resolve2(); + }); + }); + + callback.should.be.calledWith([123, 234, 345, 456, 567]); + + const docRef = firebase.native.firestore().doc('collection-tests2/col6'); + await docRef.set(newDocValue); + + await new Promise((resolve2) => { + setTimeout(() => resolve2(), 5); + }); + + // Assertions + + callback.should.be.calledWith([123, 234, 345, 456, 567, 678]); + callback.should.be.calledTwice(); + + // Tear down + + unsubscribe(); + }); }); after(() => { From a03c445e0c4a5391fd203dd3cca6b40f94d05c68 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Thu, 7 Dec 2017 12:36:51 +0000 Subject: [PATCH 35/56] [auth] Add support for state in email actions --- .../firebase/auth/RNFirebaseAuth.java | 94 +++++++++++++------ ios/RNFirebase/auth/RNFirebaseAuth.m | 68 ++++++++++---- lib/modules/auth/User.js | 6 +- lib/modules/auth/index.js | 6 +- lib/types/index.js | 13 +++ 5 files changed, 135 insertions(+), 52 deletions(-) diff --git a/android/src/main/java/io/invertase/firebase/auth/RNFirebaseAuth.java b/android/src/main/java/io/invertase/firebase/auth/RNFirebaseAuth.java index 601f5cb5..03538086 100644 --- a/android/src/main/java/io/invertase/firebase/auth/RNFirebaseAuth.java +++ b/android/src/main/java/io/invertase/firebase/auth/RNFirebaseAuth.java @@ -30,6 +30,7 @@ import com.google.android.gms.tasks.Task; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseException; import com.google.firebase.auth.ActionCodeResult; +import com.google.firebase.auth.ActionCodeSettings; import com.google.firebase.auth.AuthCredential; import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException; @@ -321,25 +322,32 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void sendPasswordResetEmail(String appName, final String email, final Promise promise) { + public void sendPasswordResetEmail(String appName, final String email, + ReadableMap actionCodeSettings, final Promise promise) { Log.d(TAG, "sendPasswordResetEmail"); FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); - firebaseAuth.sendPasswordResetEmail(email) - .addOnCompleteListener(new OnCompleteListener() { - @Override - public void onComplete(@NonNull Task task) { - if (task.isSuccessful()) { - Log.d(TAG, "sendPasswordResetEmail:onComplete:success"); - promiseNoUser(promise, false); - } else { - Exception exception = task.getException(); - Log.e(TAG, "sendPasswordResetEmail:onComplete:failure", exception); - promiseRejectAuthException(promise, exception); - } + OnCompleteListener listener = new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()) { + Log.d(TAG, "sendPasswordResetEmail:onComplete:success"); + promiseNoUser(promise, false); + } else { + Exception exception = task.getException(); + Log.e(TAG, "sendPasswordResetEmail:onComplete:failure", exception); + promiseRejectAuthException(promise, exception); } - }); + } + }; + + if (actionCodeSettings == null) { + firebaseAuth.sendPasswordResetEmail(email).addOnCompleteListener(listener); + } else { + ActionCodeSettings settings = buildActionCodeSettings(actionCodeSettings); + firebaseAuth.sendPasswordResetEmail(email, settings).addOnCompleteListener(listener); + } } /** @@ -439,7 +447,7 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { * @param promise */ @ReactMethod - public void sendEmailVerification(String appName, final Promise promise) { + public void sendEmailVerification(String appName, ReadableMap actionCodeSettings, final Promise promise) { FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); @@ -450,20 +458,26 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { promiseNoUser(promise, false); Log.e(TAG, "sendEmailVerification:failure:noCurrentUser"); } else { - user.sendEmailVerification() - .addOnCompleteListener(new OnCompleteListener() { - @Override - public void onComplete(@NonNull Task task) { - if (task.isSuccessful()) { - Log.d(TAG, "sendEmailVerification:onComplete:success"); - promiseWithUser(firebaseAuth.getCurrentUser(), promise); - } else { - Exception exception = task.getException(); - Log.e(TAG, "sendEmailVerification:onComplete:failure", exception); - promiseRejectAuthException(promise, exception); - } + OnCompleteListener listener = new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()) { + Log.d(TAG, "sendEmailVerification:onComplete:success"); + promiseWithUser(firebaseAuth.getCurrentUser(), promise); + } else { + Exception exception = task.getException(); + Log.e(TAG, "sendEmailVerification:onComplete:failure", exception); + promiseRejectAuthException(promise, exception); } - }); + } + }; + + if (actionCodeSettings == null) { + user.sendEmailVerification().addOnCompleteListener(listener); + } else { + ActionCodeSettings settings = buildActionCodeSettings(actionCodeSettings); + user.sendEmailVerification(settings).addOnCompleteListener(listener); + } } } @@ -1399,6 +1413,30 @@ class RNFirebaseAuth extends ReactContextBaseJavaModule { return userMap; } + private ActionCodeSettings buildActionCodeSettings(ReadableMap actionCodeSettings) { + ActionCodeSettings.Builder builder = ActionCodeSettings.newBuilder(); + ReadableMap android = actionCodeSettings.getMap("android"); + ReadableMap ios = actionCodeSettings.getMap("iOS"); + String url = actionCodeSettings.getString("url"); + if (android != null) { + boolean installApp = android.hasKey("installApp") ? android.getBoolean("installApp") : false; + String minimumVersion = android.hasKey("minimumVersion") ? android.getString("minimumVersion") : null; + String packageName = android.getString("packageName"); + builder = builder.setAndroidPackageName(packageName, installApp, minimumVersion); + } + if (actionCodeSettings.hasKey("handleCodeInApp")) { + builder = builder.setHandleCodeInApp(actionCodeSettings.getBoolean("handleCodeInApp")); + } + if (ios != null && ios.hasKey("bundleId")) { + builder = builder.setIOSBundleId(ios.getString("bundleId")); + } + if (url != null) { + builder = builder.setUrl(url); + } + + return builder.build(); + } + /** * @param appName * @param requestKey diff --git a/ios/RNFirebase/auth/RNFirebaseAuth.m b/ios/RNFirebase/auth/RNFirebaseAuth.m index 37662dcb..191d6330 100644 --- a/ios/RNFirebase/auth/RNFirebaseAuth.m +++ b/ios/RNFirebase/auth/RNFirebaseAuth.m @@ -262,24 +262,28 @@ RCT_EXPORT_METHOD(reload: @param RCTPromiseRejectBlock reject @return return */ -RCT_EXPORT_METHOD(sendEmailVerification: - (NSString *) appName - resolver: - (RCTPromiseResolveBlock) resolve - rejecter: - (RCTPromiseRejectBlock) reject) { +RCT_EXPORT_METHOD(sendEmailVerification:(NSString *) appName + actionCodeSettings:(NSDictionary *) actionCodeSettings + resolver:(RCTPromiseResolveBlock) resolve + rejecter:(RCTPromiseRejectBlock) reject) { FIRApp *firApp = [FIRApp appNamed:appName]; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; if (user) { - [user sendEmailVerificationWithCompletion:^(NSError *_Nullable error) { + id handler = ^(NSError *_Nullable error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else { FIRUser *userAfterUpdate = [FIRAuth authWithApp:firApp].currentUser; [self promiseWithUser:resolve rejecter:reject user:userAfterUpdate]; } - }]; + }; + if (actionCodeSettings) { + FIRActionCodeSettings *settings = [self buildActionCodeSettings:actionCodeSettings]; + [user sendEmailVerificationWithActionCodeSettings:settings completion:handler]; + } else { + [user sendEmailVerificationWithCompletion:handler]; + } } else { [self promiseNoUser:resolve rejecter:reject isError:YES]; } @@ -582,23 +586,27 @@ RCT_EXPORT_METHOD(checkActionCode: @param RCTPromiseRejectBlock reject @return */ -RCT_EXPORT_METHOD(sendPasswordResetEmail: - (NSString *) appName - email: - (NSString *) email - resolver: - (RCTPromiseResolveBlock) resolve - rejecter: - (RCTPromiseRejectBlock) reject) { +RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appName + email:(NSString *) email + actionCodeSettings:(NSDictionary *) actionCodeSettings + resolver:(RCTPromiseResolveBlock) resolve + rejecter:(RCTPromiseRejectBlock) reject) { FIRApp *firApp = [FIRApp appNamed:appName]; - [[FIRAuth authWithApp:firApp] sendPasswordResetWithEmail:email completion:^(NSError *_Nullable error) { + id handler = ^(NSError *_Nullable error) { if (error) { [self promiseRejectAuthException:reject error:error]; } else { [self promiseNoUser:resolve rejecter:reject isError:NO]; } - }]; + }; + + if (actionCodeSettings) { + FIRActionCodeSettings *settings = [self buildActionCodeSettings:actionCodeSettings]; + [[FIRAuth authWithApp:firApp] sendPasswordResetWithEmail:email actionCodeSettings:settings completion:handler]; + } else { + [[FIRAuth authWithApp:firApp] sendPasswordResetWithEmail:email completion:handler]; + } } /** @@ -1154,6 +1162,30 @@ RCT_EXPORT_METHOD(fetchProvidersForEmail: return userDict; } +- (FIRActionCodeSettings *)buildActionCodeSettings:(NSDictionary *)actionCodeSettings { + FIRActionCodeSettings *settings = [[FIRActionCodeSettings alloc] init]; + NSDictionary *android = actionCodeSettings[@"android"]; + BOOL handleCodeInApp = actionCodeSettings[@"handleCodeInApp"]; + NSDictionary *ios = actionCodeSettings[@"iOS"]; + NSString *url = actionCodeSettings[@"url"]; + if (android) { + BOOL installApp = android[@"installApp"]; + NSString *minimumVersion = android[@"minimumVersion"]; + NSString *packageName = android[@"packageName"]; + [settings setAndroidPackageName:packageName installIfNotAvailable:installApp minimumVersion:minimumVersion]; + } + if (handleCodeInApp) { + [settings setHandleCodeInApp:handleCodeInApp]; + } + if (ios && ios[@"bundleId"]) { + [settings setIOSBundleID:ios[@"bundleId"]]; + } + if (url) { + [settings setURL:[NSURL URLWithString:url]]; + } + return settings; +} + - (NSArray *)supportedEvents { return @[AUTH_CHANGED_EVENT, AUTH_ID_TOKEN_CHANGED_EVENT, PHONE_AUTH_STATE_CHANGED_EVENT]; } diff --git a/lib/modules/auth/User.js b/lib/modules/auth/User.js index c15f4f5d..aa6d5903 100644 --- a/lib/modules/auth/User.js +++ b/lib/modules/auth/User.js @@ -5,7 +5,7 @@ import INTERNALS from '../../utils/internals'; import type Auth from './'; -import type { AuthCredential } from '../../types'; +import type { ActionCodeSettings, AuthCredential } from '../../types'; type NativeUser = { displayName?: string, @@ -133,9 +133,9 @@ export default class User { /** * Send verification email to current user. */ - sendEmailVerification(): Promise { + sendEmailVerification(actionCodeSettings?: ActionCodeSettings): Promise { return this._auth - ._interceptUndefinedUserValue(this._auth._native.sendEmailVerification()); + ._interceptUndefinedUserValue(this._auth._native.sendEmailVerification(actionCodeSettings)); } toJSON(): Object { diff --git a/lib/modules/auth/index.js b/lib/modules/auth/index.js index 67abfe8a..b8d073db 100644 --- a/lib/modules/auth/index.js +++ b/lib/modules/auth/index.js @@ -17,7 +17,7 @@ import FacebookAuthProvider from './providers/FacebookAuthProvider'; import PhoneAuthListener from './PhoneAuthListener'; -import type { AuthCredential } from '../../types'; +import type { ActionCodeSettings, AuthCredential } from '../../types'; import type FirebaseApp from '../core/firebase-app'; type AuthResult = { @@ -268,8 +268,8 @@ export default class Auth extends ModuleBase { * Send reset password instructions via email * @param {string} email The email to send password reset instructions */ - sendPasswordResetEmail(email: string): Promise { - return this._native.sendPasswordResetEmail(email); + sendPasswordResetEmail(email: string, actionCodeSettings?: ActionCodeSettings): Promise { + return this._native.sendPasswordResetEmail(email, actionCodeSettings); } /** diff --git a/lib/types/index.js b/lib/types/index.js index deded1cb..d002a2a7 100644 --- a/lib/types/index.js +++ b/lib/types/index.js @@ -94,6 +94,19 @@ export type AuthModule = { nativeModuleExists: boolean, } & AuthStatics; +export type ActionCodeSettings = { + android: { + installApp?: boolean, + minimumVersion?: string, + packageName: string, + }, + handleCodeInApp?: boolean, + iOS: { + bundleId?: string, + }, + url: string, +} + /* Crash types */ export type CrashModule = { From 4c75e188f73cc7a1291224a20cdae1f0f64fe89a Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 15 Dec 2017 11:46:37 +0000 Subject: [PATCH 36/56] [firestore][typings] A few tweaks to match documentation --- lib/modules/firestore/CollectionReference.js | 34 ++++++++++++-------- lib/modules/firestore/DocumentReference.js | 2 +- lib/modules/firestore/Query.js | 7 ++-- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/lib/modules/firestore/CollectionReference.js b/lib/modules/firestore/CollectionReference.js index 7b0794bf..87598b57 100644 --- a/lib/modules/firestore/CollectionReference.js +++ b/lib/modules/firestore/CollectionReference.js @@ -6,9 +6,11 @@ import DocumentReference from './DocumentReference'; import Query from './Query'; import { firestoreAutoId } from '../../utils'; +import type DocumentSnapshot from './DocumentSnapshot'; import type Firestore from './'; import type { FirestoreQueryDirection, FirestoreQueryOperator } from '../../types'; import type Path from './Path'; +import type { Observer, QueryListenOptions } from './Query'; import type QuerySnapshot from './QuerySnapshot'; /** @@ -19,13 +21,13 @@ export default class CollectionReference { _firestore: Firestore; _query: Query; - constructor(firestore: Object, collectionPath: Path) { + constructor(firestore: Firestore, collectionPath: Path) { this._collectionPath = collectionPath; this._firestore = firestore; this._query = new Query(firestore, collectionPath); } - get firestore(): Object { + get firestore(): Firestore { return this._firestore; } @@ -56,36 +58,40 @@ export default class CollectionReference { } // From Query - endAt(fieldValues: any): Query { - return this._query.endAt(fieldValues); + endAt(...snapshotOrVarArgs: any[]): Query { + return this._query.endAt(snapshotOrVarArgs); } - endBefore(fieldValues: any): Query { - return this._query.endBefore(fieldValues); + endBefore(...snapshotOrVarArgs: any[]): Query { + return this._query.endBefore(snapshotOrVarArgs); } get(): Promise { return this._query.get(); } - limit(n: number): Query { - return this._query.limit(n); + limit(limit: number): Query { + return this._query.limit(limit); } - onSnapshot(onNext: () => any, onError?: () => any): () => void { - return this._query.onSnapshot(onNext, onError); + onSnapshot( + optionsOrObserverOrOnNext: QueryListenOptions | Observer | (DocumentSnapshot) => void, + observerOrOnNextOrOnError?: Observer | (DocumentSnapshot) => void | (Object) => void, + onError?: (Object) => void, + ): () => void { + return this._query.onSnapshot(optionsOrObserverOrOnNext, observerOrOnNextOrOnError, onError); } orderBy(fieldPath: string, directionStr?: FirestoreQueryDirection): Query { return this._query.orderBy(fieldPath, directionStr); } - startAfter(fieldValues: any): Query { - return this._query.startAfter(fieldValues); + startAfter(...snapshotOrVarArgs: any[]): Query { + return this._query.startAfter(snapshotOrVarArgs); } - startAt(fieldValues: any): Query { - return this._query.startAt(fieldValues); + startAt(...snapshotOrVarArgs: any[]): Query { + return this._query.startAt(snapshotOrVarArgs); } where(fieldPath: string, opStr: FirestoreQueryOperator, value: any): Query { diff --git a/lib/modules/firestore/DocumentReference.js b/lib/modules/firestore/DocumentReference.js index b47c88c6..97d7c4ae 100644 --- a/lib/modules/firestore/DocumentReference.js +++ b/lib/modules/firestore/DocumentReference.js @@ -163,7 +163,7 @@ export default class DocumentReference { .documentSet(this.path, nativeData, writeOptions); } - update(...args: Array): Promise { + update(...args: any[]): Promise { let data = {}; if (args.length === 1) { if (!isObject(args[0])) { diff --git a/lib/modules/firestore/Query.js b/lib/modules/firestore/Query.js index 507399ff..af11cae4 100644 --- a/lib/modules/firestore/Query.js +++ b/lib/modules/firestore/Query.js @@ -45,12 +45,13 @@ type QueryOptions = { startAfter?: any[], startAt?: any[], } -type QueryListenOptions = { + +export type QueryListenOptions = { includeDocumentMetadataChanges: boolean, includeQueryMetadataChanges: boolean, } -type Observer = { +export type Observer = { next: (DocumentSnapshot) => void, error?: (Object) => void, } @@ -81,7 +82,7 @@ export default class Query { this._referencePath = path; } - get firestore(): Object { + get firestore(): Firestore { return this._firestore; } From 3a497fa1a2d7d0fc77650c4963449c03aa6eca5b Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 15 Dec 2017 15:14:05 +0000 Subject: [PATCH 37/56] [ios] Update podspec location to resolve RN 0.50+ install issues --- RNFirebase.podspec => ios/RNFirebase.podspec | 9 +++--- tests/ios/Podfile | 4 +-- tests/ios/Podfile.lock | 8 +++--- .../project.pbxproj | 28 ------------------- 4 files changed, 10 insertions(+), 39 deletions(-) rename RNFirebase.podspec => ios/RNFirebase.podspec (72%) diff --git a/RNFirebase.podspec b/ios/RNFirebase.podspec similarity index 72% rename from RNFirebase.podspec rename to ios/RNFirebase.podspec index 1582c3f0..dc1e73af 100644 --- a/RNFirebase.podspec +++ b/ios/RNFirebase.podspec @@ -1,5 +1,5 @@ require 'json' -package = JSON.parse(File.read('package.json')) +package = JSON.parse(File.read('../package.json')) Pod::Spec.new do |s| s.name = "RNFirebase" @@ -12,9 +12,8 @@ Pod::Spec.new do |s| s.license = package['license'] s.authors = "Invertase Limited" s.source = { :git => "https://github.com/invertase/react-native-firebase.git", :tag => "v#{s.version}" } - s.social_media_url = 'http://twitter.com/mikediarmid' - s.platform = :ios, "8.0" - s.preserve_paths = 'README.md', 'package.json', '*.js' - s.source_files = 'ios/RNFirebase/**/*.{h,m}' + s.social_media_url = 'http://twitter.com/RNFirebase' + s.platform = :ios, "9.0" + s.source_files = 'RNFirebase/**/*.{h,m}' s.dependency 'React' end diff --git a/tests/ios/Podfile b/tests/ios/Podfile index 980cd7c7..09601bba 100644 --- a/tests/ios/Podfile +++ b/tests/ios/Podfile @@ -3,7 +3,7 @@ install! 'cocoapods', :deterministic_uuids => false # platform :ios, '8.0' target 'ReactNativeFirebaseDemo' do - platform :ios, '8.0' + platform :ios, '9.0' # Uncomment this line if you're using Swift or would like to use dynamic frameworks # use_frameworks! @@ -33,7 +33,7 @@ target 'ReactNativeFirebaseDemo' do pod 'Fabric', '~> 1.7.2' pod 'Crashlytics', '~> 3.9.3' - pod 'RNFirebase', :path => './../../' + pod 'RNFirebase', :path => '../../ios/RNFirebase.podspec' post_install do |installer| installer.pods_project.targets.each do |target| diff --git a/tests/ios/Podfile.lock b/tests/ios/Podfile.lock index f140bddf..55bf24ba 100644 --- a/tests/ios/Podfile.lock +++ b/tests/ios/Podfile.lock @@ -176,14 +176,14 @@ DEPENDENCIES: - React/RCTNetwork (from `../node_modules/react-native`) - React/RCTText (from `../node_modules/react-native`) - React/RCTWebSocket (from `../node_modules/react-native`) - - RNFirebase (from `./../../`) + - RNFirebase (from `../../ios/RNFirebase.podspec`) - yoga (from `../node_modules/react-native/ReactCommon/yoga`) EXTERNAL SOURCES: React: :path: "../node_modules/react-native" RNFirebase: - :path: "./../../" + :path: "../../ios/RNFirebase.podspec" yoga: :path: "../node_modules/react-native/ReactCommon/yoga" @@ -215,9 +215,9 @@ SPEC CHECKSUMS: nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3 Protobuf: 03eef2ee0b674770735cf79d9c4d3659cf6908e8 React: cf892fb84b7d06bf5fea7f328e554c6dcabe85ee - RNFirebase: 30522211772f22affff6f3a61981110852d2668b + RNFirebase: 976f3b35d112017c69da5ada20cf1f15fc2c327e yoga: 3abf02d6d9aeeb139b4c930eb1367feae690a35a -PODFILE CHECKSUM: a5e2256012836120598e7daba7320d085400ecbb +PODFILE CHECKSUM: f17a538903249834df5049668d10174810db4c4c COCOAPODS: 1.2.1 diff --git a/tests/ios/ReactNativeFirebaseDemo.xcodeproj/project.pbxproj b/tests/ios/ReactNativeFirebaseDemo.xcodeproj/project.pbxproj index 0c7128d5..ff7a6e40 100644 --- a/tests/ios/ReactNativeFirebaseDemo.xcodeproj/project.pbxproj +++ b/tests/ios/ReactNativeFirebaseDemo.xcodeproj/project.pbxproj @@ -265,13 +265,6 @@ remoteGlobalIDString = 3D383D621EBD27B9005632C8; remoteInfo = "double-conversion-tvOS"; }; - 997890041E69DE2900F6820C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C7C48FEEC8E34DE4BB5DE211 /* RNFirebase.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = E26E29F41BBE54B800BF9CD9; - remoteInfo = RNFirebase; - }; 997890071E69DE2900F6820C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 8BE028F5B04B4DC3BEF0305F /* RNVectorIcons.xcodeproj */; @@ -320,7 +313,6 @@ 8EE7622B1E718A8600B1E0F6 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 93FF19757985B70080544398 /* Pods-ReactNativeFirebaseDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReactNativeFirebaseDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-ReactNativeFirebaseDemo/Pods-ReactNativeFirebaseDemo.release.xcconfig"; sourceTree = ""; }; BBEE706291534F5F948A3805 /* libLRDRCTSimpleToast.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libLRDRCTSimpleToast.a; sourceTree = ""; }; - C7C48FEEC8E34DE4BB5DE211 /* RNFirebase.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNFirebase.xcodeproj; path = "../node_modules/react-native-firebase/RNFirebase.xcodeproj"; sourceTree = ""; }; CC24EB30F0484352BD65FFC1 /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; sourceTree = ""; }; DB5BB32AF70B41678974C6B4 /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = ""; }; FD3DFC8253C74B6298AFD3B7 /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = SimpleLineIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf"; sourceTree = ""; }; @@ -521,7 +513,6 @@ 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, - C7C48FEEC8E34DE4BB5DE211 /* RNFirebase.xcodeproj */, 8BE028F5B04B4DC3BEF0305F /* RNVectorIcons.xcodeproj */, ); name = Libraries; @@ -570,14 +561,6 @@ name = Products; sourceTree = ""; }; - 99788FE61E69DE2900F6820C /* Products */ = { - isa = PBXGroup; - children = ( - 997890051E69DE2900F6820C /* RNFirebase.framework */, - ); - name = Products; - sourceTree = ""; - }; 99788FE81E69DE2900F6820C /* Products */ = { isa = PBXGroup; children = ( @@ -722,10 +705,6 @@ ProductGroup = 146834001AC3E56700842450 /* Products */; ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; }, - { - ProductGroup = 99788FE61E69DE2900F6820C /* Products */; - ProjectRef = C7C48FEEC8E34DE4BB5DE211 /* RNFirebase.xcodeproj */; - }, { ProductGroup = 99788FE81E69DE2900F6820C /* Products */; ProjectRef = 8BE028F5B04B4DC3BEF0305F /* RNVectorIcons.xcodeproj */; @@ -957,13 +936,6 @@ remoteRef = 8EC7AC3A1F8397E50041B0FE /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 997890051E69DE2900F6820C /* RNFirebase.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = RNFirebase.framework; - remoteRef = 997890041E69DE2900F6820C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 997890081E69DE2900F6820C /* libRNVectorIcons.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; From 2dcb84c327018cb9313176bd405371c0ed0c8ef7 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 15 Dec 2017 16:04:54 +0000 Subject: [PATCH 38/56] [ios] Add Fabric and Crashlytics search paths --- ios/RNFirebase.xcodeproj/project.pbxproj | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ios/RNFirebase.xcodeproj/project.pbxproj b/ios/RNFirebase.xcodeproj/project.pbxproj index cb5b930a..03e64c14 100644 --- a/ios/RNFirebase.xcodeproj/project.pbxproj +++ b/ios/RNFirebase.xcodeproj/project.pbxproj @@ -454,6 +454,8 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "${BUILT_PRODUCTS_DIR}", + "${SRCROOT}/../../../ios/Pods/Crashlytics/Frameworks", + "${SRCROOT}/../../../ios/Pods/Fabric/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseAnalytics/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseAuth/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseCore/Frameworks", @@ -472,8 +474,10 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../../react-native/React/**", - "${SRCROOT}/../../../ios/Pods/Firebase/**", + "${SRCROOT}/../../../ios/Crashlytics/**", + "${SRCROOT}/../../../ios/Fabric/**", "${SRCROOT}/../../../ios/Firebase/**", + "${SRCROOT}/../../../ios/Pods/Firebase/**", ); IPHONEOS_DEPLOYMENT_TARGET = 8.0; LIBRARY_SEARCH_PATHS = "$(inherited)"; @@ -495,6 +499,8 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "${BUILT_PRODUCTS_DIR}", + "${SRCROOT}/../../../ios/Pods/Crashlytics/Frameworks", + "${SRCROOT}/../../../ios/Pods/Fabric/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseAnalytics/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseAuth/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseCore/Frameworks", @@ -513,8 +519,10 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../../react-native/React/**", - "${SRCROOT}/../../../ios/Pods/Firebase/**", + "${SRCROOT}/../../../ios/Crashlytics/**", + "${SRCROOT}/../../../ios/Fabric/**", "${SRCROOT}/../../../ios/Firebase/**", + "${SRCROOT}/../../../ios/Pods/Firebase/**", ); IPHONEOS_DEPLOYMENT_TARGET = 8.0; LIBRARY_SEARCH_PATHS = "$(inherited)"; From 865944d9a99d11a7e0ec92a5a6b4ebb802bbdcaf Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 15 Dec 2017 16:09:02 +0000 Subject: [PATCH 39/56] [ios][links] Remove warning for dynamic links --- ios/RNFirebase/links/RNFirebaseLinks.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ios/RNFirebase/links/RNFirebaseLinks.m b/ios/RNFirebase/links/RNFirebaseLinks.m index 350eb25b..46478d46 100644 --- a/ios/RNFirebase/links/RNFirebaseLinks.m +++ b/ios/RNFirebase/links/RNFirebaseLinks.m @@ -268,6 +268,11 @@ RCT_EXPORT_METHOD(createShortDynamicLink: (NSDictionary *) metadata resolver:(RC } } ++ (BOOL)requiresMainQueueSetup +{ + return YES; +} + @end #else From c8d82207f40a11a07c06e0ee3082d63970bba802 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 15 Dec 2017 17:04:11 +0000 Subject: [PATCH 40/56] [crashlytics][ios] Fix a couple of minor issues --- ios/RNFirebase.xcodeproj/project.pbxproj | 12 ++++++------ lib/modules/core/firebase.js | 6 +++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/ios/RNFirebase.xcodeproj/project.pbxproj b/ios/RNFirebase.xcodeproj/project.pbxproj index 03e64c14..50eb67bb 100644 --- a/ios/RNFirebase.xcodeproj/project.pbxproj +++ b/ios/RNFirebase.xcodeproj/project.pbxproj @@ -454,7 +454,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "${BUILT_PRODUCTS_DIR}", - "${SRCROOT}/../../../ios/Pods/Crashlytics/Frameworks", + "${SRCROOT}/../../../ios/Pods/Crashlytics/Frameworks/iOS", "${SRCROOT}/../../../ios/Pods/Fabric/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseAnalytics/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseAuth/Frameworks", @@ -474,9 +474,9 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../../react-native/React/**", - "${SRCROOT}/../../../ios/Crashlytics/**", - "${SRCROOT}/../../../ios/Fabric/**", "${SRCROOT}/../../../ios/Firebase/**", + "${SRCROOT}/../../../ios/Pods/Headers/Public/Crashlytics", + "${SRCROOT}/../../../ios/Pods/Headers/Public/Fabric", "${SRCROOT}/../../../ios/Pods/Firebase/**", ); IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -499,7 +499,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "${BUILT_PRODUCTS_DIR}", - "${SRCROOT}/../../../ios/Pods/Crashlytics/Frameworks", + "${SRCROOT}/../../../ios/Pods/Crashlytics/Frameworks/iOS", "${SRCROOT}/../../../ios/Pods/Fabric/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseAnalytics/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseAuth/Frameworks", @@ -519,9 +519,9 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../../react-native/React/**", - "${SRCROOT}/../../../ios/Crashlytics/**", - "${SRCROOT}/../../../ios/Fabric/**", "${SRCROOT}/../../../ios/Firebase/**", + "${SRCROOT}/../../../ios/Pods/Headers/Public/Crashlytics", + "${SRCROOT}/../../../ios/Pods/Headers/Public/Fabric", "${SRCROOT}/../../../ios/Pods/Firebase/**", ); IPHONEOS_DEPLOYMENT_TARGET = 8.0; diff --git a/lib/modules/core/firebase.js b/lib/modules/core/firebase.js index cbe83b90..e9fe087f 100644 --- a/lib/modules/core/firebase.js +++ b/lib/modules/core/firebase.js @@ -238,7 +238,11 @@ class FirebaseCore { // default to the 'DEFAULT' app if no arg provided - will throw an error // if default app not initialized else if (!_app) _app = this.app(INTERNALS.STRINGS.DEFAULT_APP_NAME); - return INTERNALS.APPS[_app._name][namespace](_app); + const firebaseApp = INTERNALS.APPS[_app._name]; + if (namespace === 'crashlytics') { + return firebaseApp.fabric[namespace](_app); + } + return firebaseApp[namespace](_app); }; return Object.assign(getNamespace, statics, { From 57a23e4263360e6223532577bbae828e4fe3f3ed Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 15 Dec 2017 17:09:11 +0000 Subject: [PATCH 41/56] 3.2.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index e637199d..eaedc9aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "3.1.1", + "version": "3.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 813c3530..cc3641f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-firebase", - "version": "3.1.1", + "version": "3.2.0", "author": "Invertase (http://invertase.io)", "description": "A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Messaging (FCM), Remote Config, Storage and Performance.", "main": "dist/index.js", From 92ae311ed1870d77bf62e34fc3ff0027c3c470e8 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 15 Dec 2017 17:16:32 +0000 Subject: [PATCH 42/56] [ios] Final header fix for crashlytics --- ios/RNFirebase.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/RNFirebase.xcodeproj/project.pbxproj b/ios/RNFirebase.xcodeproj/project.pbxproj index 50eb67bb..da929dcf 100644 --- a/ios/RNFirebase.xcodeproj/project.pbxproj +++ b/ios/RNFirebase.xcodeproj/project.pbxproj @@ -454,7 +454,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "${BUILT_PRODUCTS_DIR}", - "${SRCROOT}/../../../ios/Pods/Crashlytics/Frameworks/iOS", + "${SRCROOT}/../../../ios/Pods/Crashlytics/iOS", "${SRCROOT}/../../../ios/Pods/Fabric/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseAnalytics/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseAuth/Frameworks", @@ -499,7 +499,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "${BUILT_PRODUCTS_DIR}", - "${SRCROOT}/../../../ios/Pods/Crashlytics/Frameworks/iOS", + "${SRCROOT}/../../../ios/Pods/Crashlytics/iOS", "${SRCROOT}/../../../ios/Pods/Fabric/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseAnalytics/Frameworks", "${SRCROOT}/../../../ios/Pods/FirebaseAuth/Frameworks", From 10ca69c30763deb08e646508fd47338f77a583b8 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 15 Dec 2017 18:17:43 +0000 Subject: [PATCH 43/56] Update README.md --- README.md | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 7d9fb11e..c96fe625 100644 --- a/README.md +++ b/README.md @@ -35,37 +35,38 @@ All in all, RNFirebase provides much faster performance (~2x) over the web SDK a > '**?**' indicates partial support -| Firebase Features | v1.x.x | v2.x.x | v3.x.x | v3.1.x | Web SDK | -| ---------------------- | :---: | :---: | :---: | :---: | :---: | -| **AdMob** | ❌ | ✅ | ✅ | ✅ | ❌ | -| **Analytics**             | ✅ | ✅ | ✅ | ✅ | ❌ | -| **App Indexing**           | ❌ | ❌ | ❌ | ❌ | ❌ | -| **Authentication** | ✅ | ✅ | ✅ | ✅ | ✅ | -| _-- Phone Auth_ | ❌ | ❌ | ✅ | ✅ | ❌ | -| **Core** | ❌ |**?**| ✅ | ✅ | ✅ | -| _-- Multiple Apps_ | ❌ | ❌ | ✅ | ✅ | ✅ | -| **Cloud Firestore** | ❌ | ❌ | ✅ | ✅ |**?**| -| **Cloud Messaging (FCM)** | ✅ | ✅ | ✅ | ✅ |**?**| -| **Crash Reporting** | ✅ | ✅ | ✅ | ✅ | ❌ | -| **Dynamic Links** | ❌ | ❌ | ❌ | ✅ | ❌ | -| **Invites** | ❌ | ❌ | ❌ |**?**| ❌ | -| **Performance Monitoring** | ✅ | ✅ | ✅ | ✅ | ❌ | -| **Realtime Database** | ✅ | ✅ | ✅ | ✅ | ✅ | -| _-- Offline Persistence_ | ✅ | ✅ | ✅ | ✅ |**?**| -| _-- Transactions_ | ✅ | ✅ | ✅ | ✅ | ✅ | -| **Remote Config** | ✅ | ✅ | ✅ | ✅ | ❌ | -| **Storage** | ✅ | ✅ | ✅ | ✅ |**?**| +| Firebase Features | v1.x.x | v2.x.x | v3.x.x | v3.1.x | v3.2.x | Web SDK | +| ---------------------- | :---: | :---: | :---: | :---: | :---: | :---: | +| **AdMob** | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | +| **Analytics**             | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| **App Indexing**           | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| **Authentication** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| _-- Phone Auth_ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | +| **Core** | ❌ |**?**| ✅ | ✅ | ✅ | ✅ | +| _-- Multiple Apps_ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | +| **Cloud Firestore** | ❌ | ❌ | ✅ | ✅ | ✅ |**?**| +| **Cloud Messaging (FCM)** | ✅ | ✅ | ✅ | ✅ | ✅ |**?**| +| **Crashlytics**           | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | +| **Crash Reporting** | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| **Dynamic Links** | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | +| **Invites** | ❌ | ❌ | ❌ |**?**|**?**| ❌ | +| **Performance Monitoring** | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| **Realtime Database** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| _-- Offline Persistence_ | ✅ | ✅ | ✅ | ✅ | ✅ |**?**| +| _-- Transactions_ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| **Remote Config** | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| **Storage** | ✅ | ✅ | ✅ | ✅ | ✅ |**?**| --- ### Supported versions - React Native / Firebase > The table below shows the supported versions of React Native and the Firebase SDKs for different versions of `react-native-firebase` -| | 1.X.X | 2.0.X | 2.1.X / 2.2.X | 3.0.X | 3.1.X | -|------------------------|-------------|-------------|-----------------|----------|----------| -| React Native | 0.36 - 0.39 | 0.40 - 0.46 | 0.47 + | 0.48 + | 0.48 + | -| Firebase Android SDK | 10.2.0 + | 11.0.0 + | 11.0.0 + | 11.4.2 + | 11.4.2 + | -| Firebase iOS SDK | 3.15.0 + | 4.0.0 + | 4.0.0 + | 4.3.0 + | 4.5.0 + | +| | 1.X.X | 2.0.X | 2.1.X / 2.2.X | 3.0.X | 3.1.X | 3.2.X | +|------------------------|-------------|-------------|-----------------|----------|-------------|----------| +| React Native | 0.36 - 0.39 | 0.40 - 0.46 | 0.47 + | 0.48 + | 0.48 - 0.49 | 0.50 + | +| Firebase Android SDK | 10.2.0 + | 11.0.0 + | 11.0.0 + | 11.4.2 + | 11.6.0 + | 11.6.2 + | +| Firebase iOS SDK | 3.15.0 + | 4.0.0 + | 4.0.0 + | 4.3.0 + | 4.5.0 + | 4.7.0 + | --- From 1a35d8a7b5f64f331fdad59964967a130764018b Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Thu, 21 Dec 2017 09:31:46 +0000 Subject: [PATCH 44/56] Remove unnecessary configuration files from npm build #698 --- .npmignore | 9 +++++++++ package.json | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.npmignore b/.npmignore index 4f4a63e3..17082b9a 100644 --- a/.npmignore +++ b/.npmignore @@ -11,6 +11,15 @@ npm-debug.log project.xcworkspace/ xcuserdata/ +# Config files +.babelrc +.editorconfig +.eslintrc +.flowconfig +.watchmanconfig +buddybuild_postclone.sh +jsconfig.json + # Example example/ diff --git a/package.json b/package.json index cc3641f6..adad4656 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,8 @@ "firestack", "performance", "firestore", - "dynamic-links" + "dynamic-links", + "crashlytics" ], "peerDependencies": { "react": "*", From f2c2007fdc75a99e6405040280bd8885d6b3e10a Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 22 Dec 2017 15:24:31 +0000 Subject: [PATCH 45/56] [internals] Start refactoring some of the internals to simplify, tidy up and also reduce flow type pollution --- lib/index.js | 6 +- lib/modules/admob/Interstitial.js | 11 +- lib/modules/admob/RewardedVideo.js | 11 +- lib/modules/admob/index.js | 22 +-- lib/modules/auth/PhoneAuthListener.js | 19 ++- lib/modules/auth/index.js | 46 ++--- lib/modules/config/index.js | 9 +- lib/modules/core/firebase-app.js | 167 ++++++------------ lib/modules/core/firebase.js | 190 +++------------------ lib/modules/database/reference.js | 15 +- lib/modules/database/transaction.js | 8 +- lib/modules/firestore/DocumentReference.js | 13 +- lib/modules/firestore/Query.js | 13 +- lib/modules/firestore/index.js | 77 ++++----- lib/modules/links/index.js | 5 +- lib/modules/messaging/index.js | 7 +- lib/modules/storage/index.js | 24 +-- lib/modules/utils/index.js | 4 - lib/utils/ModuleBase.js | 130 +------------- lib/utils/ReferenceBase.js | 6 - lib/utils/SyncTree.js | 16 +- lib/utils/apps.js | 167 ++++++++++++++++++ lib/utils/events.js | 81 +++++++++ lib/utils/index.js | 19 --- lib/utils/internals.js | 22 --- lib/utils/log.js | 14 ++ lib/utils/native.js | 62 +++++++ tests/ios/Podfile.lock | 4 +- tests/src/firebase.js | 2 +- tests/src/tests/core/coreTests.js | 3 +- 30 files changed, 563 insertions(+), 610 deletions(-) create mode 100644 lib/utils/apps.js create mode 100644 lib/utils/events.js create mode 100644 lib/utils/native.js diff --git a/lib/index.js b/lib/index.js index 0d65d53e..b31d093b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,8 +1,8 @@ /** * @flow */ -import Firebase from './modules/core/firebase'; +import firebase from './modules/core/firebase'; -export const AdMob = require('./modules/admob'); +export type { default as User } from './modules/auth/User'; -export default Firebase; +export default firebase; diff --git a/lib/modules/admob/Interstitial.js b/lib/modules/admob/Interstitial.js index 617945be..06ff6eee 100644 --- a/lib/modules/admob/Interstitial.js +++ b/lib/modules/admob/Interstitial.js @@ -1,6 +1,7 @@ import { NativeModules, Platform } from 'react-native'; import { statics } from './'; import AdRequest from './AdRequest'; +import { SharedEventEmitter } from '../../utils/events'; import { nativeToJSError } from '../../utils'; const FirebaseAdMob = NativeModules.RNFirebaseAdMob; @@ -23,8 +24,8 @@ export default class Interstitial { this.admob = admob; this.adUnit = adUnit; this.loaded = false; - this.admob.removeAllListeners(`interstitial_${adUnit}`); - this.admob.on(`interstitial_${adUnit}`, this._onInterstitialEvent); + SharedEventEmitter.removeAllListeners(`interstitial_${adUnit}`); + SharedEventEmitter.addListener(`interstitial_${adUnit}`, this._onInterstitialEvent); } /** @@ -48,8 +49,8 @@ export default class Interstitial { default: } - this.admob.emit(eventType, emitData); - this.admob.emit(`interstitial:${this.adUnit}:*`, emitData); + SharedEventEmitter.emit(eventType, emitData); + SharedEventEmitter.emit(`interstitial:${this.adUnit}:*`, emitData); }; /** @@ -97,7 +98,7 @@ export default class Interstitial { return null; } - const sub = this.admob.on(`interstitial:${this.adUnit}:${eventType}`, listenerCb); + const sub = SharedEventEmitter.addListener(`interstitial:${this.adUnit}:${eventType}`, listenerCb); subscriptions.push(sub); return sub; } diff --git a/lib/modules/admob/RewardedVideo.js b/lib/modules/admob/RewardedVideo.js index f34f5eec..84b02860 100644 --- a/lib/modules/admob/RewardedVideo.js +++ b/lib/modules/admob/RewardedVideo.js @@ -1,6 +1,7 @@ import { NativeModules } from 'react-native'; import { statics } from './'; import AdRequest from './AdRequest'; +import { SharedEventEmitter } from '../../utils/events'; import { nativeToJSError } from '../../utils'; const FirebaseAdMob = NativeModules.RNFirebaseAdMob; @@ -18,8 +19,8 @@ export default class RewardedVideo { this.admob = admob; this.adUnit = adUnit; this.loaded = false; - this.admob.removeAllListeners(`rewarded_video_${adUnit}`); - this.admob.on(`rewarded_video_${adUnit}`, this._onRewardedVideoEvent); + SharedEventEmitter.removeAllListeners(`rewarded_video_${adUnit}`); + SharedEventEmitter.addListener(`rewarded_video_${adUnit}`, this._onRewardedVideoEvent); } /** @@ -43,8 +44,8 @@ export default class RewardedVideo { default: } - this.admob.emit(eventType, emitData); - this.admob.emit(`rewarded_video:${this.adUnit}:*`, emitData); + SharedEventEmitter.emit(eventType, emitData); + SharedEventEmitter.emit(`rewarded_video:${this.adUnit}:*`, emitData); }; /** @@ -97,7 +98,7 @@ export default class RewardedVideo { return null; } - const sub = this.admob.on(`rewarded_video:${this.adUnit}:${eventType}`, listenerCb); + const sub = SharedEventEmitter.addListener(`rewarded_video:${this.adUnit}:${eventType}`, listenerCb); subscriptions.push(sub); return sub; } diff --git a/lib/modules/admob/index.js b/lib/modules/admob/index.js index c044646b..070e1a3f 100644 --- a/lib/modules/admob/index.js +++ b/lib/modules/admob/index.js @@ -2,7 +2,9 @@ * @flow * AdMob representation wrapper */ -import ModuleBase from './../../utils/ModuleBase'; +import { SharedEventEmitter } from '../../utils/events'; +import { getLogger } from '../../utils/log'; +import ModuleBase from '../../utils/ModuleBase'; import Interstitial from './Interstitial'; import RewardedVideo from './RewardedVideo'; @@ -37,35 +39,35 @@ export default class AdMob extends ModuleBase { this._initialized = false; this._appId = null; - this._eventEmitter.addListener('interstitial_event', this._onInterstitialEvent.bind(this)); - this._eventEmitter.addListener('rewarded_video_event', this._onRewardedVideoEvent.bind(this)); + SharedEventEmitter.addListener('interstitial_event', this._onInterstitialEvent.bind(this)); + SharedEventEmitter.addListener('rewarded_video_event', this._onRewardedVideoEvent.bind(this)); } _onInterstitialEvent(event: NativeEvent): void { const { adUnit } = event; const jsEventType = `interstitial_${adUnit}`; - if (!this.hasListeners(jsEventType)) { + if (!SharedEventEmitter.hasListeners(jsEventType)) { // TODO } - this.emit(jsEventType, event); + SharedEventEmitter.emit(jsEventType, event); } _onRewardedVideoEvent(event: NativeEvent): void { const { adUnit } = event; const jsEventType = `rewarded_video_${adUnit}`; - if (!this.hasListeners(jsEventType)) { + if (!SharedEventEmitter.hasListeners(jsEventType)) { // TODO } - this.emit(jsEventType, event); + SharedEventEmitter.emit(jsEventType, event); } initialize(appId: string): void { if (this._initialized) { - this.log.warn('AdMob has already been initialized!'); + getLogger(this).warn('AdMob has already been initialized!'); } else { this._initialized = true; this._appId = appId; @@ -75,9 +77,9 @@ export default class AdMob extends ModuleBase { openDebugMenu(): void { if (!this._initialized) { - this.log.warn('AdMob needs to be initialized before opening the dev menu!'); + getLogger(this).warn('AdMob needs to be initialized before opening the dev menu!'); } else { - this.log.info('Opening debug menu'); + getLogger(this).info('Opening debug menu'); this._native.openDebugMenu(this._appId); } } diff --git a/lib/modules/auth/PhoneAuthListener.js b/lib/modules/auth/PhoneAuthListener.js index 0848b080..9503d8cf 100644 --- a/lib/modules/auth/PhoneAuthListener.js +++ b/lib/modules/auth/PhoneAuthListener.js @@ -1,5 +1,6 @@ // @flow import INTERNALS from '../../utils/internals'; +import { SharedEventEmitter } from '../../utils/events'; import { generatePushID, isFunction, isAndroid, isIOS, isString, nativeToJSError } from './../../utils'; import type Auth from './'; @@ -92,7 +93,7 @@ export default class PhoneAuthListener { for (let i = 0, len = events.length; i < len; i++) { const type = events[i]; - this._auth.once(this._internalEvents[type], this[`_${type}Handler`].bind(this)); + SharedEventEmitter.once(this._internalEvents[type], this[`_${type}Handler`].bind(this)); } } @@ -102,7 +103,7 @@ export default class PhoneAuthListener { * @private */ _addUserObserver(observer) { - this._auth.on(this._publicEvents.event, observer); + SharedEventEmitter.addListener(this._publicEvents.event, observer); } /** @@ -111,7 +112,7 @@ export default class PhoneAuthListener { * @private */ _emitToObservers(snapshot: PhoneAuthSnapshot) { - this._auth.emit(this._publicEvents.event, snapshot); + SharedEventEmitter.emit(this._publicEvents.event, snapshot); } /** @@ -122,7 +123,7 @@ export default class PhoneAuthListener { _emitToErrorCb(snapshot) { const error = snapshot.error; if (this._reject) this._reject(error); - this._auth.emit(this._publicEvents.error, error); + SharedEventEmitter.emit(this._publicEvents.error, error); } /** @@ -132,7 +133,7 @@ export default class PhoneAuthListener { */ _emitToSuccessCb(snapshot) { if (this._resolve) this._resolve(snapshot); - this._auth.emit(this._publicEvents.success, snapshot); + SharedEventEmitter.emit(this._publicEvents.success, snapshot); } /** @@ -143,12 +144,12 @@ export default class PhoneAuthListener { setTimeout(() => { // move to next event loop - not sure if needed // internal listeners Object.values(this._internalEvents).forEach((event) => { - this._auth.removeAllListeners(event); + SharedEventEmitter.removeAllListeners(event); }); // user observer listeners Object.values(this._publicEvents).forEach((publicEvent) => { - this._auth.removeAllListeners(publicEvent); + SharedEventEmitter.removeAllListeners(publicEvent); }); }, 0); } @@ -279,11 +280,11 @@ export default class PhoneAuthListener { this._addUserObserver(observer); if (isFunction(errorCb)) { - this._auth.once(this._publicEvents.error, errorCb); + SharedEventEmitter.once(this._publicEvents.error, errorCb); } if (isFunction(successCb)) { - this._auth.once(this._publicEvents.success, successCb); + SharedEventEmitter.once(this._publicEvents.success, successCb); } return this; diff --git a/lib/modules/auth/index.js b/lib/modules/auth/index.js index b8d073db..18e27066 100644 --- a/lib/modules/auth/index.js +++ b/lib/modules/auth/index.js @@ -4,6 +4,8 @@ */ import User from './User'; import ModuleBase from '../../utils/ModuleBase'; +import { getAppEventName, SharedEventEmitter } from '../../utils/events'; +import { getLogger } from '../../utils/log'; import INTERNALS from '../../utils/internals'; import ConfirmationResult from './ConfirmationResult'; @@ -37,24 +39,24 @@ export default class Auth extends ModuleBase { this._user = null; this._authResult = null; - this.addListener( + SharedEventEmitter.addListener( // sub to internal native event - this fans out to // public event name: onAuthStateChanged - super._getAppEventName('auth_state_changed'), + getAppEventName(this, 'auth_state_changed'), this._onInternalAuthStateChanged.bind(this), ); - this.addListener( + SharedEventEmitter.addListener( // sub to internal native event - this fans out to // public events based on event.type - super._getAppEventName('phone_auth_state_changed'), + getAppEventName(this, 'phone_auth_state_changed'), this._onInternalPhoneAuthStateChanged.bind(this), ); - this.addListener( + SharedEventEmitter.addListener( // sub to internal native event - this fans out to // public event name: onIdTokenChanged - super._getAppEventName('auth_id_token_changed'), + getAppEventName(this, 'auth_id_token_changed'), this._onInternalIdTokenChanged.bind(this), ); @@ -69,13 +71,13 @@ export default class Auth extends ModuleBase { */ _onInternalPhoneAuthStateChanged(event: Object) { const eventKey = `phone:auth:${event.requestKey}:${event.type}`; - this.emit(eventKey, event.state); + SharedEventEmitter.emit(eventKey, event.state); } _setAuthState(auth: AuthResult) { this._authResult = auth; this._user = auth && auth.user ? new User(this, auth.user) : null; - this.emit(this._getAppEventName('onUserChanged'), this._user); + SharedEventEmitter.emit(getAppEventName(this, 'onUserChanged'), this._user); } /** @@ -85,7 +87,7 @@ export default class Auth extends ModuleBase { */ _onInternalAuthStateChanged(auth: AuthResult) { this._setAuthState(auth); - this.emit(this._getAppEventName('onAuthStateChanged'), this._user); + SharedEventEmitter.emit(getAppEventName(this, 'onAuthStateChanged'), this._user); } /** @@ -96,7 +98,7 @@ export default class Auth extends ModuleBase { */ _onInternalIdTokenChanged(auth: AuthResult) { this._setAuthState(auth); - this.emit(this._getAppEventName('onIdTokenChanged'), this._user); + SharedEventEmitter.emit(getAppEventName(this, 'onIdTokenChanged'), this._user); } /** @@ -129,8 +131,8 @@ export default class Auth extends ModuleBase { * @param listener */ onAuthStateChanged(listener: Function) { - this.log.info('Creating onAuthStateChanged listener'); - this.on(this._getAppEventName('onAuthStateChanged'), listener); + getLogger(this).info('Creating onAuthStateChanged listener'); + SharedEventEmitter.addListener(getAppEventName(this, 'onAuthStateChanged'), listener); if (this._authResult) listener(this._user || null); return this._offAuthStateChanged.bind(this, listener); } @@ -140,8 +142,8 @@ export default class Auth extends ModuleBase { * @param listener */ _offAuthStateChanged(listener: Function) { - this.log.info('Removing onAuthStateChanged listener'); - this.removeListener(this._getAppEventName('onAuthStateChanged'), listener); + getLogger(this).info('Removing onAuthStateChanged listener'); + SharedEventEmitter.removeListener(getAppEventName(this, 'onAuthStateChanged'), listener); } /** @@ -149,8 +151,8 @@ export default class Auth extends ModuleBase { * @param listener */ onIdTokenChanged(listener: Function) { - this.log.info('Creating onIdTokenChanged listener'); - this.on(this._getAppEventName('onIdTokenChanged'), listener); + getLogger(this).info('Creating onIdTokenChanged listener'); + SharedEventEmitter.addListener(getAppEventName(this, 'onIdTokenChanged'), listener); if (this._authResult) listener(this._user || null); return this._offIdTokenChanged.bind(this, listener); } @@ -160,8 +162,8 @@ export default class Auth extends ModuleBase { * @param listener */ _offIdTokenChanged(listener: Function) { - this.log.info('Removing onIdTokenChanged listener'); - this.removeListener(this._getAppEventName('onIdTokenChanged'), listener); + getLogger(this).info('Removing onIdTokenChanged listener'); + SharedEventEmitter.removeListener(getAppEventName(this, 'onIdTokenChanged'), listener); } /** @@ -169,8 +171,8 @@ export default class Auth extends ModuleBase { * @param listener */ onUserChanged(listener: Function) { - this.log.info('Creating onUserChanged listener'); - this.on(this._getAppEventName('onUserChanged'), listener); + getLogger(this).info('Creating onUserChanged listener'); + SharedEventEmitter.addListener(getAppEventName(this, 'onUserChanged'), listener); if (this._authResult) listener(this._user || null); return this._offUserChanged.bind(this, listener); } @@ -180,8 +182,8 @@ export default class Auth extends ModuleBase { * @param listener */ _offUserChanged(listener: Function) { - this.log.info('Removing onUserChanged listener'); - this.removeListener(this._getAppEventName('onUserChanged'), listener); + getLogger(this).info('Removing onUserChanged listener'); + SharedEventEmitter.removeListener(getAppEventName(this, 'onUserChanged'), listener); } /** diff --git a/lib/modules/config/index.js b/lib/modules/config/index.js index 999c838a..990d8e9a 100644 --- a/lib/modules/config/index.js +++ b/lib/modules/config/index.js @@ -2,6 +2,7 @@ * @flow * Remote Config representation wrapper */ +import { getLogger } from '../../utils/log'; import ModuleBase from './../../utils/ModuleBase'; import type FirebaseApp from '../core/firebase-app'; @@ -51,7 +52,7 @@ export default class RemoteConfig extends ModuleBase { */ enableDeveloperMode() { if (!this._developerModeEnabled) { - this.log.debug('Enabled developer mode'); + getLogger(this).debug('Enabled developer mode'); this._native.enableDeveloperMode(); this._developerModeEnabled = true; } @@ -64,10 +65,10 @@ export default class RemoteConfig extends ModuleBase { */ fetch(expiration?: number) { if (expiration !== undefined) { - this.log.debug(`Fetching remote config data with expiration ${expiration.toString()}`); + getLogger(this).debug(`Fetching remote config data with expiration ${expiration.toString()}`); return this._native.fetchWithExpirationDuration(expiration); } - this.log.debug('Fetching remote config data'); + getLogger(this).debug('Fetching remote config data'); return this._native.fetch(); } @@ -78,7 +79,7 @@ export default class RemoteConfig extends ModuleBase { * rejects if no Fetched Config was found, or the Fetched Config was already activated. */ activateFetched() { - this.log.debug('Activating remote config'); + getLogger(this).debug('Activating remote config'); return this._native.activateFetched(); } diff --git a/lib/modules/core/firebase-app.js b/lib/modules/core/firebase-app.js index 686a0bed..2711d4f1 100644 --- a/lib/modules/core/firebase-app.js +++ b/lib/modules/core/firebase-app.js @@ -3,41 +3,27 @@ */ import { NativeModules } from 'react-native'; +import APPS from '../../utils/apps'; +import { SharedEventEmitter } from '../../utils/events'; import INTERNALS from '../../utils/internals'; -import { isObject, isAndroid } from '../../utils'; +import { isObject } from '../../utils'; -import AdMob, { statics as AdMobStatics } from '../admob'; -import Auth, { statics as AuthStatics } from '../auth'; -import Analytics, { statics as AnalyticsStatics } from '../analytics'; -import Config, { statics as ConfigStatics } from '../config'; -import Crash, { statics as CrashStatics } from '../crash'; -import Crashlytics, { statics as CrashlyticsStatics } from '../fabric/crashlytics'; -import Database, { statics as DatabaseStatics } from '../database'; -import Firestore, { statics as FirestoreStatics } from '../firestore'; -import Links, { statics as LinksStatics } from '../links'; -import Messaging, { statics as MessagingStatics } from '../messaging'; -import Performance, { statics as PerformanceStatics } from '../perf'; -import Storage, { statics as StorageStatics } from '../storage'; -import Utils, { statics as UtilsStatics } from '../utils'; +import AdMob from '../admob'; +import Auth from '../auth'; +import Analytics from '../analytics'; +import Config from '../config'; +import Crash from '../crash'; +import Crashlytics from '../fabric/crashlytics'; +import Database from '../database'; +import Firestore from '../firestore'; +import Links from '../links'; +import Messaging from '../messaging'; +import Performance from '../perf'; +import Storage from '../storage'; +import Utils from '../utils'; import type { - AdMobModule, - AnalyticsModule, - AuthModule, - ConfigModule, - CrashModule, - DatabaseModule, - FabricModule, - FirebaseModule, - FirebaseModuleAndStatics, FirebaseOptions, - FirebaseStatics, - FirestoreModule, - LinksModule, - MessagingModule, - PerformanceModule, - StorageModule, - UtilsModule, } from '../../types'; const FirebaseCoreModule = NativeModules.RNFirebase; @@ -45,70 +31,57 @@ const FirebaseCoreModule = NativeModules.RNFirebase; export default class FirebaseApp { _extendedProps: { [string] : boolean }; - _initialized: boolean; + _initialized: boolean = false; _name: string; - _namespaces: { [string]: FirebaseModule }; - _nativeInitialized: boolean; + _nativeInitialized: boolean = false; _options: FirebaseOptions; - admob: AdMobModule; - analytics: AnalyticsModule; - auth: AuthModule; - config: ConfigModule; - crash: CrashModule; - database: DatabaseModule; - fabric: FabricModule; - firestore: FirestoreModule; - links: LinksModule; - messaging: MessagingModule; - perf: PerformanceModule; - storage: StorageModule; - utils: UtilsModule; + admob: () => AdMob; + analytics: () => Analytics; + auth: () => Auth; + config: () => Config; + crash: () => Crash; + database: () => Database; + fabric: { + crashlytics: () => Crashlytics, + }; + firestore: () => Firestore; + links: () => Links; + messaging: () => Messaging; + perf: () => Performance; + storage: () => Storage; + utils: () => Utils; - constructor(name: string, options: FirebaseOptions) { + constructor(name: string, options: FirebaseOptions, fromNative: boolean = false) { this._name = name; - this._namespaces = {}; this._options = Object.assign({}, options); - // native ios/android to confirm initialized - this._initialized = false; - this._nativeInitialized = false; - - // modules - this.admob = this._staticsOrModuleInstance(AdMobStatics, AdMob); - this.analytics = this._staticsOrModuleInstance(AnalyticsStatics, Analytics); - this.auth = this._staticsOrModuleInstance(AuthStatics, Auth); - this.config = this._staticsOrModuleInstance(ConfigStatics, Config); - this.crash = this._staticsOrModuleInstance(CrashStatics, Crash); - this.database = this._staticsOrModuleInstance(DatabaseStatics, Database); - this.fabric = { - crashlytics: this._staticsOrModuleInstance(CrashlyticsStatics, Crashlytics), - }; - this.firestore = this._staticsOrModuleInstance(FirestoreStatics, Firestore); - this.links = this._staticsOrModuleInstance(LinksStatics, Links); - this.messaging = this._staticsOrModuleInstance(MessagingStatics, Messaging); - this.perf = this._staticsOrModuleInstance(PerformanceStatics, Performance); - this.storage = this._staticsOrModuleInstance(StorageStatics, Storage); - this.utils = this._staticsOrModuleInstance(UtilsStatics, Utils); - this._extendedProps = {}; - } - - /** - * - * @param native - * @private - */ - _initializeApp(native: boolean = false) { - if (native) { - // for apps already initialized natively that - // we have info from RN constants + if (fromNative) { this._initialized = true; this._nativeInitialized = true; - } else { + } else if (options.databaseURL && options.apiKey) { FirebaseCoreModule.initializeApp(this._name, this._options, (error, result) => { this._initialized = true; - INTERNALS.SharedEventEmitter.emit(`AppReady:${this._name}`, { error, result }); + SharedEventEmitter.emit(`AppReady:${this._name}`, { error, result }); }); } + + // modules + this.admob = APPS.appModule(this, 'admob', AdMob); + this.analytics = APPS.appModule(this, 'analytics', Analytics); + this.auth = APPS.appModule(this, 'auth', Auth); + this.config = APPS.appModule(this, 'config', Config); + this.crash = APPS.appModule(this, 'crash', Crash); + this.database = APPS.appModule(this, 'database', Database); + this.fabric = { + crashlytics: APPS.appModule(this, 'crashlytics', Crashlytics), + }; + this.firestore = APPS.appModule(this, 'firestore', Firestore); + this.links = APPS.appModule(this, 'links', Links); + this.messaging = APPS.appModule(this, 'messaging', Messaging); + this.perf = APPS.appModule(this, 'perf', Performance); + this.storage = APPS.appModule(this, 'storage', Storage); + this.utils = APPS.appModule(this, 'utils', Utils); + this._extendedProps = {}; } /** @@ -183,38 +156,10 @@ export default class FirebaseApp { if (this._initialized) return Promise.resolve(this); return new Promise((resolve, reject) => { - INTERNALS.SharedEventEmitter.once(`AppReady:${this._name}`, ({ error }) => { + SharedEventEmitter.once(`AppReady:${this._name}`, ({ error }) => { if (error) return reject(new Error(error)); // error is a string as it's from native return resolve(this); // return app }); }); } - - /** - * - * @param statics - * @param InstanceClass - * @return {function()} - * @private - */ - _staticsOrModuleInstance(statics: S, InstanceClass: Class): FirebaseModuleAndStatics { - const getInstance = (): M => { - const _name = `_${InstanceClass._NAMESPACE}`; - - if (isAndroid && InstanceClass._NAMESPACE !== Utils._NAMESPACE && !INTERNALS.FLAGS.checkedPlayServices) { - INTERNALS.FLAGS.checkedPlayServices = true; - this.utils().checkPlayServicesAvailability(); - } - - if (!this._namespaces[_name]) { - this._namespaces[_name] = new InstanceClass(this, this._options); - } - - return this._namespaces[_name]; - }; - - return Object.assign(getInstance, statics, { - nativeModuleExists: !!NativeModules[InstanceClass._NATIVE_MODULE], - }); - } } diff --git a/lib/modules/core/firebase.js b/lib/modules/core/firebase.js index e9fe087f..4dc60e88 100644 --- a/lib/modules/core/firebase.js +++ b/lib/modules/core/firebase.js @@ -2,11 +2,11 @@ * @providesModule Firebase * @flow */ -import { NativeModules, NativeEventEmitter } from 'react-native'; +import { NativeModules } from 'react-native'; +import APPS from '../../utils/apps'; import INTERNALS from '../../utils/internals'; import FirebaseApp from './firebase-app'; -import { isObject, isString } from '../../utils'; // module imports import AdMob, { statics as AdMobStatics } from '../admob'; @@ -31,10 +31,7 @@ import type { CrashModule, DatabaseModule, FabricModule, - FirebaseModule, - FirebaseModuleAndStatics, FirebaseOptions, - FirebaseStatics, FirestoreModule, LinksModule, MessagingModule, @@ -46,8 +43,6 @@ import type { const FirebaseCoreModule = NativeModules.RNFirebase; class FirebaseCore { - _nativeEmitters: { [string]: NativeEventEmitter }; - _nativeSubscriptions: { [string]: boolean }; admob: AdMobModule; analytics: AnalyticsModule; auth: AuthModule; @@ -63,45 +58,27 @@ class FirebaseCore { utils: UtilsModule; constructor() { - this._nativeEmitters = {}; - this._nativeSubscriptions = {}; - if (!FirebaseCoreModule) { throw (new Error(INTERNALS.STRINGS.ERROR_MISSING_CORE)); } - - this._initializeNativeApps(); + APPS.initializeNativeApps(); // modules - this.admob = this._appNamespaceOrStatics(AdMobStatics, AdMob); - this.analytics = this._appNamespaceOrStatics(AnalyticsStatics, Analytics); - this.auth = this._appNamespaceOrStatics(AuthStatics, Auth); - this.config = this._appNamespaceOrStatics(ConfigStatics, Config); - this.crash = this._appNamespaceOrStatics(CrashStatics, Crash); - this.database = this._appNamespaceOrStatics(DatabaseStatics, Database); + this.admob = APPS.moduleAndStatics('admob', AdMobStatics, AdMob); + this.analytics = APPS.moduleAndStatics('analytics', AnalyticsStatics, Analytics); + this.auth = APPS.moduleAndStatics('auth', AuthStatics, Auth); + this.config = APPS.moduleAndStatics('config', ConfigStatics, Config); + this.crash = APPS.moduleAndStatics('crash', CrashStatics, Crash); + this.database = APPS.moduleAndStatics('database', DatabaseStatics, Database); this.fabric = { - crashlytics: this._appNamespaceOrStatics(CrashlyticsStatics, Crashlytics), + crashlytics: APPS.moduleAndStatics('crashlytics', CrashlyticsStatics, Crashlytics), }; - this.firestore = this._appNamespaceOrStatics(FirestoreStatics, Firestore); - this.links = this._appNamespaceOrStatics(LinksStatics, Links); - this.messaging = this._appNamespaceOrStatics(MessagingStatics, Messaging); - this.perf = this._appNamespaceOrStatics(PerformanceStatics, Performance); - this.storage = this._appNamespaceOrStatics(StorageStatics, Storage); - this.utils = this._appNamespaceOrStatics(UtilsStatics, Utils); - } - - /** - * Bootstraps all native app instances that were discovered on boot - * @private - */ - _initializeNativeApps() { - for (let i = 0, len = FirebaseCoreModule.apps.length; i < len; i++) { - const app = FirebaseCoreModule.apps[i]; - const options = Object.assign({}, app); - delete options.name; - INTERNALS.APPS[app.name] = new FirebaseApp(app.name, options); - INTERNALS.APPS[app.name]._initializeApp(true); - } + this.firestore = APPS.moduleAndStatics('firestore', FirestoreStatics, Firestore); + this.links = APPS.moduleAndStatics('links', LinksStatics, Links); + this.messaging = APPS.moduleAndStatics('messaging', MessagingStatics, Messaging); + this.perf = APPS.moduleAndStatics('perf', PerformanceStatics, Performance); + this.storage = APPS.moduleAndStatics('storage', StorageStatics, Storage); + this.utils = APPS.moduleAndStatics('utils', UtilsStatics, Utils); } /** @@ -112,57 +89,7 @@ class FirebaseCore { * @return {*} */ initializeApp(options: FirebaseOptions, name: string): FirebaseApp { - if (name && !isString(name)) { - throw new Error(INTERNALS.STRINGS.ERROR_INIT_STRING_NAME); - } - - const _name = (name || INTERNALS.STRINGS.DEFAULT_APP_NAME).toUpperCase(); - - // return an existing app if found - // todo in v4 remove deprecation and throw an error - if (INTERNALS.APPS[_name]) { - console.warn(INTERNALS.STRINGS.WARN_INITIALIZE_DEPRECATION); - return INTERNALS.APPS[_name]; - } - - // only validate if app doesn't already exist - // to allow apps already initialized natively - // to still go through init without erroring (backwards compatibility) - if (!isObject(options)) { - throw new Error(INTERNALS.STRINGS.ERROR_INIT_OBJECT); - } - - if (!options.apiKey) { - throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('apiKey')); - } - - if (!options.appId) { - throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('appId')); - } - - if (!options.databaseURL) { - throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('databaseURL')); - } - - if (!options.messagingSenderId) { - throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('messagingSenderId')); - } - - if (!options.projectId) { - throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('projectId')); - } - - if (!options.storageBucket) { - throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('storageBucket')); - } - - INTERNALS.APPS[_name] = new FirebaseApp(_name, options); - // only initialize if certain props are available - if (options.databaseURL && options.apiKey) { - INTERNALS.APPS[_name]._initializeApp(); - } - - return INTERNALS.APPS[_name]; + return APPS.initializeApp(options, name); } /** @@ -175,10 +102,7 @@ class FirebaseCore { * @return {*} */ app(name?: string): FirebaseApp { - const _name = name ? name.toUpperCase() : INTERNALS.STRINGS.DEFAULT_APP_NAME; - const app = INTERNALS.APPS[_name]; - if (!app) throw new Error(INTERNALS.STRINGS.ERROR_APP_NOT_INIT(_name)); - return app; + return APPS.app(name); } /** @@ -186,83 +110,7 @@ class FirebaseCore { * @return {Array} */ get apps(): Array { - return Object.values(INTERNALS.APPS); - } - - /* - * INTERNALS - */ - - /** - * Subscribe to a native event for js side distribution by appName - * React Native events are hard set at compile - cant do dynamic event names - * so we use a single event send it to js and js then internally can prefix it - * and distribute dynamically. - * - * @param eventName - * @param nativeEmitter - * @private - */ - _subscribeForDistribution(eventName: string, nativeEmitter: NativeEventEmitter) { - if (!this._nativeSubscriptions[eventName]) { - nativeEmitter.addListener(eventName, (event) => { - if (event.appName) { - // native event has an appName property - auto prefix and internally emit - INTERNALS.SharedEventEmitter.emit(`${event.appName}-${eventName}`, event); - } else { - // standard event - no need to prefix - INTERNALS.SharedEventEmitter.emit(eventName, event); - } - }); - - this._nativeSubscriptions[eventName] = true; - } - } - - /** - * - * @param statics - * @param InstanceClass - * @return {function(FirebaseApp=)} - * @private - */ - _appNamespaceOrStatics(statics: S, InstanceClass: Class): FirebaseModuleAndStatics { - const namespace = InstanceClass._NAMESPACE; - - const getNamespace = (app?: FirebaseApp) => { - let _app = app; - - // throw an error if it's not a valid app instance - if (_app && !(_app instanceof FirebaseApp)) throw new Error(INTERNALS.STRINGS.ERROR_NOT_APP(namespace)); - - // default to the 'DEFAULT' app if no arg provided - will throw an error - // if default app not initialized - else if (!_app) _app = this.app(INTERNALS.STRINGS.DEFAULT_APP_NAME); - const firebaseApp = INTERNALS.APPS[_app._name]; - if (namespace === 'crashlytics') { - return firebaseApp.fabric[namespace](_app); - } - return firebaseApp[namespace](_app); - }; - - return Object.assign(getNamespace, statics, { - nativeModuleExists: !!NativeModules[InstanceClass._NATIVE_MODULE], - }); - } - - /** - * - * @param name - * @param nativeModule - * @return {*} - * @private - */ - _getOrSetNativeEmitter(name: string, nativeModule: Object): NativeEventEmitter { - if (this._nativeEmitters[name]) { - return this._nativeEmitters[name]; - } - - return this._nativeEmitters[name] = new NativeEventEmitter(nativeModule); + return APPS.apps(); } } diff --git a/lib/modules/database/reference.js b/lib/modules/database/reference.js index ee0f6283..43d61b9f 100644 --- a/lib/modules/database/reference.js +++ b/lib/modules/database/reference.js @@ -5,6 +5,7 @@ import Query from './query.js'; import Snapshot from './snapshot'; import Disconnect from './disconnect'; +import { getLogger } from '../../utils/log'; import ReferenceBase from '../../utils/ReferenceBase'; import { @@ -19,6 +20,7 @@ import { import INTERNALS from '../../utils/internals'; +import type Database from './'; import type { DatabaseModifier, FirebaseError } from '../../types'; import type SyncTree from '../../utils/SyncTree'; @@ -73,18 +75,18 @@ type DatabaseListener = { * @extends ReferenceBase */ export default class Reference extends ReferenceBase { - _database: Object; + _database: Database; _promise: ?Promise<*>; _query: Query; _refListeners: { [listenerId: number]: DatabaseListener }; - constructor(database: Object, path: string, existingModifiers?: Array) { + constructor(database: Database, path: string, existingModifiers?: Array) { super(path, database); this._promise = null; this._refListeners = {}; this._database = database; this._query = new Query(this, path, existingModifiers); - this.log.debug('Created new Reference', this._getRefKey()); + getLogger(database).debug('Created new Reference', this._getRefKey()); } /** @@ -549,13 +551,6 @@ export default class Reference extends ReferenceBase { return `$${this._database._appName}$/${this.path}$${this._query.queryIdentifier()}`; } - /** - * Return instance of db logger - */ - get log() { - return this._database.log; - } - /** * Set the promise this 'thenable' reference relates to * @param promise diff --git a/lib/modules/database/transaction.js b/lib/modules/database/transaction.js index d84a1d26..79d7bcf3 100644 --- a/lib/modules/database/transaction.js +++ b/lib/modules/database/transaction.js @@ -2,6 +2,8 @@ * @flow * Database Transaction representation wrapper */ +import { getAppEventName, SharedEventEmitter } from '../../utils/events'; +import { getLogger } from '../../utils/log'; import type Database from './'; let transactionId = 0; @@ -18,8 +20,8 @@ export default class TransactionHandler { this._transactions = {}; this._database = database; - this._transactionListener = this._database.addListener( - this._database._getAppEventName('database_transaction_event'), + this._transactionListener = SharedEventEmitter.addListener( + getAppEventName(this._database, 'database_transaction_event'), this._handleTransactionEvent.bind(this), ); } @@ -75,7 +77,7 @@ export default class TransactionHandler { case 'complete': return this._handleComplete(event); default: - this.log.warn(`Unknown transaction event type: '${event.type}'`, event); + getLogger(this._database).warn(`Unknown transaction event type: '${event.type}'`, event); return undefined; } } diff --git a/lib/modules/firestore/DocumentReference.js b/lib/modules/firestore/DocumentReference.js index 97d7c4ae..ae42c758 100644 --- a/lib/modules/firestore/DocumentReference.js +++ b/lib/modules/firestore/DocumentReference.js @@ -5,6 +5,7 @@ import CollectionReference from './CollectionReference'; import DocumentSnapshot from './DocumentSnapshot'; import { buildNativeMap } from './utils/serialize'; +import { getAppEventName, SharedEventEmitter } from '../../utils/events'; import { firestoreAutoId, isFunction, isObject, isString } from '../../utils'; import type Firestore from './'; @@ -136,15 +137,15 @@ export default class DocumentReference { }; // Listen to snapshot events - this._firestore.on( - this._firestore._getAppEventName(`onDocumentSnapshot:${listenerId}`), + SharedEventEmitter.addListener( + getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`), listener, ); // Listen for snapshot error events if (observer.error) { - this._firestore.on( - this._firestore._getAppEventName(`onDocumentSnapshotError:${listenerId}`), + SharedEventEmitter.addListener( + getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`), observer.error, ); } @@ -197,8 +198,8 @@ export default class DocumentReference { */ _offDocumentSnapshot(listenerId: string, listener: Function) { this._firestore.log.info('Removing onDocumentSnapshot listener'); - this._firestore.removeListener(this._firestore._getAppEventName(`onDocumentSnapshot:${listenerId}`), listener); - this._firestore.removeListener(this._firestore._getAppEventName(`onDocumentSnapshotError:${listenerId}`), listener); + SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`), listener); + SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`), listener); this._firestore._native .documentOffSnapshot(this.path, listenerId); } diff --git a/lib/modules/firestore/Query.js b/lib/modules/firestore/Query.js index af11cae4..99846818 100644 --- a/lib/modules/firestore/Query.js +++ b/lib/modules/firestore/Query.js @@ -5,6 +5,7 @@ import DocumentSnapshot from './DocumentSnapshot'; import QuerySnapshot from './QuerySnapshot'; import { buildNativeArray, buildTypeMap } from './utils/serialize'; +import { getAppEventName, SharedEventEmitter } from '../../utils/events'; import { firestoreAutoId, isFunction, isObject } from '../../utils'; import type Firestore from './'; @@ -206,15 +207,15 @@ export default class Query { }; // Listen to snapshot events - this._firestore.on( - this._firestore._getAppEventName(`onQuerySnapshot:${listenerId}`), + SharedEventEmitter.addListener( + getAppEventName(this._firestore, `onQuerySnapshot:${listenerId}`), listener, ); // Listen for snapshot error events if (observer.error) { - this._firestore.on( - this._firestore._getAppEventName(`onQuerySnapshotError:${listenerId}`), + SharedEventEmitter.addListener( + getAppEventName(this._firestore, `onQuerySnapshotError:${listenerId}`), observer.error, ); } @@ -335,8 +336,8 @@ export default class Query { */ _offCollectionSnapshot(listenerId: string, listener: Function) { this._firestore.log.info('Removing onQuerySnapshot listener'); - this._firestore.removeListener(this._firestore._getAppEventName(`onQuerySnapshot:${listenerId}`), listener); - this._firestore.removeListener(this._firestore._getAppEventName(`onQuerySnapshotError:${listenerId}`), listener); + SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onQuerySnapshot:${listenerId}`), listener); + SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onQuerySnapshotError:${listenerId}`), listener); this._firestore._native .collectionOffSnapshot( this._referencePath.relativeName, diff --git a/lib/modules/firestore/index.js b/lib/modules/firestore/index.js index ac624ae4..78c94e3d 100644 --- a/lib/modules/firestore/index.js +++ b/lib/modules/firestore/index.js @@ -4,7 +4,8 @@ */ import { NativeModules } from 'react-native'; -import ModuleBase from './../../utils/ModuleBase'; +import { getAppEventName, SharedEventEmitter } from '../../utils/events'; +import ModuleBase from '../../utils/ModuleBase'; import CollectionReference from './CollectionReference'; import DocumentReference from './DocumentReference'; import FieldValue from './FieldValue'; @@ -33,7 +34,10 @@ type DocumentSyncEvent = { path: string, } -class FirestoreInternalModule extends ModuleBase { +/** + * @class Firestore + */ +export default class Firestore extends ModuleBase { static _NAMESPACE = 'firestore'; static _NATIVE_MODULE = 'RNFirebaseFirestore'; @@ -43,56 +47,21 @@ class FirestoreInternalModule extends ModuleBase { super(firebaseApp, options, true); this._referencePath = new Path([]); - super.addListener( + SharedEventEmitter.addListener( // sub to internal native event - this fans out to // public event name: onCollectionSnapshot - super._getAppEventName('firestore_collection_sync_event'), + getAppEventName(this, 'firestore_collection_sync_event'), this._onCollectionSyncEvent.bind(this), ); - super.addListener( + SharedEventEmitter.addListener( // sub to internal native event - this fans out to // public event name: onDocumentSnapshot - super._getAppEventName('firestore_document_sync_event'), + getAppEventName(this, 'firestore_document_sync_event'), this._onDocumentSyncEvent.bind(this), ); } - /** - * Internal collection sync listener - * @param event - * @private - */ - _onCollectionSyncEvent(event: CollectionSyncEvent) { - if (event.error) { - this.emit(super._getAppEventName(`onQuerySnapshotError:${event.listenerId}`), event.error); - } else { - this.emit(super._getAppEventName(`onQuerySnapshot:${event.listenerId}`), event.querySnapshot); - } - } - - /** - * Internal document sync listener - * @param event - * @private - */ - _onDocumentSyncEvent(event: DocumentSyncEvent) { - if (event.error) { - this.emit(super._getAppEventName(`onDocumentSnapshotError:${event.listenerId}`), event.error); - } else { - this.emit(super._getAppEventName(`onDocumentSnapshot:${event.listenerId}`), event.documentSnapshot); - } - } -} - -/** - * @class Firestore - */ -export default class Firestore extends FirestoreInternalModule { - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options); - } - batch(): WriteBatch { return new WriteBatch(this); } @@ -140,6 +109,32 @@ export default class Firestore extends FirestoreInternalModule { settings(): void { throw new Error('firebase.firestore().settings() coming soon'); } + + /** + * Internal collection sync listener + * @param event + * @private + */ + _onCollectionSyncEvent(event: CollectionSyncEvent) { + if (event.error) { + SharedEventEmitter.emit(getAppEventName(this, `onQuerySnapshotError:${event.listenerId}`), event.error); + } else { + SharedEventEmitter.emit(getAppEventName(this, `onQuerySnapshot:${event.listenerId}`), event.querySnapshot); + } + } + + /** + * Internal document sync listener + * @param event + * @private + */ + _onDocumentSyncEvent(event: DocumentSyncEvent) { + if (event.error) { + SharedEventEmitter.emit(getAppEventName(this, `onDocumentSnapshotError:${event.listenerId}`), event.error); + } else { + SharedEventEmitter.emit(getAppEventName(this, `onDocumentSnapshot:${event.listenerId}`), event.documentSnapshot); + } + } } export const statics = { diff --git a/lib/modules/links/index.js b/lib/modules/links/index.js index 68b332bb..c4c26e6f 100644 --- a/lib/modules/links/index.js +++ b/lib/modules/links/index.js @@ -2,7 +2,8 @@ * @flow * Dynamic Links representation wrapper */ -import ModuleBase from './../../utils/ModuleBase'; +import { SharedEventEmitter } from '../../utils/events'; +import ModuleBase from '../../utils/ModuleBase'; import { areObjectKeysContainedInOther, isObject, isString } from './../../utils'; import type FirebaseApp from '../core/firebase-app'; @@ -87,7 +88,7 @@ export default class Links extends ModuleBase { * @returns {Function} */ onLink(listener: Function): () => any { - const rnListener = this._eventEmitter.addListener(EVENT_TYPE.Link, listener); + const rnListener = SharedEventEmitter.addListener(EVENT_TYPE.Link, listener); return () => rnListener.remove(); } diff --git a/lib/modules/messaging/index.js b/lib/modules/messaging/index.js index 595ab402..4a631137 100644 --- a/lib/modules/messaging/index.js +++ b/lib/modules/messaging/index.js @@ -3,7 +3,8 @@ * Messaging representation wrapper */ import { Platform, NativeModules } from 'react-native'; -import ModuleBase from './../../utils/ModuleBase'; +import { SharedEventEmitter } from '../../utils/events'; +import ModuleBase from '../../utils/ModuleBase'; import RemoteMessage from './RemoteMessage'; import type FirebaseApp from '../core/firebase-app'; @@ -213,7 +214,7 @@ export default class Messaging extends ModuleBase { * @returns {*} */ onMessage(listener: (Object) => any): () => any { - const rnListener = this._eventEmitter.addListener( + const rnListener = SharedEventEmitter.addListener( EVENT_TYPE.Notification, async (event) => { const data = { @@ -236,7 +237,7 @@ export default class Messaging extends ModuleBase { * @returns {*} */ onTokenRefresh(listener: (string) => any): () => any { - const rnListener = this._eventEmitter.addListener(EVENT_TYPE.RefreshToken, listener); + const rnListener = SharedEventEmitter.addListener(EVENT_TYPE.RefreshToken, listener); return () => rnListener.remove(); } diff --git a/lib/modules/storage/index.js b/lib/modules/storage/index.js index fdf5f520..a8e12c87 100644 --- a/lib/modules/storage/index.js +++ b/lib/modules/storage/index.js @@ -5,6 +5,8 @@ import { NativeModules } from 'react-native'; import StorageRef from './reference'; +import { getAppEventName, SharedEventEmitter } from '../../utils/events'; +import { getLogger } from '../../utils/log'; import ModuleBase from './../../utils/ModuleBase'; import type FirebaseApp from '../core/firebase-app'; @@ -23,13 +25,13 @@ export default class Storage extends ModuleBase { constructor(firebaseApp: FirebaseApp, options: Object = {}) { super(firebaseApp, options, true); - this.addListener( - this._getAppEventName('storage_event'), + SharedEventEmitter.addListener( + getAppEventName(this, 'storage_event'), this._handleStorageEvent.bind(this), ); - this.addListener( - this._getAppEventName('storage_error'), + SharedEventEmitter.addListener( + getAppEventName(this, 'storage_error'), this._handleStorageEvent.bind(this), ); } @@ -86,31 +88,31 @@ export default class Storage extends ModuleBase { * INTERNALS */ _getSubEventName(path: string, eventName: string) { - return this._getAppEventName(`${path}-${eventName}`); + return getAppEventName(this, `${path}-${eventName}`); } _handleStorageEvent(event: Object) { const { path, eventName } = event; const body = event.body || {}; - this.log.debug('_handleStorageEvent: ', path, eventName, body); - this.emit(this._getSubEventName(path, eventName), body); + getLogger(this).debug('_handleStorageEvent: ', path, eventName, body); + SharedEventEmitter.emit(this._getSubEventName(path, eventName), body); } _handleStorageError(err: Object) { const { path, eventName } = err; const body = err.body || {}; - this.log.debug('_handleStorageError ->', err); - this.emit(this._getSubEventName(path, eventName), body); + getLogger(this).debug('_handleStorageError ->', err); + SharedEventEmitter.emit(this._getSubEventName(path, eventName), body); } _addListener(path: string, eventName: string, cb: (evt: Object) => Object): void { - this.on(this._getSubEventName(path, eventName), cb); + SharedEventEmitter.addListener(this._getSubEventName(path, eventName), cb); } _removeListener(path: string, eventName: string, origCB: (evt: Object) => Object): void { - this.removeListener(this._getSubEventName(path, eventName), origCB); + SharedEventEmitter.removeListener(this._getSubEventName(path, eventName), origCB); } } diff --git a/lib/modules/utils/index.js b/lib/modules/utils/index.js index c7325462..e72f9beb 100644 --- a/lib/modules/utils/index.js +++ b/lib/modules/utils/index.js @@ -63,10 +63,6 @@ export default class RNFirebaseUtils extends ModuleBase { return FirebaseCoreModule.makePlayServicesAvailable(); } - get sharedEventEmitter(): Object { - return INTERNALS.SharedEventEmitter; - } - /** * Set the global logging level for all logs. * diff --git a/lib/utils/ModuleBase.js b/lib/utils/ModuleBase.js index 0f89825a..1b432583 100644 --- a/lib/utils/ModuleBase.js +++ b/lib/utils/ModuleBase.js @@ -1,45 +1,12 @@ /** * @flow */ -import { NativeModules } from 'react-native'; - -import Log from './log'; -import INTERNALS from './internals'; -import FirebaseCore from '../modules/core/firebase'; -import { nativeWithApp } from '../utils'; +import { initialiseNativeModuleEventEmitter } from './events'; +import { getNativeModule, initialiseNativeModule } from './native'; import type FirebaseApp from '../modules/core/firebase-app'; import type { FirebaseModuleName } from '../types'; -const logs = {}; - -// Firebase Native SDKs that support multiple app instances -const MULTI_APP_MODULES = [ - 'auth', - 'database', - 'firestore', - 'storage', -]; - -const NATIVE_MODULE_EVENTS = { - Storage: [ - 'storage_event', - 'storage_error', - ], - Auth: [ - 'auth_state_changed', - 'phone_auth_state_changed', - ], - Database: [ - 'database_transaction_event', - // 'database_server_offset', // TODO - ], - Firestore: [ - 'firestore_collection_sync_event', - 'firestore_document_sync_event', - ], -}; - const DEFAULTS = { Database: { persistence: false, @@ -53,7 +20,6 @@ export default class ModuleBase { _appName: string; _namespace: string; _firebaseApp: FirebaseApp; - _eventEmitter: Object; static _NAMESPACE: FirebaseModuleName; static _NATIVE_MODULE: string; @@ -71,53 +37,15 @@ export default class ModuleBase { this._options = Object.assign({}, DEFAULTS[this._module] || {}, options); // check if native module exists as all native - // modules are now optionally part of build - const nativeModule = NativeModules[this.constructor._NATIVE_MODULE]; - - if (!nativeModule && !this.constructor._NATIVE_DISABLED) { - throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(this.constructor._NAMESPACE, this.constructor._NATIVE_MODULE)); - } - - // used by the modules that extend ModuleBase - // to access their native module counterpart - if (!MULTI_APP_MODULES.includes(this._module.toLowerCase())) { - this._native = nativeModule; - } else { - this._native = nativeWithApp(this._appName, nativeModule); - } + initialiseNativeModule(this); + // TODO: Get rid of + this._native = getNativeModule(this); if (withEventEmitter) { - this._setupEventEmitter(nativeModule, this._module); + initialiseNativeModuleEventEmitter(this); } } - /** - * - * @param nativeModule - * @param moduleName - * @private - */ - _setupEventEmitter(nativeModule: Object, moduleName: string) { - this._eventEmitter = FirebaseCore._getOrSetNativeEmitter(`${this._appName}-${this._module}`, nativeModule); - const events = NATIVE_MODULE_EVENTS[moduleName]; - - if (events && events.length) { - for (let i = 0, len = events.length; i < len; i++) { - FirebaseCore._subscribeForDistribution(events[i], this._eventEmitter); - } - } - } - - /** - * - * @param eventName - * @return {string} - * @private - */ - _getAppEventName(eventName: string) { - return `${this._appName}-${eventName}`; - } - /** * Returns the FirebaseApp instance for current module * @return {*} @@ -125,50 +53,4 @@ export default class ModuleBase { get app(): FirebaseApp { return this._firebaseApp; } - - get log(): Log { - if (logs[this._namespace]) return logs[this._namespace]; - return logs[this._namespace] = Log.createLogger(`🔥 ${this._namespace.toUpperCase()}`); - } - - /* - * Proxy functions to shared event emitter instance - * https://github.com/facebook/react-native/blob/master/Libraries/EventEmitter/EventEmitter.js - */ - get sharedEventEmitter(): Object { - return INTERNALS.SharedEventEmitter; - } - - get addListener(): Function { - return INTERNALS.SharedEventEmitter.addListener.bind(INTERNALS.SharedEventEmitter); - } - - get once(): Function { - return INTERNALS.SharedEventEmitter.once.bind(INTERNALS.SharedEventEmitter); - } - - get on(): Function { - return INTERNALS.SharedEventEmitter.addListener.bind(INTERNALS.SharedEventEmitter); - } - - get emit(): Function { - return INTERNALS.SharedEventEmitter.emit.bind(INTERNALS.SharedEventEmitter); - } - - get listeners(): Function { - return INTERNALS.SharedEventEmitter.listeners.bind(INTERNALS.SharedEventEmitter); - } - - hasListeners(eventType: string): Boolean { - const subscriptions = INTERNALS.SharedEventEmitter._subscriber.getSubscriptionsForType(eventType); - return subscriptions && subscriptions.length; - } - - get removeListener(): Function { - return INTERNALS.SharedEventEmitter.removeListener.bind(INTERNALS.SharedEventEmitter); - } - - get removeAllListeners(): Function { - return INTERNALS.SharedEventEmitter.removeAllListeners.bind(INTERNALS.SharedEventEmitter); - } } diff --git a/lib/utils/ReferenceBase.js b/lib/utils/ReferenceBase.js index 4d0daf4e..631d23a1 100644 --- a/lib/utils/ReferenceBase.js +++ b/lib/utils/ReferenceBase.js @@ -1,8 +1,6 @@ /** * @flow */ -import Log from './log'; - import type Database from '../modules/database'; import type Storage from '../modules/storage'; @@ -24,8 +22,4 @@ export default class ReferenceBase { get key(): string | null { return this.path === '/' ? null : this.path.substring(this.path.lastIndexOf('/') + 1); } - - get log(): Log { - return this._module.log; - } } diff --git a/lib/utils/SyncTree.js b/lib/utils/SyncTree.js index 6cd4acb1..a1849bb3 100644 --- a/lib/utils/SyncTree.js +++ b/lib/utils/SyncTree.js @@ -3,7 +3,7 @@ */ import { NativeEventEmitter } from 'react-native'; -import INTERNALS from './internals'; +import { SharedEventEmitter } from './events'; import DatabaseSnapshot from '../modules/database/snapshot'; import DatabaseReference from '../modules/database/reference'; import { isString, nativeToJSError } from '../utils'; @@ -77,7 +77,7 @@ export default class SyncTree { const { snapshot, previousChildName } = event.data; // forward on to users .on(successCallback <-- listener - return INTERNALS.SharedEventEmitter.emit( + return SharedEventEmitter.emit( eventRegistrationKey, new DatabaseSnapshot(registration.ref, snapshot), previousChildName, @@ -104,7 +104,7 @@ export default class SyncTree { const error = nativeToJSError(code, message, { ref: registration.ref }); // forward on to users .on(successCallback, cancellationCallback <-- listener - INTERNALS.SharedEventEmitter.emit(registrationCancellationKey, error); + SharedEventEmitter.emit(registrationCancellationKey, error); // remove the paired event registration - if we received a cancellation // event then it's guaranteed that they'll be no further value events @@ -131,14 +131,14 @@ export default class SyncTree { removeListenersForRegistrations(registrations: string | string[]) { if (isString(registrations)) { this.removeRegistration(registrations); - INTERNALS.SharedEventEmitter.removeAllListeners(registrations); + SharedEventEmitter.removeAllListeners(registrations); return 1; } if (!Array.isArray(registrations)) return 0; for (let i = 0, len = registrations.length; i < len; i++) { this.removeRegistration(registrations[i]); - INTERNALS.SharedEventEmitter.removeAllListeners(registrations[i]); + SharedEventEmitter.removeAllListeners(registrations[i]); } return registrations.length; @@ -157,7 +157,7 @@ export default class SyncTree { for (let i = 0, len = registrations.length; i < len; i++) { const registration = registrations[i]; - const subscriptions = INTERNALS.SharedEventEmitter._subscriber.getSubscriptionsForType(registration); + const subscriptions = SharedEventEmitter._subscriber.getSubscriptionsForType(registration); if (subscriptions) { for (let j = 0, l = subscriptions.length; j < l; j++) { const subscription = subscriptions[j]; @@ -251,12 +251,12 @@ export default class SyncTree { this._reverseLookup[eventRegistrationKey] = Object.assign({ listener }, parameters); if (once) { - INTERNALS.SharedEventEmitter.once( + SharedEventEmitter.once( eventRegistrationKey, this._onOnceRemoveRegistration(eventRegistrationKey, listener), ); } else { - INTERNALS.SharedEventEmitter.addListener(eventRegistrationKey, listener); + SharedEventEmitter.addListener(eventRegistrationKey, listener); } return eventRegistrationKey; diff --git a/lib/utils/apps.js b/lib/utils/apps.js new file mode 100644 index 00000000..2d39e0f6 --- /dev/null +++ b/lib/utils/apps.js @@ -0,0 +1,167 @@ +/** + * @flow + */ +import { NativeModules } from 'react-native'; +import FirebaseApp from '../modules/core/firebase-app'; +import INTERNALS from './internals'; +import { isAndroid, isObject, isString } from './'; + +import type { + FirebaseModule, + FirebaseModuleAndStatics, + FirebaseModuleName, + FirebaseOptions, + FirebaseStatics, +} from '../types'; + +const FirebaseCoreModule = NativeModules.RNFirebase; + +const APPS: { [string]: FirebaseApp } = {}; +const APP_MODULES: { [FirebaseApp]: { [string]: FirebaseModule }} = {}; + +export default { + app(name?: string): FirebaseApp { + const _name = name ? name.toUpperCase() : INTERNALS.STRINGS.DEFAULT_APP_NAME; + const app = APPS[_name]; + if (!app) throw new Error(INTERNALS.STRINGS.ERROR_APP_NOT_INIT(_name)); + return app; + }, + + apps(): Array { + return Object.values(APPS); + }, + + /** + * + * @param statics + * @param InstanceClass + * @return {function()} + * @private + */ + appModule(firebaseApp: FirebaseApp, moduleName: FirebaseModuleName, InstanceClass: Class): () => FirebaseModule { + return (): M => { + if (!APP_MODULES[firebaseApp]) { + APP_MODULES[firebaseApp] = {}; + } + + if (isAndroid && moduleName !== 'utils' && !INTERNALS.FLAGS.checkedPlayServices) { + INTERNALS.FLAGS.checkedPlayServices = true; + this.utils().checkPlayServicesAvailability(); + } + + if (!APP_MODULES[firebaseApp][moduleName]) { + APP_MODULES[firebaseApp][moduleName] = new InstanceClass(firebaseApp, this._options); + } + + return APP_MODULES[firebaseApp][moduleName]; + }; + }, + + deleteApp(name: string): Promise { + const app = APPS[name]; + if (!app) return Promise.resolve(true); + + // https://firebase.google.com/docs/reference/js/firebase.app.App#delete + return app.delete().then(() => { + delete APPS[name]; + return true; + }); + }, + + /** + * Web SDK initializeApp + * + * @param options + * @param name + * @return {*} + */ + initializeApp(options: FirebaseOptions, name: string): FirebaseApp { + if (name && !isString(name)) { + throw new Error(INTERNALS.STRINGS.ERROR_INIT_STRING_NAME); + } + + const _name = (name || INTERNALS.STRINGS.DEFAULT_APP_NAME).toUpperCase(); + + // return an existing app if found + // todo in v4 remove deprecation and throw an error + if (APPS[_name]) { + console.warn(INTERNALS.STRINGS.WARN_INITIALIZE_DEPRECATION); + return APPS[_name]; + } + + // only validate if app doesn't already exist + // to allow apps already initialized natively + // to still go through init without erroring (backwards compatibility) + if (!isObject(options)) { + throw new Error(INTERNALS.STRINGS.ERROR_INIT_OBJECT); + } + + if (!options.apiKey) { + throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('apiKey')); + } + + if (!options.appId) { + throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('appId')); + } + + if (!options.databaseURL) { + throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('databaseURL')); + } + + if (!options.messagingSenderId) { + throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('messagingSenderId')); + } + + if (!options.projectId) { + throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('projectId')); + } + + if (!options.storageBucket) { + throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('storageBucket')); + } + + APPS[_name] = new FirebaseApp(_name, options); + + return APPS[_name]; + }, + + /** + * Bootstraps all native app instances that were discovered on boot + */ + initializeNativeApps() { + for (let i = 0, len = FirebaseCoreModule.apps.length; i < len; i++) { + const app = FirebaseCoreModule.apps[i]; + const options = Object.assign({}, app); + delete options.name; + APPS[app.name] = new FirebaseApp(app.name, options, true); + } + }, + + /** + * + * @param statics + * @param InstanceClass + * @return {function(FirebaseApp=)} + */ + moduleAndStatics(moduleName: FirebaseModuleName, statics: S, InstanceClass: Class): FirebaseModuleAndStatics { + const getModule = (app?: FirebaseApp): FirebaseModule => { + let firebaseApp = app; + + // throw an error if it's not a valid app instance + if (firebaseApp && !(firebaseApp instanceof FirebaseApp)) throw new Error(INTERNALS.STRINGS.ERROR_NOT_APP(moduleName)); + + // default to the 'DEFAULT' app if no arg provided - will throw an error + // if default app not initialized + else if (!firebaseApp) firebaseApp = this.app(INTERNALS.STRINGS.DEFAULT_APP_NAME); + if (moduleName === 'crashlytics') { + return firebaseApp.fabric[moduleName](); + } + const module = firebaseApp[moduleName]; + return module(); + }; + + return Object.assign(getModule, statics, { + nativeModuleExists: !!NativeModules[InstanceClass._NATIVE_MODULE], + }); + }, +}; diff --git a/lib/utils/events.js b/lib/utils/events.js new file mode 100644 index 00000000..07a0e1e3 --- /dev/null +++ b/lib/utils/events.js @@ -0,0 +1,81 @@ +/** + * @flow + */ +import { NativeEventEmitter } from 'react-native'; +import EventEmitter from './emitter/EventEmitter'; +import { getRawNativeModule } from './native'; + +import type ModuleBase from './ModuleBase'; + +const NATIVE_MODULE_EVENTS = { + Storage: [ + 'storage_event', + 'storage_error', + ], + Auth: [ + 'auth_state_changed', + 'phone_auth_state_changed', + ], + Database: [ + 'database_transaction_event', + // 'database_server_offset', // TODO + ], + Firestore: [ + 'firestore_collection_sync_event', + 'firestore_document_sync_event', + ], +}; +const NATIVE_EMITTERS: { [string]: NativeEventEmitter } = {}; +const NATIVE_SUBSCRIPTIONS: { [string]: boolean } = {}; + +export const SharedEventEmitter = new EventEmitter(); + +export const getAppEventName = (module: ModuleBase, eventName: string): string => { + return `${module._firebaseApp._name}-${eventName}`; +}; + +const getNativeEmitter = (module: ModuleBase): NativeEventEmitter => { + const name = `${module._appName}-${module._module}`; + const nativeModule = getRawNativeModule(module); + if (!NATIVE_EMITTERS[name]) { + NATIVE_EMITTERS[name] = new NativeEventEmitter(nativeModule); + } + return NATIVE_EMITTERS[name]; +}; + +/** + * Subscribe to a native event for js side distribution by appName + * React Native events are hard set at compile - cant do dynamic event names + * so we use a single event send it to js and js then internally can prefix it + * and distribute dynamically. + * + * @param module + * @param eventName + * @private + */ +const subscribeToNativeModuleEvents = (module: ModuleBase, eventName: string): void => { + if (!NATIVE_SUBSCRIPTIONS[eventName]) { + const nativeEmitter = getNativeEmitter(module); + nativeEmitter.addListener(eventName, (event) => { + if (event.appName) { + // native event has an appName property - auto prefix and internally emit + SharedEventEmitter.emit(`${event.appName}-${eventName}`, event); + } else { + // standard event - no need to prefix + SharedEventEmitter.emit(eventName, event); + } + }); + + NATIVE_SUBSCRIPTIONS[eventName] = true; + } +}; + +export const initialiseNativeModuleEventEmitter = (module: ModuleBase): void => { + const events = NATIVE_MODULE_EVENTS[module._module]; + + if (events && events.length) { + for (let i = 0, len = events.length; i < len; i++) { + subscribeToNativeModuleEvents(module, events[i]); + } + } +}; diff --git a/lib/utils/index.js b/lib/utils/index.js index 6f619e4e..cea0b5d2 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -340,25 +340,6 @@ export function nativeToJSError(code: string, message: string, additionalProps?: return error; } -/** - * Prepends appName arg to all native method calls - * @param appName - * @param NativeModule - */ -export function nativeWithApp(appName: string, NativeModule: Object) { - const native = {}; - const methods = Object.keys(NativeModule); - - for (let i = 0, len = methods.length; i < len; i++) { - const method = methods[i]; - native[method] = (...args) => { - return NativeModule[method](...[appName, ...args]); - }; - } - - return native; -} - /** * * @param object diff --git a/lib/utils/internals.js b/lib/utils/internals.js index efab8da1..53bbc73c 100644 --- a/lib/utils/internals.js +++ b/lib/utils/internals.js @@ -3,12 +3,9 @@ */ import { Platform, NativeModules } from 'react-native'; -import EventEmitter from './emitter/EventEmitter'; import ModuleBase from './ModuleBase'; import SyncTree from './SyncTree'; -import type FirebaseApp from '../modules/core/firebase-app'; - const DEFAULT_APP_NAME = Platform.OS === 'ios' ? '__FIRAPP_DEFAULT' : '[DEFAULT]'; const NAMESPACE_PODS = { @@ -55,8 +52,6 @@ const PLAY_SERVICES_CODES = { }, }; -const APPS: { [string]: FirebaseApp } = {}; - export default { // default options OPTIONS: { @@ -69,9 +64,6 @@ export default { checkedPlayServices: false, }, - // track all initialized firebase apps - APPS, - STRINGS: { WARN_INITIALIZE_DEPRECATION: 'Deprecation: Calling \'initializeApp()\' for apps that are already initialised natively ' + 'is unnecessary, use \'firebase.app()\' instead to access the already initialized default app instance.', @@ -227,19 +219,5 @@ export default { DEFAULT_APP_NAME, }, - - SharedEventEmitter: new EventEmitter(), SyncTree: NativeModules.RNFirebaseDatabase ? new SyncTree(NativeModules.RNFirebaseDatabase) : null, - - // internal utils - deleteApp(name: String): Promise { - const app = this.APPS[name]; - if (!app) return Promise.resolve(true); - - // https://firebase.google.com/docs/reference/js/firebase.app.App#delete - return app.delete().then(() => { - delete this.APPS[name]; - return true; - }); - }, }; diff --git a/lib/utils/log.js b/lib/utils/log.js index b43dbe73..73f5f83d 100644 --- a/lib/utils/log.js +++ b/lib/utils/log.js @@ -1,5 +1,10 @@ +/* + * @flow + */ import { windowOrGlobal } from './'; +import type ModuleBase from './ModuleBase'; + ((base) => { window = base || window; if (!window.localStorage) window.localStorage = {}; @@ -7,6 +12,15 @@ import { windowOrGlobal } from './'; // clean up time +const NATIVE_LOGGERS: { [ModuleBase]: Object } = {}; + +export const getLogger = (module: ModuleBase) => { + if (!NATIVE_LOGGERS[module]) { + NATIVE_LOGGERS[module] = require('bows')(`🔥 ${module._namespace.toUpperCase()}`); + } + return NATIVE_LOGGERS[module]; +}; + export default class Log { static createLogger(namespace) { return require('bows')(namespace); diff --git a/lib/utils/native.js b/lib/utils/native.js new file mode 100644 index 00000000..a6ff5926 --- /dev/null +++ b/lib/utils/native.js @@ -0,0 +1,62 @@ +/* + * @flow + */ +import { NativeModules } from 'react-native'; +import INTERNALS from './internals'; + +import type ModuleBase from './ModuleBase'; + +// Firebase Native SDKs that support multiple app instances +const MULTI_APP_MODULES = [ + 'auth', + 'database', + 'firestore', + 'storage', +]; + +const NATIVE_MODULES: { [ModuleBase]: Object } = {}; +const RAW_NATIVE_MODULES: { [ModuleBase]: Object } = {}; + +/** + * Prepends appName arg to all native method calls + * @param appName + * @param NativeModule + */ +const nativeWithApp = (appName: string, NativeModule: Object): Object => { + const native = {}; + const methods = Object.keys(NativeModule); + + for (let i = 0, len = methods.length; i < len; i++) { + const method = methods[i]; + native[method] = (...args) => { + return NativeModule[method](...[appName, ...args]); + }; + } + + return native; +}; + +export const getNativeModule = (module: ModuleBase): Object => { + return NATIVE_MODULES[module]; +}; + +export const getRawNativeModule = (module: ModuleBase): Object => { + return RAW_NATIVE_MODULES[module]; +}; + +export const initialiseNativeModule = (module: ModuleBase): void => { + const nativeModule = NativeModules[module.constructor._NATIVE_MODULE]; + + if (!nativeModule && !module.constructor._NATIVE_DISABLED) { + throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(module.constructor._NAMESPACE, module.constructor._NATIVE_MODULE)); + } + + // used by the modules that extend ModuleBase + // to access their native module counterpart + RAW_NATIVE_MODULES[module] = nativeModule; + if (!MULTI_APP_MODULES.includes(module._module.toLowerCase())) { + NATIVE_MODULES[module] = nativeModule; + } else { + NATIVE_MODULES[module] = nativeWithApp(module._appName, nativeModule); + } +}; diff --git a/tests/ios/Podfile.lock b/tests/ios/Podfile.lock index 55bf24ba..a8f8ff96 100644 --- a/tests/ios/Podfile.lock +++ b/tests/ios/Podfile.lock @@ -153,7 +153,7 @@ PODS: - React/Core - React/fishhook - React/RCTBlob - - RNFirebase (3.1.1): + - RNFirebase (3.2.0): - React - yoga (0.49.1.React) @@ -215,7 +215,7 @@ SPEC CHECKSUMS: nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3 Protobuf: 03eef2ee0b674770735cf79d9c4d3659cf6908e8 React: cf892fb84b7d06bf5fea7f328e554c6dcabe85ee - RNFirebase: 976f3b35d112017c69da5ada20cf1f15fc2c327e + RNFirebase: 22b1917fec663706907bc901ed665ac4f8b9bfd6 yoga: 3abf02d6d9aeeb139b4c930eb1367feae690a35a PODFILE CHECKSUM: f17a538903249834df5049668d10174810db4c4c diff --git a/tests/src/firebase.js b/tests/src/firebase.js index f51fb163..4df18e2f 100644 --- a/tests/src/firebase.js +++ b/tests/src/firebase.js @@ -40,7 +40,7 @@ const ios = { const instances = { web: firebase.initializeApp(config), - native: RNfirebase.app(), + native: RNfirebase, another: RNfirebase.initializeApp(Platform.OS === 'ios' ? ios : android, 'anotherApp'), }; diff --git a/tests/src/tests/core/coreTests.js b/tests/src/tests/core/coreTests.js index d96e5d78..b7e971a4 100644 --- a/tests/src/tests/core/coreTests.js +++ b/tests/src/tests/core/coreTests.js @@ -53,8 +53,7 @@ function coreTests({ describe, it }) { it('it should provide an array of apps', () => { should.equal(!!RNFirebase.apps.length, true); - should.equal(RNFirebase.apps[0]._name, RNFirebase.utils.DEFAULT_APP_NAME); - should.equal(RNFirebase.apps[0].name, '[DEFAULT]'); + should.equal(RNFirebase.apps.includes(RNFirebase.app(RNFirebase.utils.DEFAULT_APP_NAME)), true); return Promise.resolve(); }); From 61d7c3b2ebf3e31c912b9b0ed4d8d8fa3fffbdb4 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 22 Dec 2017 15:57:33 +0000 Subject: [PATCH 46/56] [internals] Move native events to individual modules to make it easier to see the relationship --- lib/modules/admob/index.js | 7 ++++++- lib/modules/auth/index.js | 7 ++++++- lib/modules/database/index.js | 7 ++++++- lib/modules/firestore/index.js | 7 ++++++- lib/modules/links/index.js | 6 +++++- lib/modules/messaging/index.js | 7 ++++++- lib/modules/storage/index.js | 7 ++++++- lib/utils/ModuleBase.js | 6 ++---- lib/utils/events.js | 22 +--------------------- 9 files changed, 44 insertions(+), 32 deletions(-) diff --git a/lib/modules/admob/index.js b/lib/modules/admob/index.js index 070e1a3f..fc971d01 100644 --- a/lib/modules/admob/index.js +++ b/lib/modules/admob/index.js @@ -26,6 +26,11 @@ type NativeEvent = { type: string, } +const NATIVE_EVENTS = [ + 'interstitial_event', + 'rewarded_video_event', +]; + export default class AdMob extends ModuleBase { static _NAMESPACE = 'admob'; static _NATIVE_MODULE = 'RNFirebaseAdMob'; @@ -34,7 +39,7 @@ export default class AdMob extends ModuleBase { _initialized: boolean; constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, true); + super(firebaseApp, options, NATIVE_EVENTS); this._initialized = false; this._appId = null; diff --git a/lib/modules/auth/index.js b/lib/modules/auth/index.js index 18e27066..e9ac0296 100644 --- a/lib/modules/auth/index.js +++ b/lib/modules/auth/index.js @@ -27,6 +27,11 @@ type AuthResult = { user: Object|null } | null; +const NATIVE_EVENTS = [ + 'auth_state_changed', + 'phone_auth_state_changed', +]; + export default class Auth extends ModuleBase { static _NAMESPACE = 'auth'; static _NATIVE_MODULE = 'RNFirebaseAuth'; @@ -35,7 +40,7 @@ export default class Auth extends ModuleBase { _user: User | null; constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, true); + super(firebaseApp, options, NATIVE_EVENTS); this._user = null; this._authResult = null; diff --git a/lib/modules/database/index.js b/lib/modules/database/index.js index ddcae474..850f6152 100644 --- a/lib/modules/database/index.js +++ b/lib/modules/database/index.js @@ -10,6 +10,11 @@ import ModuleBase from './../../utils/ModuleBase'; import type FirebaseApp from '../core/firebase-app'; +const NATIVE_EVENTS = [ + 'database_transaction_event', + // 'database_server_offset', // TODO +]; + /** * @class Database */ @@ -22,7 +27,7 @@ export default class Database extends ModuleBase { _transactionHandler: TransactionHandler; constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, true); + super(firebaseApp, options, NATIVE_EVENTS); this._transactionHandler = new TransactionHandler(this); if (this._options.persistence) { diff --git a/lib/modules/firestore/index.js b/lib/modules/firestore/index.js index 78c94e3d..c3d3a0fb 100644 --- a/lib/modules/firestore/index.js +++ b/lib/modules/firestore/index.js @@ -34,6 +34,11 @@ type DocumentSyncEvent = { path: string, } +const NATIVE_EVENTS = [ + 'firestore_collection_sync_event', + 'firestore_document_sync_event', +]; + /** * @class Firestore */ @@ -44,7 +49,7 @@ export default class Firestore extends ModuleBase { _referencePath: Path; constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, true); + super(firebaseApp, options, NATIVE_EVENTS); this._referencePath = new Path([]); SharedEventEmitter.addListener( diff --git a/lib/modules/links/index.js b/lib/modules/links/index.js index c4c26e6f..fc36c1ae 100644 --- a/lib/modules/links/index.js +++ b/lib/modules/links/index.js @@ -12,6 +12,10 @@ const EVENT_TYPE = { Link: 'dynamic_link_received', }; +const NATIVE_EVENTS = [ + EVENT_TYPE.Link, +]; + function validateParameters(parameters: Object): void { const suportedParametersObject = { dynamicLinkDomain: 'string', @@ -67,7 +71,7 @@ export default class Links extends ModuleBase { static _NATIVE_MODULE = 'RNFirebaseLinks'; constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, true); + super(firebaseApp, options, NATIVE_EVENTS); } get EVENT_TYPE(): Object { diff --git a/lib/modules/messaging/index.js b/lib/modules/messaging/index.js index 4a631137..091b5b05 100644 --- a/lib/modules/messaging/index.js +++ b/lib/modules/messaging/index.js @@ -32,6 +32,11 @@ const WILL_PRESENT_RESULT = { None: 'UNNotificationPresentationOptionNone', }; +const NATIVE_EVENTS = [ + EVENT_TYPE.RefreshToken, + EVENT_TYPE.Notification, +]; + const FirebaseMessaging = NativeModules.RNFirebaseMessaging; /** @@ -83,7 +88,7 @@ export default class Messaging extends ModuleBase { static _NATIVE_MODULE = 'RNFirebaseMessaging'; constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, true); + super(firebaseApp, options, NATIVE_EVENTS); } get EVENT_TYPE(): Object { diff --git a/lib/modules/storage/index.js b/lib/modules/storage/index.js index a8e12c87..358f7594 100644 --- a/lib/modules/storage/index.js +++ b/lib/modules/storage/index.js @@ -13,6 +13,11 @@ import type FirebaseApp from '../core/firebase-app'; const FirebaseStorage = NativeModules.RNFirebaseStorage; +const NATIVE_EVENTS = [ + 'storage_event', + 'storage_error', +]; + export default class Storage extends ModuleBase { static _NAMESPACE = 'storage'; static _NATIVE_MODULE = 'RNFirebaseStorage'; @@ -23,7 +28,7 @@ export default class Storage extends ModuleBase { * @param options */ constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, true); + super(firebaseApp, options, NATIVE_EVENTS); SharedEventEmitter.addListener( getAppEventName(this, 'storage_event'), diff --git a/lib/utils/ModuleBase.js b/lib/utils/ModuleBase.js index 1b432583..cb0a974f 100644 --- a/lib/utils/ModuleBase.js +++ b/lib/utils/ModuleBase.js @@ -29,7 +29,7 @@ export default class ModuleBase { * @param options * @param withEventEmitter */ - constructor(firebaseApp: FirebaseApp, options: Object, withEventEmitter: boolean = false) { + constructor(firebaseApp: FirebaseApp, options: Object, events: string[] = []) { this._module = this.constructor._NATIVE_MODULE.replace('RNFirebase', ''); this._firebaseApp = firebaseApp; this._appName = firebaseApp._name; @@ -41,9 +41,7 @@ export default class ModuleBase { // TODO: Get rid of this._native = getNativeModule(this); - if (withEventEmitter) { - initialiseNativeModuleEventEmitter(this); - } + initialiseNativeModuleEventEmitter(this, events); } /** diff --git a/lib/utils/events.js b/lib/utils/events.js index 07a0e1e3..90be83c1 100644 --- a/lib/utils/events.js +++ b/lib/utils/events.js @@ -7,24 +7,6 @@ import { getRawNativeModule } from './native'; import type ModuleBase from './ModuleBase'; -const NATIVE_MODULE_EVENTS = { - Storage: [ - 'storage_event', - 'storage_error', - ], - Auth: [ - 'auth_state_changed', - 'phone_auth_state_changed', - ], - Database: [ - 'database_transaction_event', - // 'database_server_offset', // TODO - ], - Firestore: [ - 'firestore_collection_sync_event', - 'firestore_document_sync_event', - ], -}; const NATIVE_EMITTERS: { [string]: NativeEventEmitter } = {}; const NATIVE_SUBSCRIPTIONS: { [string]: boolean } = {}; @@ -70,9 +52,7 @@ const subscribeToNativeModuleEvents = (module: ModuleBase, eventName: string): v } }; -export const initialiseNativeModuleEventEmitter = (module: ModuleBase): void => { - const events = NATIVE_MODULE_EVENTS[module._module]; - +export const initialiseNativeModuleEventEmitter = (module: ModuleBase, events: string[]): void => { if (events && events.length) { for (let i = 0, len = events.length; i < len; i++) { subscribeToNativeModuleEvents(module, events[i]); From 1f293541456568fe44cb41626242f410e45adf5e Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 27 Dec 2017 15:29:38 +0000 Subject: [PATCH 47/56] [internals] Fix a couple of missing log references --- lib/modules/firestore/DocumentReference.js | 3 ++- lib/modules/firestore/Query.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/modules/firestore/DocumentReference.js b/lib/modules/firestore/DocumentReference.js index ae42c758..0befcbfd 100644 --- a/lib/modules/firestore/DocumentReference.js +++ b/lib/modules/firestore/DocumentReference.js @@ -6,6 +6,7 @@ import CollectionReference from './CollectionReference'; import DocumentSnapshot from './DocumentSnapshot'; import { buildNativeMap } from './utils/serialize'; import { getAppEventName, SharedEventEmitter } from '../../utils/events'; +import { getLogger } from '../../utils/log'; import { firestoreAutoId, isFunction, isObject, isString } from '../../utils'; import type Firestore from './'; @@ -197,7 +198,7 @@ export default class DocumentReference { * @param listener */ _offDocumentSnapshot(listenerId: string, listener: Function) { - this._firestore.log.info('Removing onDocumentSnapshot listener'); + getLogger(this._firestore).info('Removing onDocumentSnapshot listener'); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`), listener); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`), listener); this._firestore._native diff --git a/lib/modules/firestore/Query.js b/lib/modules/firestore/Query.js index 99846818..5f5b9129 100644 --- a/lib/modules/firestore/Query.js +++ b/lib/modules/firestore/Query.js @@ -6,6 +6,7 @@ import DocumentSnapshot from './DocumentSnapshot'; import QuerySnapshot from './QuerySnapshot'; import { buildNativeArray, buildTypeMap } from './utils/serialize'; import { getAppEventName, SharedEventEmitter } from '../../utils/events'; +import { getLogger } from '../../utils/log'; import { firestoreAutoId, isFunction, isObject } from '../../utils'; import type Firestore from './'; @@ -335,7 +336,7 @@ export default class Query { * @param listener */ _offCollectionSnapshot(listenerId: string, listener: Function) { - this._firestore.log.info('Removing onQuerySnapshot listener'); + getLogger(this._firestore).info('Removing onQuerySnapshot listener'); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onQuerySnapshot:${listenerId}`), listener); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onQuerySnapshotError:${listenerId}`), listener); this._firestore._native From 226c94c906859a787df4e73c6ab4392470f64f35 Mon Sep 17 00:00:00 2001 From: chrisbianca Date: Wed, 3 Jan 2018 09:09:02 +0000 Subject: [PATCH 48/56] Update ISSUE_TEMPLATE.md with links to Discord and SO --- .github/ISSUE_TEMPLATE.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index b49108a9..d4d824c0 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,14 +1,13 @@ +BEFORE YOU MAKE AN ISSUE - +The issue list of this repo is exclusively for bug reports. - ### Issue @@ -38,4 +37,4 @@ 6. Firebase Module: \ No newline at end of file +👉 https://opencollective.com/react-native-firebase/donate --> From 0fe2fec819ed644dc9e6514145871fe49722ff4a Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Wed, 3 Jan 2018 20:00:38 +0000 Subject: [PATCH 49/56] [internals] More tidy up and hiding of internal functions --- ios/RNFirebase/RNFirebase.m | 12 +- ios/RNFirebase/RNFirebaseUtil.h | 6 +- ios/RNFirebase/RNFirebaseUtil.m | 26 ++- ios/RNFirebase/auth/RNFirebaseAuth.m | 169 +++++++++--------- ios/RNFirebase/database/RNFirebaseDatabase.h | 2 +- ios/RNFirebase/database/RNFirebaseDatabase.m | 98 +++++----- .../database/RNFirebaseDatabaseReference.h | 4 +- .../database/RNFirebaseDatabaseReference.m | 6 +- .../firestore/RNFirebaseFirestore.h | 2 +- .../firestore/RNFirebaseFirestore.m | 50 +++--- .../RNFirebaseFirestoreCollectionReference.h | 4 +- .../RNFirebaseFirestoreCollectionReference.m | 14 +- .../RNFirebaseFirestoreDocumentReference.h | 4 +- .../RNFirebaseFirestoreDocumentReference.m | 14 +- ios/RNFirebase/storage/RNFirebaseStorage.m | 92 +++++----- lib/modules/admob/index.js | 12 +- lib/modules/analytics/index.js | 11 +- lib/modules/auth/index.js | 22 ++- lib/modules/config/index.js | 11 +- lib/modules/core/firebase-app.js | 61 +++---- lib/modules/core/firebase.js | 52 +++--- lib/modules/crash/index.js | 11 +- lib/modules/database/index.js | 19 +- lib/modules/database/reference.js | 37 ++-- lib/modules/fabric/crashlytics/index.js | 11 +- lib/modules/firestore/index.js | 20 ++- lib/modules/links/index.js | 12 +- lib/modules/messaging/index.js | 11 +- lib/modules/perf/index.js | 11 +- lib/modules/storage/index.js | 12 +- lib/modules/utils/index.js | 35 +--- lib/types/index.js | 13 +- lib/utils/ModuleBase.js | 43 ++--- lib/utils/SyncTree.js | 28 +-- lib/utils/apps.js | 32 ++-- lib/utils/events.js | 19 +- lib/utils/internals.js | 16 +- lib/utils/log.js | 7 +- lib/utils/native.js | 33 ++-- tests/src/tests/core/coreTests.js | 2 +- 40 files changed, 542 insertions(+), 502 deletions(-) diff --git a/ios/RNFirebase/RNFirebase.m b/ios/RNFirebase/RNFirebase.m index b9c99c9e..6f05d927 100644 --- a/ios/RNFirebase/RNFirebase.m +++ b/ios/RNFirebase/RNFirebase.m @@ -1,4 +1,5 @@ #import "RNFirebase.h" +#import "RNFirebaseUtil.h" #import @implementation RNFirebase @@ -21,14 +22,14 @@ RCT_EXPORT_MODULE(RNFirebase); * @return */ RCT_EXPORT_METHOD(initializeApp: - (NSString *) appName + (NSString *) appDisplayName options: (NSDictionary *) options callback: (RCTResponseSenderBlock) callback) { dispatch_sync(dispatch_get_main_queue(), ^{ - FIRApp *existingApp = [FIRApp appNamed:appName]; + FIRApp *existingApp = [RNFirebaseUtil getApp:appDisplayName]; if (!existingApp) { FIROptions *firOptions = [[FIROptions alloc] initWithGoogleAppID:[options valueForKey:@"appId"] GCMSenderID:[options valueForKey:@"messagingSenderId"]]; @@ -43,6 +44,7 @@ RCT_EXPORT_METHOD(initializeApp: firOptions.deepLinkURLScheme = [options valueForKey:@"deepLinkURLScheme"]; firOptions.bundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"]; + NSString *appName = [RNFirebaseUtil getAppName:appDisplayName]; [FIRApp configureWithName:appName options:firOptions]; } @@ -55,13 +57,13 @@ RCT_EXPORT_METHOD(initializeApp: * @return */ RCT_EXPORT_METHOD(deleteApp: - (NSString *) appName + (NSString *) appDisplayName resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *existingApp = [FIRApp appNamed:appName]; + FIRApp *existingApp = [RNFirebaseUtil getApp:appDisplayName]; if (!existingApp) { return resolve([NSNull null]); @@ -90,7 +92,7 @@ RCT_EXPORT_METHOD(deleteApp: NSMutableDictionary *appOptions = [NSMutableDictionary new]; FIRApp *firApp = firApps[key]; FIROptions *firOptions = [firApp options]; - appOptions[@"name"] = firApp.name; + appOptions[@"name"] = [RNFirebaseUtil getAppDisplayName:firApp.name]; appOptions[@"apiKey"] = firOptions.APIKey; appOptions[@"appId"] = firOptions.googleAppID; appOptions[@"databaseURL"] = firOptions.databaseURL; diff --git a/ios/RNFirebase/RNFirebaseUtil.h b/ios/RNFirebase/RNFirebaseUtil.h index ab0ef52d..8191c387 100644 --- a/ios/RNFirebase/RNFirebaseUtil.h +++ b/ios/RNFirebase/RNFirebaseUtil.h @@ -3,11 +3,15 @@ #import #import +#import @interface RNFirebaseUtil : NSObject ++ (FIRApp *)getApp:(NSString *)appDisplayName; ++ (NSString *)getAppName:(NSString *)appDisplayName; ++ (NSString *)getAppDisplayName:(NSString *)appName; + (void)sendJSEvent:(RCTEventEmitter *)emitter name:(NSString *)name body:(NSDictionary *)body; -+ (void)sendJSEventWithAppName:(RCTEventEmitter *)emitter appName:(NSString *)appName name:(NSString *)name body:(NSDictionary *)body; ++ (void)sendJSEventWithAppName:(RCTEventEmitter *)emitter app:(FIRApp *)app name:(NSString *)name body:(NSDictionary *)body; @end diff --git a/ios/RNFirebase/RNFirebaseUtil.m b/ios/RNFirebase/RNFirebaseUtil.m index 898e31cb..c97bb636 100644 --- a/ios/RNFirebase/RNFirebaseUtil.m +++ b/ios/RNFirebase/RNFirebaseUtil.m @@ -2,6 +2,28 @@ @implementation RNFirebaseUtil +static NSString *const DEFAULT_APP_DISPLAY_NAME = @"[DEFAULT]"; +static NSString *const DEFAULT_APP_NAME = @"__FIRAPP_DEFAULT"; + ++ (FIRApp *)getApp:(NSString *)appDisplayName { + NSString *appName = [RNFirebaseUtil getAppName:appDisplayName]; + return [FIRApp appNamed:appName]; +} + ++ (NSString *)getAppName:(NSString *)appDisplayName { + if ([appDisplayName isEqualToString:DEFAULT_APP_DISPLAY_NAME]) { + return DEFAULT_APP_NAME; + } + return appDisplayName; +} + ++ (NSString *)getAppDisplayName:(NSString *)appName { + if ([appName isEqualToString:DEFAULT_APP_NAME]) { + return DEFAULT_APP_DISPLAY_NAME; + } + return appName; +} + + (void)sendJSEvent:(RCTEventEmitter *)emitter name:(NSString *)name body:(NSDictionary *)body { @try { // TODO: Temporary fix for https://github.com/invertase/react-native-firebase/issues/233 @@ -14,10 +36,10 @@ } } -+ (void)sendJSEventWithAppName:(RCTEventEmitter *)emitter appName:(NSString *)appName name:(NSString *)name body:(NSDictionary *)body { ++ (void)sendJSEventWithAppName:(RCTEventEmitter *)emitter app:(FIRApp *)app name:(NSString *)name body:(NSDictionary *)body { // Add the appName to the body NSMutableDictionary *newBody = [body mutableCopy]; - newBody[@"appName"] = appName; + newBody[@"appName"] = [RNFirebaseUtil getAppDisplayName:app.name]; [RNFirebaseUtil sendJSEvent:emitter name:name body:newBody]; } diff --git a/ios/RNFirebase/auth/RNFirebaseAuth.m b/ios/RNFirebase/auth/RNFirebaseAuth.m index 191d6330..576e8c3b 100644 --- a/ios/RNFirebase/auth/RNFirebaseAuth.m +++ b/ios/RNFirebase/auth/RNFirebaseAuth.m @@ -23,19 +23,19 @@ RCT_EXPORT_MODULE(); */ RCT_EXPORT_METHOD(addAuthStateListener: - (NSString *) appName) { + (NSString *) appDisplayName) { + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; - if (![_authStateHandlers valueForKey:appName]) { - FIRApp *firApp = [FIRApp appNamed:appName]; + if (![_authStateHandlers valueForKey:firApp.name]) { FIRAuthStateDidChangeListenerHandle newListenerHandle = [[FIRAuth authWithApp:firApp] addAuthStateDidChangeListener:^(FIRAuth *_Nonnull auth, FIRUser *_Nullable user) { if (user != nil) { - [RNFirebaseUtil sendJSEventWithAppName:self appName:appName name:AUTH_CHANGED_EVENT body:@{@"authenticated": @(true), @"user": [self firebaseUserToDict:user]}]; + [RNFirebaseUtil sendJSEventWithAppName:self app:firApp name:AUTH_CHANGED_EVENT body:@{@"authenticated": @(true), @"user": [self firebaseUserToDict:user]}]; } else { - [RNFirebaseUtil sendJSEventWithAppName:self appName:appName name:AUTH_CHANGED_EVENT body:@{@"authenticated": @(false)}]; + [RNFirebaseUtil sendJSEventWithAppName:self app:firApp name:AUTH_CHANGED_EVENT body:@{@"authenticated": @(false)}]; } }]; - _authStateHandlers[appName] = [NSValue valueWithNonretainedObject:newListenerHandle]; + _authStateHandlers[firApp.name] = [NSValue valueWithNonretainedObject:newListenerHandle]; } } @@ -44,12 +44,12 @@ RCT_EXPORT_METHOD(addAuthStateListener: */ RCT_EXPORT_METHOD(removeAuthStateListener: - (NSString *) appName) { + (NSString *) appDisplayName) { + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; - if ([_authStateHandlers valueForKey:appName]) { - FIRApp *firApp = [FIRApp appNamed:appName]; - [[FIRAuth authWithApp:firApp] removeAuthStateDidChangeListener:[_authStateHandlers valueForKey:appName]]; - [_authStateHandlers removeObjectForKey:appName]; + if ([_authStateHandlers valueForKey:firApp.name]) { + [[FIRAuth authWithApp:firApp] removeAuthStateDidChangeListener:[_authStateHandlers valueForKey:firApp.name]]; + [_authStateHandlers removeObjectForKey:firApp.name]; } } @@ -58,19 +58,19 @@ RCT_EXPORT_METHOD(removeAuthStateListener: */ RCT_EXPORT_METHOD(addIdTokenListener: - (NSString *) appName) { + (NSString *) appDisplayName) { + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; - if (![_idTokenHandlers valueForKey:appName]) { - FIRApp *firApp = [FIRApp appNamed:appName]; + if (![_idTokenHandlers valueForKey:firApp.name]) { FIRIDTokenDidChangeListenerHandle newListenerHandle = [[FIRAuth authWithApp:firApp] addIDTokenDidChangeListener:^(FIRAuth * _Nonnull auth, FIRUser * _Nullable user) { if (user != nil) { - [RNFirebaseUtil sendJSEventWithAppName:self appName:appName name:AUTH_ID_TOKEN_CHANGED_EVENT body:@{@"authenticated": @(true), @"user": [self firebaseUserToDict:user]}]; + [RNFirebaseUtil sendJSEventWithAppName:self app:firApp name:AUTH_ID_TOKEN_CHANGED_EVENT body:@{@"authenticated": @(true), @"user": [self firebaseUserToDict:user]}]; } else { - [RNFirebaseUtil sendJSEventWithAppName:self appName:appName name:AUTH_ID_TOKEN_CHANGED_EVENT body:@{@"authenticated": @(false)}]; + [RNFirebaseUtil sendJSEventWithAppName:self app:firApp name:AUTH_ID_TOKEN_CHANGED_EVENT body:@{@"authenticated": @(false)}]; } }]; - _idTokenHandlers[appName] = [NSValue valueWithNonretainedObject:newListenerHandle]; + _idTokenHandlers[firApp.name] = [NSValue valueWithNonretainedObject:newListenerHandle]; } } @@ -79,11 +79,12 @@ RCT_EXPORT_METHOD(addIdTokenListener: */ RCT_EXPORT_METHOD(removeIdTokenListener: - (NSString *) appName) { - if ([_idTokenHandlers valueForKey:appName]) { - FIRApp *firApp = [FIRApp appNamed:appName]; - [[FIRAuth authWithApp:firApp] removeIDTokenDidChangeListener:[_idTokenHandlers valueForKey:appName]]; - [_idTokenHandlers removeObjectForKey:appName]; + (NSString *) appDisplayName) { + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; + + if ([_idTokenHandlers valueForKey:firApp.name]) { + [[FIRAuth authWithApp:firApp] removeIDTokenDidChangeListener:[_idTokenHandlers valueForKey:firApp.name]]; + [_idTokenHandlers removeObjectForKey:firApp.name]; } } @@ -97,12 +98,12 @@ RCT_EXPORT_METHOD(removeIdTokenListener: @return */ RCT_EXPORT_METHOD(signOut: - (NSString *) appName + (NSString *) appDisplayName resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; @@ -125,12 +126,12 @@ RCT_EXPORT_METHOD(signOut: @return */ RCT_EXPORT_METHOD(signInAnonymously: - (NSString *) appName + (NSString *) appDisplayName resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; [[FIRAuth authWithApp:firApp] signInAnonymouslyWithCompletion:^(FIRUser *user, NSError *error) { if (error) { @@ -152,7 +153,7 @@ RCT_EXPORT_METHOD(signInAnonymously: @return return */ RCT_EXPORT_METHOD(signInWithEmailAndPassword: - (NSString *) appName + (NSString *) appDisplayName email: (NSString *) email pass: @@ -161,7 +162,7 @@ RCT_EXPORT_METHOD(signInWithEmailAndPassword: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; [[FIRAuth authWithApp:firApp] signInWithEmail:email password:password completion:^(FIRUser *user, NSError *error) { if (error) { @@ -182,7 +183,7 @@ RCT_EXPORT_METHOD(signInWithEmailAndPassword: @return return */ RCT_EXPORT_METHOD(createUserWithEmailAndPassword: - (NSString *) appName + (NSString *) appDisplayName email: (NSString *) email pass: @@ -191,7 +192,7 @@ RCT_EXPORT_METHOD(createUserWithEmailAndPassword: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; [[FIRAuth authWithApp:firApp] createUserWithEmail:email password:password completion:^(FIRUser *user, NSError *error) { if (error) { @@ -210,12 +211,12 @@ RCT_EXPORT_METHOD(createUserWithEmailAndPassword: @return return */ RCT_EXPORT_METHOD(delete: - (NSString *) appName + (NSString *) appDisplayName resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; if (user) { @@ -239,12 +240,12 @@ RCT_EXPORT_METHOD(delete: @return return */ RCT_EXPORT_METHOD(reload: - (NSString *) appName + (NSString *) appDisplayName resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; @@ -262,11 +263,11 @@ RCT_EXPORT_METHOD(reload: @param RCTPromiseRejectBlock reject @return return */ -RCT_EXPORT_METHOD(sendEmailVerification:(NSString *) appName +RCT_EXPORT_METHOD(sendEmailVerification:(NSString *) appDisplayName actionCodeSettings:(NSDictionary *) actionCodeSettings resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; if (user) { @@ -298,14 +299,14 @@ RCT_EXPORT_METHOD(sendEmailVerification:(NSString *) appName @return return */ RCT_EXPORT_METHOD(updateEmail: - (NSString *) appName + (NSString *) appDisplayName email: (NSString *) email resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; if (user) { @@ -330,14 +331,14 @@ RCT_EXPORT_METHOD(updateEmail: @return return */ RCT_EXPORT_METHOD(updatePassword: - (NSString *) appName + (NSString *) appDisplayName password: (NSString *) password resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; @@ -364,14 +365,14 @@ RCT_EXPORT_METHOD(updatePassword: @return return */ RCT_EXPORT_METHOD(updateProfile: - (NSString *) appName + (NSString *) appDisplayName props: (NSDictionary *) props resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; @@ -412,14 +413,14 @@ RCT_EXPORT_METHOD(updateProfile: @return */ RCT_EXPORT_METHOD(getToken: - (NSString *) appName + (NSString *) appDisplayName forceRefresh: (BOOL) forceRefresh resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; @@ -447,7 +448,7 @@ RCT_EXPORT_METHOD(getToken: @return */ RCT_EXPORT_METHOD(signInWithCredential: - (NSString *) appName + (NSString *) appDisplayName provider: (NSString *) provider token: @@ -458,7 +459,7 @@ RCT_EXPORT_METHOD(signInWithCredential: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret]; @@ -485,7 +486,7 @@ RCT_EXPORT_METHOD(signInWithCredential: @return */ RCT_EXPORT_METHOD(confirmPasswordReset: - (NSString *) appName + (NSString *) appDisplayName code: (NSString *) code newPassword: @@ -494,8 +495,8 @@ RCT_EXPORT_METHOD(confirmPasswordReset: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; - + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; + [[FIRAuth authWithApp:firApp] confirmPasswordResetWithCode:code newPassword:newPassword completion:^(NSError *_Nullable error) { if (error) { [self promiseRejectAuthException:reject error:error]; @@ -515,15 +516,15 @@ RCT_EXPORT_METHOD(confirmPasswordReset: * @return */ RCT_EXPORT_METHOD(applyActionCode: - (NSString *) appName + (NSString *) appDisplayName code: (NSString *) code resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; - + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; + [[FIRAuth authWithApp:firApp] applyActionCode:code completion:^(NSError *_Nullable error) { if (error) { [self promiseRejectAuthException:reject error:error]; @@ -542,15 +543,15 @@ RCT_EXPORT_METHOD(applyActionCode: * @return */ RCT_EXPORT_METHOD(checkActionCode: - (NSString *) appName + (NSString *) appDisplayName code: (NSString *) code resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; - + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; + [[FIRAuth authWithApp:firApp] checkActionCode:code completion:^(FIRActionCodeInfo *_Nullable info, NSError *_Nullable error) { if (error) { [self promiseRejectAuthException:reject error:error]; @@ -586,12 +587,12 @@ RCT_EXPORT_METHOD(checkActionCode: @param RCTPromiseRejectBlock reject @return */ -RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appName +RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appDisplayName email:(NSString *) email actionCodeSettings:(NSDictionary *) actionCodeSettings resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; id handler = ^(NSError *_Nullable error) { if (error) { @@ -600,7 +601,7 @@ RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appName [self promiseNoUser:resolve rejecter:reject isError:NO]; } }; - + if (actionCodeSettings) { FIRActionCodeSettings *settings = [self buildActionCodeSettings:actionCodeSettings]; [[FIRAuth authWithApp:firApp] sendPasswordResetWithEmail:email actionCodeSettings:settings completion:handler]; @@ -617,12 +618,12 @@ RCT_EXPORT_METHOD(sendPasswordResetEmail:(NSString *) appName @return */ RCT_EXPORT_METHOD(getCurrentUser: - (NSString *) appName + (NSString *) appDisplayName resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; [self promiseWithUser:resolve rejecter:reject user:user]; @@ -637,14 +638,14 @@ RCT_EXPORT_METHOD(getCurrentUser: @return */ RCT_EXPORT_METHOD(signInWithCustomToken: - (NSString *) appName + (NSString *) appDisplayName customToken: (NSString *) customToken resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; [[FIRAuth authWithApp:firApp] signInWithCustomToken:customToken completion:^(FIRUser *user, NSError *error) { if (error) { @@ -663,11 +664,11 @@ RCT_EXPORT_METHOD(signInWithCustomToken: @param RCTPromiseRejectBlock reject @return */ -RCT_EXPORT_METHOD(signInWithPhoneNumber:(NSString *) appName +RCT_EXPORT_METHOD(signInWithPhoneNumber:(NSString *) appDisplayName phoneNumber:(NSString *) phoneNumber resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; [[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firApp]] verifyPhoneNumber:phoneNumber UIDelegate:nil completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { if (error) { @@ -684,17 +685,17 @@ RCT_EXPORT_METHOD(signInWithPhoneNumber:(NSString *) appName /** verifyPhoneNumber - + @param string phoneNumber @param RCTPromiseResolveBlock resolve @param RCTPromiseRejectBlock reject @return */ -RCT_EXPORT_METHOD(verifyPhoneNumber:(NSString *) appName +RCT_EXPORT_METHOD(verifyPhoneNumber:(NSString *) appDisplayName phoneNumber:(NSString *) phoneNumber requestKey:(NSString *) requestKey) { - FIRApp *firApp = [FIRApp appNamed:appName]; - + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; + [[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firApp]] verifyPhoneNumber:phoneNumber UIDelegate:nil completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { if (error) { NSDictionary * jsError = [self getJSError:(error)]; @@ -703,7 +704,7 @@ RCT_EXPORT_METHOD(verifyPhoneNumber:(NSString *) appName @"requestKey":requestKey, @"state": @{@"error": jsError}, }; - [RNFirebaseUtil sendJSEventWithAppName:self appName:appName name:PHONE_AUTH_STATE_CHANGED_EVENT body:body]; + [RNFirebaseUtil sendJSEventWithAppName:self app:firApp name:PHONE_AUTH_STATE_CHANGED_EVENT body:body]; } else { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject:verificationID forKey:@"authVerificationID"]; @@ -712,16 +713,16 @@ RCT_EXPORT_METHOD(verifyPhoneNumber:(NSString *) appName @"requestKey":requestKey, @"state": @{@"verificationId": verificationID}, }; - [RNFirebaseUtil sendJSEventWithAppName:self appName:appName name:PHONE_AUTH_STATE_CHANGED_EVENT body:body]; + [RNFirebaseUtil sendJSEventWithAppName:self app:firApp name:PHONE_AUTH_STATE_CHANGED_EVENT body:body]; } }]; } -RCT_EXPORT_METHOD(_confirmVerificationCode:(NSString *) appName +RCT_EXPORT_METHOD(_confirmVerificationCode:(NSString *) appDisplayName verificationCode:(NSString *) verificationCode resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *verificationId = [defaults stringForKey:@"authVerificationID"]; FIRAuthCredential *credential = [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationId verificationCode:verificationCode]; @@ -746,7 +747,7 @@ RCT_EXPORT_METHOD(_confirmVerificationCode:(NSString *) appName @return */ RCT_EXPORT_METHOD(link: - (NSString *) appName + (NSString *) appDisplayName provider: (NSString *) provider authToken: @@ -757,7 +758,7 @@ RCT_EXPORT_METHOD(link: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret]; @@ -791,14 +792,14 @@ RCT_EXPORT_METHOD(link: @return */ RCT_EXPORT_METHOD(unlink: - (NSString *) appName + (NSString *) appDisplayName providerId: (NSString *) providerId resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; FIRUser *user = [FIRAuth authWithApp:firApp].currentUser; if (user) { @@ -825,7 +826,7 @@ RCT_EXPORT_METHOD(unlink: @return */ RCT_EXPORT_METHOD(reauthenticate: - (NSString *) appName + (NSString *) appDisplayName provider: (NSString *) provider authToken: @@ -836,7 +837,7 @@ RCT_EXPORT_METHOD(reauthenticate: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; FIRAuthCredential *credential = [self getCredentialForProvider:provider token:authToken secret:authSecret]; @@ -869,14 +870,14 @@ RCT_EXPORT_METHOD(reauthenticate: @return */ RCT_EXPORT_METHOD(fetchProvidersForEmail: - (NSString *) appName + (NSString *) appDisplayName email: (NSString *) email resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) { - FIRApp *firApp = [FIRApp appNamed:appName]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; [[FIRAuth authWithApp:firApp] fetchProvidersForEmail:email completion:^(NSArray *_Nullable providers, NSError *_Nullable error) { if (error) { @@ -962,14 +963,14 @@ RCT_EXPORT_METHOD(fetchProvidersForEmail: /** Reject a promise with an auth exception - + @param error NSError */ - (NSDictionary *)getJSError:(NSError *)error { NSString *code = @"auth/unknown"; NSString *message = [error localizedDescription]; NSString *nativeErrorMessage = [error localizedDescription]; - + switch (error.code) { case FIRAuthErrorCodeInvalidCustomToken: code = @"auth/invalid-custom-token"; @@ -1043,7 +1044,7 @@ RCT_EXPORT_METHOD(fetchProvidersForEmail: code = @"auth/internal-error"; message = @"An internal error has occurred, please try again."; break; - + // unsure of the below codes so leaving them as the default error message case FIRAuthErrorCodeTooManyRequests: code = @"auth/too-many-requests"; @@ -1078,7 +1079,7 @@ RCT_EXPORT_METHOD(fetchProvidersForEmail: default: break; } - + return @{ @"code": code, @"message": message, diff --git a/ios/RNFirebase/database/RNFirebaseDatabase.h b/ios/RNFirebase/database/RNFirebaseDatabase.h index 6991c4cc..e88d5b5a 100644 --- a/ios/RNFirebase/database/RNFirebaseDatabase.h +++ b/ios/RNFirebase/database/RNFirebaseDatabase.h @@ -16,7 +16,7 @@ + (void)handlePromise:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject databaseError:(NSError *)databaseError; -+ (FIRDatabase *)getDatabaseForApp:(NSString *)appName; ++ (FIRDatabase *)getDatabaseForApp:(NSString *)appDisplayName; + (NSDictionary *)getJSError:(NSError *)nativeError; diff --git a/ios/RNFirebase/database/RNFirebaseDatabase.m b/ios/RNFirebase/database/RNFirebaseDatabase.m index 30d6dedd..69a235fb 100644 --- a/ios/RNFirebase/database/RNFirebaseDatabase.m +++ b/ios/RNFirebase/database/RNFirebaseDatabase.m @@ -22,38 +22,38 @@ RCT_EXPORT_MODULE(); return self; } -RCT_EXPORT_METHOD(goOnline:(NSString *) appName) { - [[RNFirebaseDatabase getDatabaseForApp:appName] goOnline]; +RCT_EXPORT_METHOD(goOnline:(NSString *) appDisplayName) { + [[RNFirebaseDatabase getDatabaseForApp:appDisplayName] goOnline]; } -RCT_EXPORT_METHOD(goOffline:(NSString *) appName) { - [[RNFirebaseDatabase getDatabaseForApp:appName] goOffline]; +RCT_EXPORT_METHOD(goOffline:(NSString *) appDisplayName) { + [[RNFirebaseDatabase getDatabaseForApp:appDisplayName] goOffline]; } -RCT_EXPORT_METHOD(setPersistence:(NSString *) appName +RCT_EXPORT_METHOD(setPersistence:(NSString *) appDisplayName state:(BOOL) state) { - [RNFirebaseDatabase getDatabaseForApp:appName].persistenceEnabled = state; + [RNFirebaseDatabase getDatabaseForApp:appDisplayName].persistenceEnabled = state; } -RCT_EXPORT_METHOD(setPersistenceCacheSizeBytes:(NSString *) appName +RCT_EXPORT_METHOD(setPersistenceCacheSizeBytes:(NSString *) appDisplayName size:(NSInteger *) size) { - [RNFirebaseDatabase getDatabaseForApp:appName].persistenceCacheSizeBytes = (NSUInteger)size; + [RNFirebaseDatabase getDatabaseForApp:appDisplayName].persistenceCacheSizeBytes = (NSUInteger)size; } RCT_EXPORT_METHOD(enableLogging:(BOOL) enabled) { [FIRDatabase setLoggingEnabled:enabled]; } -RCT_EXPORT_METHOD(keepSynced:(NSString *) appName +RCT_EXPORT_METHOD(keepSynced:(NSString *) appDisplayName key:(NSString *) key path:(NSString *) path modifiers:(NSArray *) modifiers state:(BOOL) state) { - FIRDatabaseQuery *query = [self getInternalReferenceForApp:appName key:key path:path modifiers:modifiers].query; + FIRDatabaseQuery *query = [self getInternalReferenceForApp:appDisplayName key:key path:path modifiers:modifiers].query; [query keepSynced:state]; } -RCT_EXPORT_METHOD(transactionTryCommit:(NSString *) appName +RCT_EXPORT_METHOD(transactionTryCommit:(NSString *) appDisplayName transactionId:(nonnull NSNumber *) transactionId updates:(NSDictionary *) updates) { __block NSMutableDictionary *transactionState; @@ -82,7 +82,7 @@ RCT_EXPORT_METHOD(transactionTryCommit:(NSString *) appName } -RCT_EXPORT_METHOD(transactionStart:(NSString *) appName +RCT_EXPORT_METHOD(transactionStart:(NSString *) appDisplayName path:(NSString *) path transactionId:(nonnull NSNumber *) transactionId applyLocally:(BOOL) applyLocally) { @@ -90,13 +90,13 @@ RCT_EXPORT_METHOD(transactionStart:(NSString *) appName NSMutableDictionary *transactionState = [NSMutableDictionary new]; dispatch_semaphore_t sema = dispatch_semaphore_create(0); transactionState[@"semaphore"] = sema; - FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; + FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref runTransactionBlock:^FIRTransactionResult * _Nonnull(FIRMutableData * _Nonnull currentData) { dispatch_barrier_async(_transactionQueue, ^{ [_transactions setValue:transactionState forKey:transactionId]; - NSDictionary *updateMap = [self createTransactionUpdateMap:appName transactionId:transactionId updatesData:currentData]; + NSDictionary *updateMap = [self createTransactionUpdateMap:appDisplayName transactionId:transactionId updatesData:currentData]; [RNFirebaseUtil sendJSEvent:self name:DATABASE_TRANSACTION_EVENT body:updateMap]; }); @@ -123,7 +123,7 @@ RCT_EXPORT_METHOD(transactionStart:(NSString *) appName } andCompletionBlock: ^(NSError *_Nullable databaseError, BOOL committed, FIRDataSnapshot *_Nullable snapshot) { - NSDictionary *resultMap = [self createTransactionResultMap:appName transactionId:transactionId error:databaseError committed:committed snapshot:snapshot]; + NSDictionary *resultMap = [self createTransactionResultMap:appDisplayName transactionId:transactionId error:databaseError committed:committed snapshot:snapshot]; [RNFirebaseUtil sendJSEvent:self name:DATABASE_TRANSACTION_EVENT body:resultMap]; } withLocalEvents: @@ -131,117 +131,117 @@ RCT_EXPORT_METHOD(transactionStart:(NSString *) appName }); } -RCT_EXPORT_METHOD(onDisconnectSet:(NSString *) appName +RCT_EXPORT_METHOD(onDisconnectSet:(NSString *) appDisplayName path:(NSString *) path props:(NSDictionary *) props resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; + FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref onDisconnectSetValue:props[@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(onDisconnectUpdate:(NSString *) appName +RCT_EXPORT_METHOD(onDisconnectUpdate:(NSString *) appDisplayName path:(NSString *) path props:(NSDictionary *) props resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; + FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref onDisconnectUpdateChildValues:props withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(onDisconnectRemove:(NSString *) appName +RCT_EXPORT_METHOD(onDisconnectRemove:(NSString *) appDisplayName path:(NSString *) path resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; + FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref onDisconnectRemoveValueWithCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(onDisconnectCancel:(NSString *) appName +RCT_EXPORT_METHOD(onDisconnectCancel:(NSString *) appDisplayName path:(NSString *) path resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; + FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref cancelDisconnectOperationsWithCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(set:(NSString *) appName +RCT_EXPORT_METHOD(set:(NSString *) appDisplayName path:(NSString *) path props:(NSDictionary *) props resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; + FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref setValue:[props valueForKey:@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(setPriority:(NSString *) appName +RCT_EXPORT_METHOD(setPriority:(NSString *) appDisplayName path:(NSString *) path priority:(NSDictionary *) priority resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; + FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref setPriority:[priority valueForKey:@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(setWithPriority:(NSString *) appName +RCT_EXPORT_METHOD(setWithPriority:(NSString *) appDisplayName path:(NSString *) path data:(NSDictionary *) data priority:(NSDictionary *) priority resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; + FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref setValue:[data valueForKey:@"value"] andPriority:[priority valueForKey:@"value"] withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(update:(NSString *) appName +RCT_EXPORT_METHOD(update:(NSString *) appDisplayName path:(NSString *) path props:(NSDictionary *) props resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; + FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref updateChildValues:props withCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(remove:(NSString *) appName +RCT_EXPORT_METHOD(remove:(NSString *) appDisplayName path:(NSString *) path resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRDatabaseReference *ref = [self getReferenceForAppPath:appName path:path]; + FIRDatabaseReference *ref = [self getReferenceForAppPath:appDisplayName path:path]; [ref removeValueWithCompletionBlock:^(NSError *_Nullable error, FIRDatabaseReference *_Nonnull _ref) { [RNFirebaseDatabase handlePromise:resolve rejecter:reject databaseError:error]; }]; } -RCT_EXPORT_METHOD(once:(NSString *) appName +RCT_EXPORT_METHOD(once:(NSString *) appDisplayName key:(NSString *) key path:(NSString *) path modifiers:(NSArray *) modifiers eventName:(NSString *) eventName resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - RNFirebaseDatabaseReference *ref = [self getInternalReferenceForApp:appName key:key path:path modifiers:modifiers]; + RNFirebaseDatabaseReference *ref = [self getInternalReferenceForApp:appDisplayName key:key path:path modifiers:modifiers]; [ref once:eventName resolver:resolve rejecter:reject]; } -RCT_EXPORT_METHOD(on:(NSString *) appName +RCT_EXPORT_METHOD(on:(NSString *) appDisplayName props:(NSDictionary *) props) { - RNFirebaseDatabaseReference *ref = [self getCachedInternalReferenceForApp:appName props:props]; + RNFirebaseDatabaseReference *ref = [self getCachedInternalReferenceForApp:appDisplayName props:props]; [ref on:props[@"eventType"] registration:props[@"registration"]]; } @@ -271,20 +271,20 @@ RCT_EXPORT_METHOD(off:(NSString *) key } } -+ (FIRDatabase *)getDatabaseForApp:(NSString *)appName { - FIRApp *app = [FIRApp appNamed:appName]; ++ (FIRDatabase *)getDatabaseForApp:(NSString *)appDisplayName { + FIRApp *app = [RNFirebaseUtil getApp:appDisplayName]; return [FIRDatabase databaseForApp:app]; } -- (FIRDatabaseReference *)getReferenceForAppPath:(NSString *)appName path:(NSString *)path { - return [[RNFirebaseDatabase getDatabaseForApp:appName] referenceWithPath:path]; +- (FIRDatabaseReference *)getReferenceForAppPath:(NSString *)appDisplayName path:(NSString *)path { + return [[RNFirebaseDatabase getDatabaseForApp:appDisplayName] referenceWithPath:path]; } -- (RNFirebaseDatabaseReference *)getInternalReferenceForApp:(NSString *)appName key:(NSString *)key path:(NSString *)path modifiers:(NSArray *)modifiers { - return [[RNFirebaseDatabaseReference alloc] initWithPathAndModifiers:self app:appName key:key refPath:path modifiers:modifiers]; +- (RNFirebaseDatabaseReference *)getInternalReferenceForApp:(NSString *)appDisplayName key:(NSString *)key path:(NSString *)path modifiers:(NSArray *)modifiers { + return [[RNFirebaseDatabaseReference alloc] initWithPathAndModifiers:self appDisplayName:appDisplayName key:key refPath:path modifiers:modifiers]; } -- (RNFirebaseDatabaseReference *)getCachedInternalReferenceForApp:(NSString *)appName props:(NSDictionary *)props { +- (RNFirebaseDatabaseReference *)getCachedInternalReferenceForApp:(NSString *)appDisplayName props:(NSDictionary *)props { NSString *key = props[@"key"]; NSString *path = props[@"path"]; NSDictionary *modifiers = props[@"modifiers"]; @@ -292,7 +292,7 @@ RCT_EXPORT_METHOD(off:(NSString *) key RNFirebaseDatabaseReference *ref = _dbReferences[key]; if (ref == nil) { - ref = [[RNFirebaseDatabaseReference alloc] initWithPathAndModifiers:self app:appName key:key refPath:path modifiers:modifiers]; + ref = [[RNFirebaseDatabaseReference alloc] initWithPathAndModifiers:self appDisplayName:appDisplayName key:key refPath:path modifiers:modifiers]; _dbReferences[key] = ref; } return ref; @@ -380,20 +380,20 @@ RCT_EXPORT_METHOD(off:(NSString *) key return errorMap; } -- (NSDictionary *)createTransactionUpdateMap:(NSString *)appName transactionId:(NSNumber *)transactionId updatesData:(FIRMutableData *)updatesData { +- (NSDictionary *)createTransactionUpdateMap:(NSString *)appDisplayName transactionId:(NSNumber *)transactionId updatesData:(FIRMutableData *)updatesData { NSMutableDictionary *updatesMap = [[NSMutableDictionary alloc] init]; [updatesMap setValue:transactionId forKey:@"id"]; [updatesMap setValue:@"update" forKey:@"type"]; - [updatesMap setValue:appName forKey:@"appName"]; + [updatesMap setValue:appDisplayName forKey:@"appName"]; [updatesMap setValue:updatesData.value forKey:@"value"]; return updatesMap; } -- (NSDictionary *)createTransactionResultMap:(NSString *)appName transactionId:(NSNumber *)transactionId error:(NSError *)error committed:(BOOL)committed snapshot:(FIRDataSnapshot *)snapshot { +- (NSDictionary *)createTransactionResultMap:(NSString *)appDisplayName transactionId:(NSNumber *)transactionId error:(NSError *)error committed:(BOOL)committed snapshot:(FIRDataSnapshot *)snapshot { NSMutableDictionary *resultMap = [[NSMutableDictionary alloc] init]; [resultMap setValue:transactionId forKey:@"id"]; - [resultMap setValue:appName forKey:@"appName"]; + [resultMap setValue:appDisplayName forKey:@"appName"]; // TODO: no timeout on iOS [resultMap setValue:@(committed) forKey:@"committed"]; // TODO: no interrupted on iOS diff --git a/ios/RNFirebase/database/RNFirebaseDatabaseReference.h b/ios/RNFirebase/database/RNFirebaseDatabaseReference.h index ec02e502..fb64295c 100644 --- a/ios/RNFirebase/database/RNFirebaseDatabaseReference.h +++ b/ios/RNFirebase/database/RNFirebaseDatabaseReference.h @@ -12,12 +12,12 @@ @interface RNFirebaseDatabaseReference : NSObject @property RCTEventEmitter *emitter; @property FIRDatabaseQuery *query; -@property NSString *app; +@property NSString *appDisplayName; @property NSString *key; @property NSString *path; @property NSMutableDictionary *listeners; -- (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter app:(NSString *)app key:(NSString *)key refPath:(NSString *)refPath modifiers:(NSArray *)modifiers; +- (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter appDisplayName:(NSString *)appDisplayName key:(NSString *)key refPath:(NSString *)refPath modifiers:(NSArray *)modifiers; - (void)on:(NSString *) eventName registration:(NSDictionary *) registration; - (void)once:(NSString *) eventType resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject; - (void)removeEventListener:(NSString *)eventRegistrationKey; diff --git a/ios/RNFirebase/database/RNFirebaseDatabaseReference.m b/ios/RNFirebase/database/RNFirebaseDatabaseReference.m index 3a3d6730..a6caf8c2 100644 --- a/ios/RNFirebase/database/RNFirebaseDatabaseReference.m +++ b/ios/RNFirebase/database/RNFirebaseDatabaseReference.m @@ -5,14 +5,14 @@ #if __has_include() - (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter - app:(NSString *) app + appDisplayName:(NSString *) appDisplayName key:(NSString *) key refPath:(NSString *) refPath modifiers:(NSArray *) modifiers { self = [super init]; if (self) { _emitter = emitter; - _app = app; + _appDisplayName = appDisplayName; _key = key; _path = refPath; _listeners = [[NSMutableDictionary alloc] init]; @@ -123,7 +123,7 @@ - (FIRDatabaseQuery *)buildQueryAtPathWithModifiers:(NSString *) path modifiers:(NSArray *)modifiers { - FIRDatabase *firebaseDatabase = [RNFirebaseDatabase getDatabaseForApp:_app]; + FIRDatabase *firebaseDatabase = [RNFirebaseDatabase getDatabaseForApp:_appDisplayName]; FIRDatabaseQuery *query = [[firebaseDatabase reference] child:path]; for (NSDictionary *modifier in modifiers) { diff --git a/ios/RNFirebase/firestore/RNFirebaseFirestore.h b/ios/RNFirebase/firestore/RNFirebaseFirestore.h index e93595b1..98036471 100644 --- a/ios/RNFirebase/firestore/RNFirebaseFirestore.h +++ b/ios/RNFirebase/firestore/RNFirebaseFirestore.h @@ -13,7 +13,7 @@ + (void)promiseRejectException:(RCTPromiseRejectBlock)reject error:(NSError *)error; -+ (FIRFirestore *)getFirestoreForApp:(NSString *)appName; ++ (FIRFirestore *)getFirestoreForApp:(NSString *)appDisplayName; + (NSDictionary *)getJSError:(NSError *)nativeError; @end diff --git a/ios/RNFirebase/firestore/RNFirebaseFirestore.m b/ios/RNFirebase/firestore/RNFirebaseFirestore.m index 29d8646d..f662afb0 100644 --- a/ios/RNFirebase/firestore/RNFirebaseFirestore.m +++ b/ios/RNFirebase/firestore/RNFirebaseFirestore.m @@ -22,17 +22,17 @@ RCT_EXPORT_METHOD(enableLogging:(BOOL) enabled) { [FIRFirestore enableLogging:enabled]; } -RCT_EXPORT_METHOD(collectionGet:(NSString *) appName +RCT_EXPORT_METHOD(collectionGet:(NSString *) appDisplayName path:(NSString *) path filters:(NSArray *) filters orders:(NSArray *) orders options:(NSDictionary *) options resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - [[self getCollectionForAppPath:appName path:path filters:filters orders:orders options:options] get:resolve rejecter:reject]; + [[self getCollectionForAppPath:appDisplayName path:path filters:filters orders:orders options:options] get:resolve rejecter:reject]; } -RCT_EXPORT_METHOD(collectionOffSnapshot:(NSString *) appName +RCT_EXPORT_METHOD(collectionOffSnapshot:(NSString *) appDisplayName path:(NSString *) path filters:(NSArray *) filters orders:(NSArray *) orders @@ -41,22 +41,22 @@ RCT_EXPORT_METHOD(collectionOffSnapshot:(NSString *) appName [RNFirebaseFirestoreCollectionReference offSnapshot:listenerId]; } -RCT_EXPORT_METHOD(collectionOnSnapshot:(NSString *) appName +RCT_EXPORT_METHOD(collectionOnSnapshot:(NSString *) appDisplayName path:(NSString *) path filters:(NSArray *) filters orders:(NSArray *) orders options:(NSDictionary *) options listenerId:(nonnull NSString *) listenerId queryListenOptions:(NSDictionary *) queryListenOptions) { - RNFirebaseFirestoreCollectionReference *ref = [self getCollectionForAppPath:appName path:path filters:filters orders:orders options:options]; + RNFirebaseFirestoreCollectionReference *ref = [self getCollectionForAppPath:appDisplayName path:path filters:filters orders:orders options:options]; [ref onSnapshot:listenerId queryListenOptions:queryListenOptions]; } -RCT_EXPORT_METHOD(documentBatch:(NSString *) appName +RCT_EXPORT_METHOD(documentBatch:(NSString *) appDisplayName writes:(NSArray *) writes resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:appName]; + FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:appDisplayName]; FIRWriteBatch *batch = [firestore batch]; for (NSDictionary *write in writes) { @@ -89,56 +89,56 @@ RCT_EXPORT_METHOD(documentBatch:(NSString *) appName }]; } -RCT_EXPORT_METHOD(documentDelete:(NSString *) appName +RCT_EXPORT_METHOD(documentDelete:(NSString *) appDisplayName path:(NSString *) path resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - [[self getDocumentForAppPath:appName path:path] delete:resolve rejecter:reject]; + [[self getDocumentForAppPath:appDisplayName path:path] delete:resolve rejecter:reject]; } -RCT_EXPORT_METHOD(documentGet:(NSString *) appName +RCT_EXPORT_METHOD(documentGet:(NSString *) appDisplayName path:(NSString *) path resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - [[self getDocumentForAppPath:appName path:path] get:resolve rejecter:reject]; + [[self getDocumentForAppPath:appDisplayName path:path] get:resolve rejecter:reject]; } -RCT_EXPORT_METHOD(documentGetAll:(NSString *) appName +RCT_EXPORT_METHOD(documentGetAll:(NSString *) appDisplayName documents:(NSString *) documents resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { // Not supported on iOS out of the box } -RCT_EXPORT_METHOD(documentOffSnapshot:(NSString *) appName +RCT_EXPORT_METHOD(documentOffSnapshot:(NSString *) appDisplayName path:(NSString *) path listenerId:(nonnull NSString *) listenerId) { [RNFirebaseFirestoreDocumentReference offSnapshot:listenerId]; } -RCT_EXPORT_METHOD(documentOnSnapshot:(NSString *) appName +RCT_EXPORT_METHOD(documentOnSnapshot:(NSString *) appDisplayName path:(NSString *) path listenerId:(nonnull NSString *) listenerId docListenOptions:(NSDictionary *) docListenOptions) { - RNFirebaseFirestoreDocumentReference *ref = [self getDocumentForAppPath:appName path:path]; + RNFirebaseFirestoreDocumentReference *ref = [self getDocumentForAppPath:appDisplayName path:path]; [ref onSnapshot:listenerId docListenOptions:docListenOptions]; } -RCT_EXPORT_METHOD(documentSet:(NSString *) appName +RCT_EXPORT_METHOD(documentSet:(NSString *) appDisplayName path:(NSString *) path data:(NSDictionary *) data options:(NSDictionary *) options resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - [[self getDocumentForAppPath:appName path:path] set:data options:options resolver:resolve rejecter:reject]; + [[self getDocumentForAppPath:appDisplayName path:path] set:data options:options resolver:resolve rejecter:reject]; } -RCT_EXPORT_METHOD(documentUpdate:(NSString *) appName +RCT_EXPORT_METHOD(documentUpdate:(NSString *) appDisplayName path:(NSString *) path data:(NSDictionary *) data resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - [[self getDocumentForAppPath:appName path:path] update:data resolver:resolve rejecter:reject]; + [[self getDocumentForAppPath:appDisplayName path:path] update:data resolver:resolve rejecter:reject]; } /* @@ -149,17 +149,17 @@ RCT_EXPORT_METHOD(documentUpdate:(NSString *) appName reject([jsError valueForKey:@"code"], [jsError valueForKey:@"message"], error); } -+ (FIRFirestore *)getFirestoreForApp:(NSString *)appName { - FIRApp *app = [FIRApp appNamed:appName]; ++ (FIRFirestore *)getFirestoreForApp:(NSString *)appDisplayName { + FIRApp *app = [RNFirebaseUtil getApp:appDisplayName]; return [FIRFirestore firestoreForApp:app]; } -- (RNFirebaseFirestoreCollectionReference *)getCollectionForAppPath:(NSString *)appName path:(NSString *)path filters:(NSArray *)filters orders:(NSArray *)orders options:(NSDictionary *)options { - return [[RNFirebaseFirestoreCollectionReference alloc] initWithPathAndModifiers:self app:appName path:path filters:filters orders:orders options:options]; +- (RNFirebaseFirestoreCollectionReference *)getCollectionForAppPath:(NSString *)appDisplayName path:(NSString *)path filters:(NSArray *)filters orders:(NSArray *)orders options:(NSDictionary *)options { + return [[RNFirebaseFirestoreCollectionReference alloc] initWithPathAndModifiers:self appDisplayName:appDisplayName path:path filters:filters orders:orders options:options]; } -- (RNFirebaseFirestoreDocumentReference *)getDocumentForAppPath:(NSString *)appName path:(NSString *)path { - return [[RNFirebaseFirestoreDocumentReference alloc] initWithPath:self app:appName path:path]; +- (RNFirebaseFirestoreDocumentReference *)getDocumentForAppPath:(NSString *)appDisplayName path:(NSString *)path { + return [[RNFirebaseFirestoreDocumentReference alloc] initWithPath:self appDisplayName:appDisplayName path:path]; } // TODO: Move to error util for use in other modules diff --git a/ios/RNFirebase/firestore/RNFirebaseFirestoreCollectionReference.h b/ios/RNFirebase/firestore/RNFirebaseFirestoreCollectionReference.h index 8fc07cbe..9e067ab0 100644 --- a/ios/RNFirebase/firestore/RNFirebaseFirestoreCollectionReference.h +++ b/ios/RNFirebase/firestore/RNFirebaseFirestoreCollectionReference.h @@ -13,14 +13,14 @@ @interface RNFirebaseFirestoreCollectionReference : NSObject @property RCTEventEmitter *emitter; -@property NSString *app; +@property NSString *appDisplayName; @property NSString *path; @property NSArray *filters; @property NSArray *orders; @property NSDictionary *options; @property FIRQuery *query; -- (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter app:(NSString *)app path:(NSString *)path filters:(NSArray *)filters orders:(NSArray *)orders options:(NSDictionary *)options; +- (id)initWithPathAndModifiers:(RCTEventEmitter *)emitter appDisplayName:(NSString *)appDisplayName path:(NSString *)path filters:(NSArray *)filters orders:(NSArray *)orders options:(NSDictionary *)options; - (void)get:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject; + (void)offSnapshot:(NSString *)listenerId; - (void)onSnapshot:(NSString *)listenerId queryListenOptions:(NSDictionary *) queryListenOptions; diff --git a/ios/RNFirebase/firestore/RNFirebaseFirestoreCollectionReference.m b/ios/RNFirebase/firestore/RNFirebaseFirestoreCollectionReference.m index 4985ab8e..91af07cd 100644 --- a/ios/RNFirebase/firestore/RNFirebaseFirestoreCollectionReference.m +++ b/ios/RNFirebase/firestore/RNFirebaseFirestoreCollectionReference.m @@ -7,7 +7,7 @@ static NSMutableDictionary *_listeners; - (id)initWithPathAndModifiers:(RCTEventEmitter *) emitter - app:(NSString *) app + appDisplayName:(NSString *) appDisplayName path:(NSString *) path filters:(NSArray *) filters orders:(NSArray *) orders @@ -15,7 +15,7 @@ static NSMutableDictionary *_listeners; self = [super init]; if (self) { _emitter = emitter; - _app = app; + _appDisplayName = appDisplayName; _path = path; _filters = filters; _orders = orders; @@ -64,7 +64,7 @@ queryListenOptions:(NSDictionary *) queryListenOptions { [self handleQuerySnapshotEvent:listenerId querySnapshot:snapshot]; } }; - + FIRQueryListenOptions *options = [[FIRQueryListenOptions alloc] init]; if (queryListenOptions) { if (queryListenOptions[@"includeDocumentMetadataChanges"]) { @@ -74,14 +74,14 @@ queryListenOptions:(NSDictionary *) queryListenOptions { [options includeQueryMetadataChanges:TRUE]; } } - + id listener = [_query addSnapshotListenerWithOptions:options listener:listenerBlock]; _listeners[listenerId] = listener; } } - (FIRQuery *)buildQuery { - FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:_app]; + FIRFirestore *firestore = [RNFirebaseFirestore getFirestoreForApp:_appDisplayName]; FIRQuery *query = (FIRQuery*)[firestore collectionWithPath:_path]; query = [self applyFilters:firestore query:query]; query = [self applyOrders:query]; @@ -152,7 +152,7 @@ queryListenOptions:(NSDictionary *) queryListenOptions { - (void)handleQuerySnapshotError:(NSString *)listenerId error:(NSError *)error { NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; - [event setValue:_app forKey:@"appName"]; + [event setValue:_appDisplayName forKey:@"appName"]; [event setValue:_path forKey:@"path"]; [event setValue:listenerId forKey:@"listenerId"]; [event setValue:[RNFirebaseFirestore getJSError:error] forKey:@"error"]; @@ -163,7 +163,7 @@ queryListenOptions:(NSDictionary *) queryListenOptions { - (void)handleQuerySnapshotEvent:(NSString *)listenerId querySnapshot:(FIRQuerySnapshot *)querySnapshot { NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; - [event setValue:_app forKey:@"appName"]; + [event setValue:_appDisplayName forKey:@"appName"]; [event setValue:_path forKey:@"path"]; [event setValue:listenerId forKey:@"listenerId"]; [event setValue:[RNFirebaseFirestoreCollectionReference snapshotToDictionary:querySnapshot] forKey:@"querySnapshot"]; diff --git a/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.h b/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.h index 5a944ad9..9745a091 100644 --- a/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.h +++ b/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.h @@ -13,11 +13,11 @@ @interface RNFirebaseFirestoreDocumentReference : NSObject @property RCTEventEmitter *emitter; -@property NSString *app; +@property NSString *appDisplayName; @property NSString *path; @property FIRDocumentReference *ref; -- (id)initWithPath:(RCTEventEmitter *)emitter app:(NSString *)app path:(NSString *)path; +- (id)initWithPath:(RCTEventEmitter *)emitter appDisplayName:(NSString *)appDisplayName path:(NSString *)path; - (void)delete:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject; - (void)get:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject; + (void)offSnapshot:(NSString *)listenerId; diff --git a/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.m b/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.m index d9c5a950..ba8ca21b 100644 --- a/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.m +++ b/ios/RNFirebase/firestore/RNFirebaseFirestoreDocumentReference.m @@ -7,14 +7,14 @@ static NSMutableDictionary *_listeners; - (id)initWithPath:(RCTEventEmitter *)emitter - app:(NSString *) app + appDisplayName:(NSString *) appDisplayName path:(NSString *) path { self = [super init]; if (self) { _emitter = emitter; - _app = app; + _appDisplayName = appDisplayName; _path = path; - _ref = [[RNFirebaseFirestore getFirestoreForApp:_app] documentWithPath:_path]; + _ref = [[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] documentWithPath:_path]; } // Initialise the static listeners object if required if (!_listeners) { @@ -78,7 +78,7 @@ static NSMutableDictionary *_listeners; options:(NSDictionary *) options resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject { - NSDictionary *dictionary = [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_app] jsMap:data]; + NSDictionary *dictionary = [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] jsMap:data]; if (options && options[@"merge"]) { [_ref setData:dictionary options:[FIRSetOptions merge] completion:^(NSError * _Nullable error) { [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; @@ -93,7 +93,7 @@ static NSMutableDictionary *_listeners; - (void)update:(NSDictionary *) data resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject { - NSDictionary *dictionary = [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_app] jsMap:data]; + NSDictionary *dictionary = [RNFirebaseFirestoreDocumentReference parseJSMap:[RNFirebaseFirestore getFirestoreForApp:_appDisplayName] jsMap:data]; [_ref updateData:dictionary completion:^(NSError * _Nullable error) { [RNFirebaseFirestoreDocumentReference handleWriteResponse:error resolver:resolve rejecter:reject]; }]; @@ -131,7 +131,7 @@ static NSMutableDictionary *_listeners; - (void)handleDocumentSnapshotError:(NSString *)listenerId error:(NSError *)error { NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; - [event setValue:_app forKey:@"appName"]; + [event setValue:_appDisplayName forKey:@"appName"]; [event setValue:_path forKey:@"path"]; [event setValue:listenerId forKey:@"listenerId"]; [event setValue:[RNFirebaseFirestore getJSError:error] forKey:@"error"]; @@ -142,7 +142,7 @@ static NSMutableDictionary *_listeners; - (void)handleDocumentSnapshotEvent:(NSString *)listenerId documentSnapshot:(FIRDocumentSnapshot *)documentSnapshot { NSMutableDictionary *event = [[NSMutableDictionary alloc] init]; - [event setValue:_app forKey:@"appName"]; + [event setValue:_appDisplayName forKey:@"appName"]; [event setValue:_path forKey:@"path"]; [event setValue:listenerId forKey:@"listenerId"]; [event setValue:[RNFirebaseFirestoreDocumentReference snapshotToDictionary:documentSnapshot] forKey:@"documentSnapshot"]; diff --git a/ios/RNFirebase/storage/RNFirebaseStorage.m b/ios/RNFirebase/storage/RNFirebaseStorage.m index e73038d5..ce6ea1ed 100644 --- a/ios/RNFirebase/storage/RNFirebaseStorage.m +++ b/ios/RNFirebase/storage/RNFirebaseStorage.m @@ -23,11 +23,11 @@ RCT_EXPORT_MODULE(RNFirebaseStorage); @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#delete @param NSString path */ -RCT_EXPORT_METHOD(delete:(NSString *) appName +RCT_EXPORT_METHOD(delete:(NSString *) appDisplayName path:(NSString *) path resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRStorageReference *fileRef = [self getReference:path appName:appName]; + FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName]; [fileRef deleteWithCompletion:^(NSError *_Nullable error) { if (error != nil) { @@ -44,11 +44,11 @@ RCT_EXPORT_METHOD(delete:(NSString *) appName @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#getDownloadURL @param NSString path */ -RCT_EXPORT_METHOD(getDownloadURL:(NSString *) appName +RCT_EXPORT_METHOD(getDownloadURL:(NSString *) appDisplayName path:(NSString *) path resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRStorageReference *fileRef = [self getReference:path appName:appName]; + FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName]; [fileRef downloadURLWithCompletion:^(NSURL *_Nullable URL, NSError *_Nullable error) { if (error != nil) { @@ -65,11 +65,11 @@ RCT_EXPORT_METHOD(getDownloadURL:(NSString *) appName @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference#getMetadata @param NSString path */ -RCT_EXPORT_METHOD(getMetadata:(NSString *) appName +RCT_EXPORT_METHOD(getMetadata:(NSString *) appDisplayName path:(NSString *) path resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRStorageReference *fileRef = [self getReference:path appName:appName]; + FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName]; [fileRef metadataWithCompletion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) { if (error != nil) { @@ -87,12 +87,12 @@ RCT_EXPORT_METHOD(getMetadata:(NSString *) appName @param NSString path @param NSDictionary metadata */ -RCT_EXPORT_METHOD(updateMetadata:(NSString *) appName +RCT_EXPORT_METHOD(updateMetadata:(NSString *) appDisplayName path:(NSString *) path metadata:(NSDictionary *) metadata resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRStorageReference *fileRef = [self getReference:path appName:appName]; + FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName]; FIRStorageMetadata *firmetadata = [self buildMetadataFromMap:metadata]; [fileRef updateMetadata:firmetadata completion:^(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error) { @@ -111,12 +111,12 @@ RCT_EXPORT_METHOD(updateMetadata:(NSString *) appName @param NSString path @param NSString localPath */ -RCT_EXPORT_METHOD(downloadFile:(NSString *) appName +RCT_EXPORT_METHOD(downloadFile:(NSString *) appDisplayName path:(NSString *) path localPath:(NSString *) localPath resolver:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject) { - FIRStorageReference *fileRef = [self getReference:path appName:appName]; + FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName]; NSURL *localFile = [NSURL fileURLWithPath:localPath]; FIRStorageDownloadTask *downloadTask = [fileRef writeToFile:localFile]; @@ -124,25 +124,25 @@ RCT_EXPORT_METHOD(downloadFile:(NSString *) appName [downloadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) { // download resumed, also fires when the upload starts NSDictionary *event = [self getDownloadTaskAsDictionary:snapshot]; - [self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; + [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; }]; [downloadTask observeStatus:FIRStorageTaskStatusPause handler:^(FIRStorageTaskSnapshot *snapshot) { // download paused NSDictionary *event = [self getDownloadTaskAsDictionary:snapshot]; - [self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; + [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; }]; [downloadTask observeStatus:FIRStorageTaskStatusProgress handler:^(FIRStorageTaskSnapshot *snapshot) { // download reported progress NSDictionary *event = [self getDownloadTaskAsDictionary:snapshot]; - [self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; + [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; }]; [downloadTask observeStatus:FIRStorageTaskStatusSuccess handler:^(FIRStorageTaskSnapshot *snapshot) { // download completed successfully NSDictionary *resp = [self getDownloadTaskAsDictionary:snapshot]; - [self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_DOWNLOAD_SUCCESS props:resp]; + [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_DOWNLOAD_SUCCESS props:resp]; resolve(resp); }]; @@ -161,9 +161,10 @@ RCT_EXPORT_METHOD(downloadFile:(NSString *) appName @url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxDownloadRetryTime @param NSNumber milliseconds */ -RCT_EXPORT_METHOD(setMaxDownloadRetryTime:(NSString *) appName +RCT_EXPORT_METHOD(setMaxDownloadRetryTime:(NSString *) appDisplayName milliseconds:(NSNumber *) milliseconds) { - [[FIRStorage storageForApp:[FIRApp appNamed:appName]] setMaxDownloadRetryTime:[milliseconds doubleValue]]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; + [[FIRStorage storageForApp:firApp] setMaxDownloadRetryTime:[milliseconds doubleValue]]; } /** @@ -172,9 +173,10 @@ RCT_EXPORT_METHOD(setMaxDownloadRetryTime:(NSString *) appName @url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxOperationRetryTime @param NSNumber milliseconds */ -RCT_EXPORT_METHOD(setMaxOperationRetryTime:(NSString *) appName +RCT_EXPORT_METHOD(setMaxOperationRetryTime:(NSString *) appDisplayName milliseconds:(NSNumber *) milliseconds) { - [[FIRStorage storageForApp:[FIRApp appNamed:appName]] setMaxOperationRetryTime:[milliseconds doubleValue]]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; + [[FIRStorage storageForApp:firApp] setMaxOperationRetryTime:[milliseconds doubleValue]]; } /** @@ -182,9 +184,10 @@ RCT_EXPORT_METHOD(setMaxOperationRetryTime:(NSString *) appName @url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxUploadRetryTime */ -RCT_EXPORT_METHOD(setMaxUploadRetryTime:(NSString *) appName +RCT_EXPORT_METHOD(setMaxUploadRetryTime:(NSString *) appDisplayName milliseconds:(NSNumber *) milliseconds) { - [[FIRStorage storageForApp:[FIRApp appNamed:appName]] setMaxUploadRetryTime:[milliseconds doubleValue]]; + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; + [[FIRStorage storageForApp:firApp] setMaxUploadRetryTime:[milliseconds doubleValue]]; } /** @@ -195,7 +198,7 @@ RCT_EXPORT_METHOD(setMaxUploadRetryTime:(NSString *) appName @param NSString localPath @param NSDictionary metadata */ -RCT_EXPORT_METHOD(putFile:(NSString *) appName +RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName path:(NSString *) path localPath:(NSString *) localPath metadata:(NSDictionary *) metadata @@ -224,7 +227,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName if (info[PHImageErrorKey] == nil) { if (UTTypeConformsTo((__bridge CFStringRef)dataUTI, kUTTypeJPEG)) { firmetadata.contentType = [self utiToMimeType:dataUTI]; - [self uploadData:appName data:imageData firmetadata:firmetadata path:path resolver:resolve rejecter:reject]; + [self uploadData:appDisplayName data:imageData firmetadata:firmetadata path:path resolver:resolve rejecter:reject]; } else { // if the image UTI is not JPEG then convert to JPEG, e.g. HEI CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL); @@ -236,7 +239,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName CGImageDestinationFinalize(destination); // Manually set mimetype to JPEG firmetadata.contentType = @"image/jpeg"; - [self uploadData:appName data:[NSData dataWithData:imageDataJPEG] firmetadata:firmetadata path:path resolver:resolve rejecter:reject]; + [self uploadData:appDisplayName data:[NSData dataWithData:imageDataJPEG] firmetadata:firmetadata path:path resolver:resolve rejecter:reject]; } } else { reject(@"storage/request-image-data-failed", @"Could not obtain image data for the specified file.", nil); @@ -260,7 +263,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName [exportSession exportAsynchronouslyWithCompletionHandler:^{ if (exportSession.status == AVAssetExportSessionStatusCompleted) { firmetadata.contentType = [self utiToMimeType:exportSession.outputFileType]; - [self uploadFile:appName url:tempUrl firmetadata:firmetadata path:path resolver:resolve rejecter:reject]; + [self uploadFile:appDisplayName url:tempUrl firmetadata:firmetadata path:path resolver:resolve rejecter:reject]; // we're not cleaning up the temporary file at the moment, just relying on the OS to do that in it's own time - todo? } else { reject(@"storage/temporary-file-failure", @"Unable to create temporary file for upload.", nil); @@ -274,7 +277,7 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName } else { // TODO: Content type for file? NSData *data = [[NSFileManager defaultManager] contentsAtPath:localPath]; - [self uploadData:appName data:data firmetadata:firmetadata path:path resolver:resolve rejecter:reject]; + [self uploadData:appDisplayName data:data firmetadata:firmetadata path:path resolver:resolve rejecter:reject]; } } @@ -288,42 +291,42 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName return (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)dataUTI, kUTTagClassMIMEType); } -- (void)uploadFile:(NSString *)appName url:(NSURL *)url firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject { - FIRStorageReference *fileRef = [self getReference:path appName:appName]; +- (void)uploadFile:(NSString *)appDisplayName url:(NSURL *)url firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject { + FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName]; FIRStorageUploadTask *uploadTask = [fileRef putFile:url metadata:firmetadata]; - [self addUploadObservers:appName uploadTask:uploadTask path:path resolver:resolve rejecter:reject]; + [self addUploadObservers:appDisplayName uploadTask:uploadTask path:path resolver:resolve rejecter:reject]; } -- (void)uploadData:(NSString *)appName data:(NSData *)data firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject { - FIRStorageReference *fileRef = [self getReference:path appName:appName]; +- (void)uploadData:(NSString *)appDisplayName data:(NSData *)data firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject { + FIRStorageReference *fileRef = [self getReference:path appDisplayName:appDisplayName]; FIRStorageUploadTask *uploadTask = [fileRef putData:data metadata:firmetadata]; - [self addUploadObservers:appName uploadTask:uploadTask path:path resolver:resolve rejecter:reject]; + [self addUploadObservers:appDisplayName uploadTask:uploadTask path:path resolver:resolve rejecter:reject]; } -- (void)addUploadObservers:(NSString *)appName uploadTask:(FIRStorageUploadTask *)uploadTask path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject { +- (void)addUploadObservers:(NSString *)appDisplayName uploadTask:(FIRStorageUploadTask *)uploadTask path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject { // listen for state changes, errors, and completion of the upload. [uploadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) { // upload resumed, also fires when the upload starts NSDictionary *event = [self getUploadTaskAsDictionary:snapshot]; - [self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; + [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; }]; [uploadTask observeStatus:FIRStorageTaskStatusPause handler:^(FIRStorageTaskSnapshot *snapshot) { // upload paused NSDictionary *event = [self getUploadTaskAsDictionary:snapshot]; - [self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; + [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; }]; [uploadTask observeStatus:FIRStorageTaskStatusProgress handler:^(FIRStorageTaskSnapshot *snapshot) { // upload reported progress NSDictionary *event = [self getUploadTaskAsDictionary:snapshot]; - [self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; + [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:event]; }]; [uploadTask observeStatus:FIRStorageTaskStatusSuccess handler:^(FIRStorageTaskSnapshot *snapshot) { // upload completed successfully NSDictionary *resp = [self getUploadTaskAsDictionary:snapshot]; - [self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:resp]; - [self sendJSEvent:appName type:STORAGE_EVENT path:path title:STORAGE_UPLOAD_SUCCESS props:resp]; + [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_STATE_CHANGED props:resp]; + [self sendJSEvent:appDisplayName type:STORAGE_EVENT path:path title:STORAGE_UPLOAD_SUCCESS props:resp]; resolve(resp); }]; @@ -335,12 +338,13 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName } - (FIRStorageReference *)getReference:(NSString *)path - appName:(NSString *)appName { + appDisplayName:(NSString *)appDisplayName { + FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; if ([path hasPrefix:@"url::"]) { NSString *url = [path substringFromIndex:5]; - return [[FIRStorage storageForApp:[FIRApp appNamed:appName]] referenceForURL:url]; + return [[FIRStorage storageForApp:firApp] referenceForURL:url]; } else { - return [[FIRStorage storageForApp:[FIRApp appNamed:appName]] referenceWithPath:path]; + return [[FIRStorage storageForApp:firApp] referenceWithPath:path]; } } @@ -387,13 +391,13 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appName return @[STORAGE_EVENT, STORAGE_ERROR]; } -- (void)sendJSError:(NSString *)appName error:(NSError *)error path:(NSString *)path { +- (void)sendJSError:(NSString *)appDisplayName error:(NSError *)error path:(NSString *)path { NSDictionary *evt = @{@"path": path, @"message": [error debugDescription]}; - [self sendJSEvent:appName type:STORAGE_ERROR path:path title:STORAGE_ERROR props:evt]; + [self sendJSEvent:appDisplayName type:STORAGE_ERROR path:path title:STORAGE_ERROR props:evt]; } -- (void)sendJSEvent:(NSString *)appName type:(NSString *)type path:(NSString *)path title:(NSString *)title props:(NSDictionary *)props { - [RNFirebaseUtil sendJSEvent:self name:type body:@{@"eventName": title, @"appName": appName, @"path": path, @"body": props}]; +- (void)sendJSEvent:(NSString *)appDisplayName type:(NSString *)type path:(NSString *)path title:(NSString *)title props:(NSDictionary *)props { + [RNFirebaseUtil sendJSEvent:self name:type body:@{@"eventName": title, @"appName": appDisplayName, @"path": path, @"body": props}]; } /** diff --git a/lib/modules/admob/index.js b/lib/modules/admob/index.js index fc971d01..8a81f873 100644 --- a/lib/modules/admob/index.js +++ b/lib/modules/admob/index.js @@ -31,15 +31,19 @@ const NATIVE_EVENTS = [ 'rewarded_video_event', ]; -export default class AdMob extends ModuleBase { - static _NAMESPACE = 'admob'; - static _NATIVE_MODULE = 'RNFirebaseAdMob'; +export const MODULE_NAME = 'RNFirebaseAdmob'; +export const NAMESPACE = 'admob'; +export default class AdMob extends ModuleBase { _appId: ?string; _initialized: boolean; constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, NATIVE_EVENTS); + super(firebaseApp, options, { + events: NATIVE_EVENTS, + moduleName: MODULE_NAME, + namespace: NAMESPACE, + }); this._initialized = false; this._appId = null; diff --git a/lib/modules/analytics/index.js b/lib/modules/analytics/index.js index cc842340..dbff883c 100644 --- a/lib/modules/analytics/index.js +++ b/lib/modules/analytics/index.js @@ -24,12 +24,15 @@ const ReservedEventNames = [ 'user_engagement', ]; -export default class Analytics extends ModuleBase { - static _NAMESPACE = 'analytics'; - static _NATIVE_MODULE = 'RNFirebaseAnalytics'; +export const MODULE_NAME = 'RNFirebaseAnalytics'; +export const NAMESPACE = 'analytics'; +export default class Analytics extends ModuleBase { constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options); + super(firebaseApp, options, { + moduleName: MODULE_NAME, + namespace: NAMESPACE, + }); } /** diff --git a/lib/modules/auth/index.js b/lib/modules/auth/index.js index e9ac0296..acf8e0a5 100644 --- a/lib/modules/auth/index.js +++ b/lib/modules/auth/index.js @@ -32,15 +32,19 @@ const NATIVE_EVENTS = [ 'phone_auth_state_changed', ]; -export default class Auth extends ModuleBase { - static _NAMESPACE = 'auth'; - static _NATIVE_MODULE = 'RNFirebaseAuth'; +export const MODULE_NAME = 'RNFirebaseAuth'; +export const NAMESPACE = 'auth'; +export default class Auth extends ModuleBase { _authResult: AuthResult | null; _user: User | null; constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, NATIVE_EVENTS); + super(firebaseApp, options, { + events: NATIVE_EVENTS, + moduleName: MODULE_NAME, + namespace: NAMESPACE, + }); this._user = null; this._authResult = null; @@ -346,23 +350,23 @@ export default class Auth extends ModuleBase { */ getRedirectResult() { - throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'getRedirectResult')); + throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'getRedirectResult')); } setPersistence() { - throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'setPersistence')); + throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'setPersistence')); } signInAndRetrieveDataWithCredential() { - throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'signInAndRetrieveDataWithCredential')); + throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'signInAndRetrieveDataWithCredential')); } signInWithPopup() { - throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'signInWithPopup')); + throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'signInWithPopup')); } signInWithRedirect() { - throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Auth, 'signInWithRedirect')); + throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'signInWithRedirect')); } } diff --git a/lib/modules/config/index.js b/lib/modules/config/index.js index 990d8e9a..ea3ab5cb 100644 --- a/lib/modules/config/index.js +++ b/lib/modules/config/index.js @@ -15,17 +15,20 @@ type NativeValue = { source: 'remoteConfigSourceRemote' | 'remoteConfigSourceDefault' | ' remoteConfigSourceStatic', } +export const MODULE_NAME = 'RNFirebaseRemoteConfig'; +export const NAMESPACE = 'config'; + /** * @class Config */ export default class RemoteConfig extends ModuleBase { - static _NAMESPACE = 'config'; - static _NATIVE_MODULE = 'RNFirebaseRemoteConfig'; - _developerModeEnabled: boolean; constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options); + super(firebaseApp, options, { + moduleName: MODULE_NAME, + namespace: NAMESPACE, + }); this._developerModeEnabled = false; } diff --git a/lib/modules/core/firebase-app.js b/lib/modules/core/firebase-app.js index 2711d4f1..ae340e44 100644 --- a/lib/modules/core/firebase-app.js +++ b/lib/modules/core/firebase-app.js @@ -8,19 +8,19 @@ import { SharedEventEmitter } from '../../utils/events'; import INTERNALS from '../../utils/internals'; import { isObject } from '../../utils'; -import AdMob from '../admob'; -import Auth from '../auth'; -import Analytics from '../analytics'; -import Config from '../config'; -import Crash from '../crash'; -import Crashlytics from '../fabric/crashlytics'; -import Database from '../database'; -import Firestore from '../firestore'; -import Links from '../links'; -import Messaging from '../messaging'; -import Performance from '../perf'; -import Storage from '../storage'; -import Utils from '../utils'; +import AdMob, { NAMESPACE as AdmobNamespace } from '../admob'; +import Auth, { NAMESPACE as AuthNamespace } from '../auth'; +import Analytics, { NAMESPACE as AnalyticsNamespace } from '../analytics'; +import Config, { NAMESPACE as ConfigNamespace } from '../config'; +import Crash, { NAMESPACE as CrashNamespace } from '../crash'; +import Crashlytics, { NAMESPACE as CrashlyticsNamespace } from '../fabric/crashlytics'; +import Database, { NAMESPACE as DatabaseNamespace } from '../database'; +import Firestore, { NAMESPACE as FirestoreNamespace } from '../firestore'; +import Links, { NAMESPACE as LinksNamespace } from '../links'; +import Messaging, { NAMESPACE as MessagingNamespace } from '../messaging'; +import Performance, { NAMESPACE as PerfNamespace } from '../perf'; +import Storage, { NAMESPACE as StorageNamespace } from '../storage'; +import Utils, { NAMESPACE as UtilsNamespace } from '../utils'; import type { FirebaseOptions, @@ -66,21 +66,21 @@ export default class FirebaseApp { } // modules - this.admob = APPS.appModule(this, 'admob', AdMob); - this.analytics = APPS.appModule(this, 'analytics', Analytics); - this.auth = APPS.appModule(this, 'auth', Auth); - this.config = APPS.appModule(this, 'config', Config); - this.crash = APPS.appModule(this, 'crash', Crash); - this.database = APPS.appModule(this, 'database', Database); + this.admob = APPS.appModule(this, AdmobNamespace, AdMob); + this.analytics = APPS.appModule(this, AnalyticsNamespace, Analytics); + this.auth = APPS.appModule(this, AuthNamespace, Auth); + this.config = APPS.appModule(this, ConfigNamespace, Config); + this.crash = APPS.appModule(this, CrashNamespace, Crash); + this.database = APPS.appModule(this, DatabaseNamespace, Database); this.fabric = { - crashlytics: APPS.appModule(this, 'crashlytics', Crashlytics), + crashlytics: APPS.appModule(this, CrashlyticsNamespace, Crashlytics), }; - this.firestore = APPS.appModule(this, 'firestore', Firestore); - this.links = APPS.appModule(this, 'links', Links); - this.messaging = APPS.appModule(this, 'messaging', Messaging); - this.perf = APPS.appModule(this, 'perf', Performance); - this.storage = APPS.appModule(this, 'storage', Storage); - this.utils = APPS.appModule(this, 'utils', Utils); + this.firestore = APPS.appModule(this, FirestoreNamespace, Firestore); + this.links = APPS.appModule(this, LinksNamespace, Links); + this.messaging = APPS.appModule(this, MessagingNamespace, Messaging); + this.perf = APPS.appModule(this, PerfNamespace, Performance); + this.storage = APPS.appModule(this, StorageNamespace, Storage); + this.utils = APPS.appModule(this, UtilsNamespace, Utils); this._extendedProps = {}; } @@ -89,13 +89,6 @@ export default class FirebaseApp { * @return {*} */ get name(): string { - if (this._name === INTERNALS.STRINGS.DEFAULT_APP_NAME) { - // ios and android firebase sdk's return different - // app names - so we just return what the web sdk - // would if it was default. - return '[DEFAULT]'; - } - return this._name; } @@ -138,7 +131,7 @@ export default class FirebaseApp { delete() { throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('app', 'delete')); // TODO only the ios sdk currently supports delete, add back in when android also supports it - // if (this._name === INTERNALS.STRINGS.DEFAULT_APP_NAME && this._nativeInitialized) { + // if (this._name === APPS.DEFAULT_APP_NAME && this._nativeInitialized) { // return Promise.reject( // new Error('Unable to delete the default native firebase app instance.'), // ); diff --git a/lib/modules/core/firebase.js b/lib/modules/core/firebase.js index 4dc60e88..7bd151b6 100644 --- a/lib/modules/core/firebase.js +++ b/lib/modules/core/firebase.js @@ -9,19 +9,19 @@ import INTERNALS from '../../utils/internals'; import FirebaseApp from './firebase-app'; // module imports -import AdMob, { statics as AdMobStatics } from '../admob'; -import Auth, { statics as AuthStatics } from '../auth'; -import Analytics, { statics as AnalyticsStatics } from '../analytics'; -import Config, { statics as ConfigStatics } from '../config'; -import Crash, { statics as CrashStatics } from '../crash'; -import Crashlytics, { statics as CrashlyticsStatics } from '../fabric/crashlytics'; -import Database, { statics as DatabaseStatics } from '../database'; -import Firestore, { statics as FirestoreStatics } from '../firestore'; -import Links, { statics as LinksStatics } from '../links'; -import Messaging, { statics as MessagingStatics } from '../messaging'; -import Performance, { statics as PerformanceStatics } from '../perf'; -import Storage, { statics as StorageStatics } from '../storage'; -import Utils, { statics as UtilsStatics } from '../utils'; +import { statics as AdMobStatics, MODULE_NAME as AdmobModuleName } from '../admob'; +import { statics as AuthStatics, MODULE_NAME as AuthModuleName } from '../auth'; +import { statics as AnalyticsStatics, MODULE_NAME as AnalyticsModuleName } from '../analytics'; +import { statics as ConfigStatics, MODULE_NAME as ConfigModuleName } from '../config'; +import { statics as CrashStatics, MODULE_NAME as CrashModuleName } from '../crash'; +import { statics as CrashlyticsStatics, MODULE_NAME as CrashlyticsModuleName } from '../fabric/crashlytics'; +import { statics as DatabaseStatics, MODULE_NAME as DatabaseModuleName } from '../database'; +import { statics as FirestoreStatics, MODULE_NAME as FirestoreModuleName } from '../firestore'; +import { statics as LinksStatics, MODULE_NAME as LinksModuleName } from '../links'; +import { statics as MessagingStatics, MODULE_NAME as MessagingModuleName } from '../messaging'; +import { statics as PerformanceStatics, MODULE_NAME as PerfModuleName } from '../perf'; +import { statics as StorageStatics, MODULE_NAME as StorageModuleName } from '../storage'; +import { statics as UtilsStatics, MODULE_NAME as UtilsModuleName } from '../utils'; import type { AdMobModule, @@ -64,21 +64,21 @@ class FirebaseCore { APPS.initializeNativeApps(); // modules - this.admob = APPS.moduleAndStatics('admob', AdMobStatics, AdMob); - this.analytics = APPS.moduleAndStatics('analytics', AnalyticsStatics, Analytics); - this.auth = APPS.moduleAndStatics('auth', AuthStatics, Auth); - this.config = APPS.moduleAndStatics('config', ConfigStatics, Config); - this.crash = APPS.moduleAndStatics('crash', CrashStatics, Crash); - this.database = APPS.moduleAndStatics('database', DatabaseStatics, Database); + this.admob = APPS.moduleAndStatics('admob', AdMobStatics, AdmobModuleName); + this.analytics = APPS.moduleAndStatics('analytics', AnalyticsStatics, AnalyticsModuleName); + this.auth = APPS.moduleAndStatics('auth', AuthStatics, AuthModuleName); + this.config = APPS.moduleAndStatics('config', ConfigStatics, ConfigModuleName); + this.crash = APPS.moduleAndStatics('crash', CrashStatics, CrashModuleName); + this.database = APPS.moduleAndStatics('database', DatabaseStatics, DatabaseModuleName); this.fabric = { - crashlytics: APPS.moduleAndStatics('crashlytics', CrashlyticsStatics, Crashlytics), + crashlytics: APPS.moduleAndStatics('crashlytics', CrashlyticsStatics, CrashlyticsModuleName), }; - this.firestore = APPS.moduleAndStatics('firestore', FirestoreStatics, Firestore); - this.links = APPS.moduleAndStatics('links', LinksStatics, Links); - this.messaging = APPS.moduleAndStatics('messaging', MessagingStatics, Messaging); - this.perf = APPS.moduleAndStatics('perf', PerformanceStatics, Performance); - this.storage = APPS.moduleAndStatics('storage', StorageStatics, Storage); - this.utils = APPS.moduleAndStatics('utils', UtilsStatics, Utils); + this.firestore = APPS.moduleAndStatics('firestore', FirestoreStatics, FirestoreModuleName); + this.links = APPS.moduleAndStatics('links', LinksStatics, LinksModuleName); + this.messaging = APPS.moduleAndStatics('messaging', MessagingStatics, MessagingModuleName); + this.perf = APPS.moduleAndStatics('perf', PerformanceStatics, PerfModuleName); + this.storage = APPS.moduleAndStatics('storage', StorageStatics, StorageModuleName); + this.utils = APPS.moduleAndStatics('utils', UtilsStatics, UtilsModuleName); } /** diff --git a/lib/modules/crash/index.js b/lib/modules/crash/index.js index 2844a65c..9d2a2042 100644 --- a/lib/modules/crash/index.js +++ b/lib/modules/crash/index.js @@ -7,12 +7,15 @@ import ModuleBase from '../../utils/ModuleBase'; import type FirebaseApp from '../core/firebase-app'; import type { FirebaseError } from '../../types'; -export default class Crash extends ModuleBase { - static _NAMESPACE = 'crash'; - static _NATIVE_MODULE = 'RNFirebaseCrash'; +export const MODULE_NAME = 'RNFirebaseCrash'; +export const NAMESPACE = 'crash'; +export default class Crash extends ModuleBase { constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options); + super(firebaseApp, options, { + moduleName: MODULE_NAME, + namespace: NAMESPACE, + }); } /** diff --git a/lib/modules/database/index.js b/lib/modules/database/index.js index 850f6152..cfac1094 100644 --- a/lib/modules/database/index.js +++ b/lib/modules/database/index.js @@ -15,19 +15,26 @@ const NATIVE_EVENTS = [ // 'database_server_offset', // TODO ]; +export const MODULE_NAME = 'RNFirebaseDatabase'; +export const NAMESPACE = 'database'; + /** * @class Database */ export default class Database extends ModuleBase { - static _NAMESPACE = 'database'; - static _NATIVE_MODULE = 'RNFirebaseDatabase'; - _offsetRef: Reference; _serverTimeOffset: number; _transactionHandler: TransactionHandler; constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, NATIVE_EVENTS); + super(firebaseApp, { + persistence: false, + ...options, + }, { + events: NATIVE_EVENTS, + moduleName: MODULE_NAME, + namespace: NAMESPACE, + }); this._transactionHandler = new TransactionHandler(this); if (this._options.persistence) { @@ -84,8 +91,8 @@ export const statics = { TIMESTAMP: NativeModules.RNFirebaseDatabase.serverValueTimestamp || { '.sv': 'timestamp' }, } : {}, enableLogging(enabled: boolean) { - if (NativeModules[Database._NATIVE_MODULE]) { - NativeModules[Database._NATIVE_MODULE].enableLogging(enabled); + if (NativeModules[MODULE_NAME]) { + NativeModules[MODULE_NAME].enableLogging(enabled); } }, }; diff --git a/lib/modules/database/reference.js b/lib/modules/database/reference.js index 43d61b9f..fbb2a7e2 100644 --- a/lib/modules/database/reference.js +++ b/lib/modules/database/reference.js @@ -18,11 +18,10 @@ import { generatePushID, } from '../../utils'; -import INTERNALS from '../../utils/internals'; +import SyncTree from '../../utils/SyncTree'; import type Database from './'; import type { DatabaseModifier, FirebaseError } from '../../types'; -import type SyncTree from '../../utils/SyncTree'; // track all event registrations by path let listeners = 0; @@ -537,7 +536,7 @@ export default class Reference extends ReferenceBase { * @return {string} */ _getRegistrationKey(eventType: string): string { - return `$${this._database._appName}$/${this.path}$${this._query.queryIdentifier()}$${listeners}$${eventType}`; + return `$${this._database.app.name}$/${this.path}$${this._query.queryIdentifier()}$${listeners}$${eventType}`; } /** @@ -548,7 +547,7 @@ export default class Reference extends ReferenceBase { * @private */ _getRefKey(): string { - return `$${this._database._appName}$/${this.path}$${this._query.queryIdentifier()}`; + return `$${this._database.app.name}$/${this.path}$${this._query.queryIdentifier()}`; } /** @@ -654,23 +653,23 @@ export default class Reference extends ReferenceBase { ref: this, path: this.path, key: this._getRefKey(), - appName: this._database._appName, + appName: this._database.app.name, eventRegistrationKey, }; - this._syncTree.addRegistration(registrationObj, _context ? callback.bind(_context) : callback); + SyncTree.addRegistration(registrationObj, _context ? callback.bind(_context) : callback); if (isFunction(cancelCallbackOrContext)) { // cancellations have their own separate registration // as these are one off events, and they're not guaranteed // to occur either, only happens on failure to register on native - this._syncTree.addRegistration( + SyncTree.addRegistration( { ref: this, once: true, path: this.path, key: this._getRefKey(), - appName: this._database._appName, + appName: this._database.app.name, eventType: `${eventType}$cancelled`, eventRegistrationKey: registrationCancellationKey, }, @@ -683,7 +682,7 @@ export default class Reference extends ReferenceBase { eventType, path: this.path, key: this._getRefKey(), - appName: this._database._appName, + appName: this._database.app.name, modifiers: this._query.getModifiers(), hasCancellationCallback: isFunction(cancelCallbackOrContext), registration: { @@ -721,7 +720,7 @@ export default class Reference extends ReferenceBase { if (!arguments.length) { // Firebase Docs: // if no eventType or callback is specified, all callbacks for the Reference will be removed. - return this._syncTree.removeListenersForRegistrations(this._syncTree.getRegistrationsByPath(this.path)); + return SyncTree.removeListenersForRegistrations(SyncTree.getRegistrationsByPath(this.path)); } /* @@ -742,29 +741,25 @@ export default class Reference extends ReferenceBase { // remove the callback. // Remove only a single registration if (eventType && originalCallback) { - const registration = this._syncTree.getOneByPathEventListener(this.path, eventType, originalCallback); + const registration = SyncTree.getOneByPathEventListener(this.path, eventType, originalCallback); if (!registration) return []; // remove the paired cancellation registration if any exist - this._syncTree.removeListenersForRegistrations([`${registration}$cancelled`]); + SyncTree.removeListenersForRegistrations([`${registration}$cancelled`]); // remove only the first registration to match firebase web sdk // call multiple times to remove multiple registrations - return this._syncTree.removeListenerRegistrations(originalCallback, [registration]); + return SyncTree.removeListenerRegistrations(originalCallback, [registration]); } // Firebase Docs: // If a callback is not specified, all callbacks for the specified eventType will be removed. - const registrations = this._syncTree.getRegistrationsByPathEvent(this.path, eventType); + const registrations = SyncTree.getRegistrationsByPathEvent(this.path, eventType); - this._syncTree.removeListenersForRegistrations( - this._syncTree.getRegistrationsByPathEvent(this.path, `${eventType}$cancelled`), + SyncTree.removeListenersForRegistrations( + SyncTree.getRegistrationsByPathEvent(this.path, `${eventType}$cancelled`), ); - return this._syncTree.removeListenersForRegistrations(registrations); - } - - get _syncTree(): SyncTree { - return INTERNALS.SyncTree; + return SyncTree.removeListenersForRegistrations(registrations); } } diff --git a/lib/modules/fabric/crashlytics/index.js b/lib/modules/fabric/crashlytics/index.js index 6ab1d9f9..5c55bb0c 100644 --- a/lib/modules/fabric/crashlytics/index.js +++ b/lib/modules/fabric/crashlytics/index.js @@ -6,12 +6,15 @@ import ModuleBase from '../../../utils/ModuleBase'; import type FirebaseApp from '../../core/firebase-app'; -export default class Crashlytics extends ModuleBase { - static _NAMESPACE = 'crashlytics'; - static _NATIVE_MODULE = 'RNFirebaseCrashlytics'; +export const MODULE_NAME = 'RNFirebaseCrashlytics'; +export const NAMESPACE = 'crashlytics'; +export default class Crashlytics extends ModuleBase { constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options); + super(firebaseApp, options, { + moduleName: MODULE_NAME, + namespace: NAMESPACE, + }); } /** diff --git a/lib/modules/firestore/index.js b/lib/modules/firestore/index.js index c3d3a0fb..ac78e497 100644 --- a/lib/modules/firestore/index.js +++ b/lib/modules/firestore/index.js @@ -39,17 +39,21 @@ const NATIVE_EVENTS = [ 'firestore_document_sync_event', ]; +export const MODULE_NAME = 'RNFirebaseFirestore'; +export const NAMESPACE = 'firestore'; + /** * @class Firestore */ export default class Firestore extends ModuleBase { - static _NAMESPACE = 'firestore'; - static _NATIVE_MODULE = 'RNFirebaseFirestore'; - _referencePath: Path; constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, NATIVE_EVENTS); + super(firebaseApp, options, { + events: NATIVE_EVENTS, + moduleName: MODULE_NAME, + namespace: NAMESPACE, + }); this._referencePath = new Path([]); SharedEventEmitter.addListener( @@ -108,7 +112,7 @@ export default class Firestore extends ModuleBase { } setLogLevel(): void { - throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(Firestore, 'setLogLevel')); + throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('firestore', 'setLogLevel')); } settings(): void { @@ -145,9 +149,9 @@ export default class Firestore extends ModuleBase { export const statics = { FieldValue, GeoPoint, - enableLogging(bool) { - if (NativeModules[Firestore._NATIVE_MODULE]) { - NativeModules[Firestore._NATIVE_MODULE].enableLogging(bool); + enableLogging(enabled: boolean) { + if (NativeModules[MODULE_NAME]) { + NativeModules[MODULE_NAME].enableLogging(enabled); } }, }; diff --git a/lib/modules/links/index.js b/lib/modules/links/index.js index fc36c1ae..411a2427 100644 --- a/lib/modules/links/index.js +++ b/lib/modules/links/index.js @@ -16,6 +16,9 @@ const NATIVE_EVENTS = [ EVENT_TYPE.Link, ]; +export const MODULE_NAME = 'RNFirebaseLinks'; +export const NAMESPACE = 'links'; + function validateParameters(parameters: Object): void { const suportedParametersObject = { dynamicLinkDomain: 'string', @@ -67,11 +70,12 @@ function checkForMandatoryParameters(parameters: Object): void { * @class Links */ export default class Links extends ModuleBase { - static _NAMESPACE = 'links'; - static _NATIVE_MODULE = 'RNFirebaseLinks'; - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, NATIVE_EVENTS); + super(firebaseApp, options, { + events: NATIVE_EVENTS, + moduleName: MODULE_NAME, + namespace: NAMESPACE, + }); } get EVENT_TYPE(): Object { diff --git a/lib/modules/messaging/index.js b/lib/modules/messaging/index.js index 091b5b05..ab365583 100644 --- a/lib/modules/messaging/index.js +++ b/lib/modules/messaging/index.js @@ -79,16 +79,19 @@ function finish(data) { } } +export const MODULE_NAME = 'RNFirebaseMessaging'; +export const NAMESPACE = 'messaging'; /** * @class Messaging */ export default class Messaging extends ModuleBase { - static _NAMESPACE = 'messaging'; - static _NATIVE_MODULE = 'RNFirebaseMessaging'; - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, NATIVE_EVENTS); + super(firebaseApp, options, { + events: NATIVE_EVENTS, + moduleName: MODULE_NAME, + namespace: NAMESPACE, + }); } get EVENT_TYPE(): Object { diff --git a/lib/modules/perf/index.js b/lib/modules/perf/index.js index 81d3a5d1..7ac349c3 100644 --- a/lib/modules/perf/index.js +++ b/lib/modules/perf/index.js @@ -7,12 +7,15 @@ import ModuleBase from '../../utils/ModuleBase'; import type FirebaseApp from '../core/firebase-app'; -export default class PerformanceMonitoring extends ModuleBase { - static _NAMESPACE = 'perf'; - static _NATIVE_MODULE = 'RNFirebasePerformance'; +export const MODULE_NAME = 'RNFirebasePerformance'; +export const NAMESPACE = 'perf'; +export default class PerformanceMonitoring extends ModuleBase { constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options); + super(firebaseApp, options, { + moduleName: MODULE_NAME, + namespace: NAMESPACE, + }); } /** diff --git a/lib/modules/storage/index.js b/lib/modules/storage/index.js index 358f7594..77f0400f 100644 --- a/lib/modules/storage/index.js +++ b/lib/modules/storage/index.js @@ -18,17 +18,21 @@ const NATIVE_EVENTS = [ 'storage_error', ]; -export default class Storage extends ModuleBase { - static _NAMESPACE = 'storage'; - static _NATIVE_MODULE = 'RNFirebaseStorage'; +export const MODULE_NAME = 'RNFirebaseStorage'; +export const NAMESPACE = 'storage'; +export default class Storage extends ModuleBase { /** * * @param firebaseApp * @param options */ constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, NATIVE_EVENTS); + super(firebaseApp, options, { + events: NATIVE_EVENTS, + moduleName: MODULE_NAME, + namespace: NAMESPACE, + }); SharedEventEmitter.addListener( getAppEventName(this, 'storage_event'), diff --git a/lib/modules/utils/index.js b/lib/modules/utils/index.js index e72f9beb..9e3cc5db 100644 --- a/lib/modules/utils/index.js +++ b/lib/modules/utils/index.js @@ -2,7 +2,6 @@ import { NativeModules } from 'react-native'; // import { version as ReactVersion } from 'react'; // import ReactNativeVersion from 'react-native/Libraries/Core/ReactNativeVersion'; - import INTERNALS from '../../utils/internals'; import { isIOS } from '../../utils'; import ModuleBase from '../../utils/ModuleBase'; @@ -18,18 +17,17 @@ type GoogleApiAvailabilityType = { error?: string } -export default class RNFirebaseUtils extends ModuleBase { - static _NAMESPACE = 'utils'; - static _NATIVE_DISABLED = true; - static _NATIVE_MODULE = 'RNFirebaseUtils'; +export const MODULE_NAME = 'RNFirebaseUtils'; +export const NAMESPACE = 'utils'; +export default class RNFirebaseUtils extends ModuleBase { /** * */ checkPlayServicesAvailability() { if (isIOS) return null; - const code = this.playServicesAvailability.code; + const { code } = this.playServicesAvailability; if (!this.playServicesAvailability.isAvailable) { if (INTERNALS.OPTIONS.promptOnMissingPlayServices && this.playServicesAvailability.isUserResolvableError) { @@ -72,30 +70,6 @@ export default class RNFirebaseUtils extends ModuleBase { INTERNALS.OPTIONS.logLevel = booleanOrDebugString; } - - /** - * Returns an array of all current database registrations id strings - */ - get databaseRegistrations(): Array { - return Object.keys(INTERNALS.SyncTree._reverseLookup); - } - - /** - * Call with a registration id string to get the details off this reg - */ - get getDatabaseRegistrationDetails(): Function { - return INTERNALS.SyncTree.getRegistration.bind(INTERNALS.SyncTree); - } - - /** - * Accepts an array or a single string of registration ids. - * This will remove the refs on both the js and native sides and their listeners. - * @return {function(this:T)} - */ - get removeDatabaseRegistration(): Function { - return INTERNALS.SyncTree.removeListenersForRegistrations.bind(INTERNALS.SyncTree); - } - /** * Returns props from the android GoogleApiAvailability sdk * @android @@ -126,7 +100,6 @@ export default class RNFirebaseUtils extends ModuleBase { export const statics = { - DEFAULT_APP_NAME: INTERNALS.STRINGS.DEFAULT_APP_NAME, // VERSIONS: { // react: ReactVersion, // 'react-native': Object.values(ReactNativeVersion.version).slice(0, 3).join('.'), diff --git a/lib/types/index.js b/lib/types/index.js index d002a2a7..31588854 100644 --- a/lib/types/index.js +++ b/lib/types/index.js @@ -40,7 +40,18 @@ export type FirebaseError = { export type FirebaseModule = $Subtype; -export type FirebaseModuleName = 'admob' | 'analytics' | 'auth' | 'config' | 'crash' +export type FirebaseModuleConfig = { + events?: string[], + moduleName: FirebaseModuleName, + namespace: FirebaseNamespace, +} + +export type FirebaseModuleName = 'RNFirebaseAdmob' | 'RNFirebaseAnalytics' | 'RNFirebaseAuth' + | 'RNFirebaseRemoteConfig' | 'RNFirebaseCrash' | 'RNFirebaseCrashlytics' | 'RNFirebaseDatabase' + | 'RNFirebaseFirestore' | 'RNFirebaseLinks' | 'RNFirebaseMessaging' | 'RNFirebasePerformance' + | 'RNFirebaseStorage' | 'RNFirebaseUtils'; + +export type FirebaseNamespace = 'admob' | 'analytics' | 'auth' | 'config' | 'crash' | 'crashlytics' | 'database' | 'firestore' | 'links' | 'messaging' | 'perf' | 'storage' | 'utils'; diff --git a/lib/utils/ModuleBase.js b/lib/utils/ModuleBase.js index cb0a974f..c93ba6ba 100644 --- a/lib/utils/ModuleBase.js +++ b/lib/utils/ModuleBase.js @@ -1,27 +1,16 @@ /** * @flow */ -import { initialiseNativeModuleEventEmitter } from './events'; -import { getNativeModule, initialiseNativeModule } from './native'; +import { initialiseLogger } from './log'; +import { initialiseNativeModule } from './native'; import type FirebaseApp from '../modules/core/firebase-app'; -import type { FirebaseModuleName } from '../types'; - -const DEFAULTS = { - Database: { - persistence: false, - }, -}; +import type { FirebaseModuleConfig } from '../types'; export default class ModuleBase { - _native: Object; - _module: string; - _options: Object; - _appName: string; - _namespace: string; _firebaseApp: FirebaseApp; - static _NAMESPACE: FirebaseModuleName; - static _NATIVE_MODULE: string; + _native: Object; + _options: Object; /** * @@ -29,19 +18,21 @@ export default class ModuleBase { * @param options * @param withEventEmitter */ - constructor(firebaseApp: FirebaseApp, options: Object, events: string[] = []) { - this._module = this.constructor._NATIVE_MODULE.replace('RNFirebase', ''); + constructor(firebaseApp: FirebaseApp, options: Object, config: FirebaseModuleConfig) { + if (!config.moduleName) { + throw new Error('Missing module name'); + } + if (!config.namespace) { + throw new Error('Missing namespace'); + } + const { moduleName } = config; this._firebaseApp = firebaseApp; - this._appName = firebaseApp._name; - this._namespace = `${this._appName}:${this._module}`; - this._options = Object.assign({}, DEFAULTS[this._module] || {}, options); + this._options = options; // check if native module exists as all native - initialiseNativeModule(this); - // TODO: Get rid of - this._native = getNativeModule(this); - - initialiseNativeModuleEventEmitter(this, events); + // TODO: Get rid of this._native and change to using getNativeModule instead? + this._native = initialiseNativeModule(this, config); + initialiseLogger(this, `${firebaseApp.name}:${moduleName.replace('RNFirebase', '')}`); } /** diff --git a/lib/utils/SyncTree.js b/lib/utils/SyncTree.js index a1849bb3..c4213365 100644 --- a/lib/utils/SyncTree.js +++ b/lib/utils/SyncTree.js @@ -1,7 +1,7 @@ /** * @flow */ -import { NativeEventEmitter } from 'react-native'; +import { NativeEventEmitter, NativeModules } from 'react-native'; import { SharedEventEmitter } from './events'; import DatabaseSnapshot from '../modules/database/snapshot'; @@ -23,21 +23,21 @@ type Registration = { * Internally used to manage firebase database realtime event * subscriptions and keep the listeners in sync in js vs native. */ -export default class SyncTree { - _databaseNative: Object; +class SyncTree { _nativeEmitter: NativeEventEmitter; _reverseLookup: { [string]: Registration }; - _tree: { [string]: { [string]: Array }}; + _tree: { [string]: { [string]: { [string]: Function }}}; - constructor(databaseNative: Object) { + constructor() { this._tree = {}; this._reverseLookup = {}; - this._databaseNative = databaseNative; - this._nativeEmitter = new NativeEventEmitter(databaseNative); - this._nativeEmitter.addListener( - 'database_sync_event', - this._handleSyncEvent.bind(this), - ); + if (NativeModules.RNFirebaseDatabase) { + this._nativeEmitter = new NativeEventEmitter(NativeModules.RNFirebaseDatabase); + this._nativeEmitter.addListener( + 'database_sync_event', + this._handleSyncEvent.bind(this), + ); + } } /** @@ -71,7 +71,7 @@ export default class SyncTree { // notify native that the registration // no longer exists so it can remove // the native listeners - return this._databaseNative.off(key, eventRegistrationKey); + return NativeModules.RNFirebaseDatabase.off(key, eventRegistrationKey); } const { snapshot, previousChildName } = event.data; @@ -287,7 +287,7 @@ export default class SyncTree { // automatically unsubscribed on native when the first event is sent const registrationObj = this._reverseLookup[registration]; if (registrationObj && !once) { - this._databaseNative.off(registrationObj.key, registration); + NativeModules.RNFirebaseDatabase.off(registrationObj.key, registration); } delete this._tree[path][eventType][registration]; @@ -311,3 +311,5 @@ export default class SyncTree { }; } } + +export default new SyncTree(); diff --git a/lib/utils/apps.js b/lib/utils/apps.js index 2d39e0f6..fcef8fa1 100644 --- a/lib/utils/apps.js +++ b/lib/utils/apps.js @@ -10,6 +10,7 @@ import type { FirebaseModule, FirebaseModuleAndStatics, FirebaseModuleName, + FirebaseNamespace, FirebaseOptions, FirebaseStatics, } from '../types'; @@ -18,10 +19,13 @@ const FirebaseCoreModule = NativeModules.RNFirebase; const APPS: { [string]: FirebaseApp } = {}; const APP_MODULES: { [FirebaseApp]: { [string]: FirebaseModule }} = {}; +const DEFAULT_APP_NAME = '[DEFAULT]'; export default { + DEFAULT_APP_NAME, + app(name?: string): FirebaseApp { - const _name = name ? name.toUpperCase() : INTERNALS.STRINGS.DEFAULT_APP_NAME; + const _name = name ? name.toUpperCase() : DEFAULT_APP_NAME; const app = APPS[_name]; if (!app) throw new Error(INTERNALS.STRINGS.ERROR_APP_NOT_INIT(_name)); return app; @@ -38,22 +42,22 @@ export default { * @return {function()} * @private */ - appModule(firebaseApp: FirebaseApp, moduleName: FirebaseModuleName, InstanceClass: Class): () => FirebaseModule { + appModule(firebaseApp: FirebaseApp, namespace: FirebaseNamespace, InstanceClass: Class): () => FirebaseModule { return (): M => { if (!APP_MODULES[firebaseApp]) { APP_MODULES[firebaseApp] = {}; } - if (isAndroid && moduleName !== 'utils' && !INTERNALS.FLAGS.checkedPlayServices) { + if (isAndroid && namespace !== 'utils' && !INTERNALS.FLAGS.checkedPlayServices) { INTERNALS.FLAGS.checkedPlayServices = true; this.utils().checkPlayServicesAvailability(); } - if (!APP_MODULES[firebaseApp][moduleName]) { - APP_MODULES[firebaseApp][moduleName] = new InstanceClass(firebaseApp, this._options); + if (!APP_MODULES[firebaseApp][namespace]) { + APP_MODULES[firebaseApp][namespace] = new InstanceClass(firebaseApp, firebaseApp.options); } - return APP_MODULES[firebaseApp][moduleName]; + return APP_MODULES[firebaseApp][namespace]; }; }, @@ -80,7 +84,7 @@ export default { throw new Error(INTERNALS.STRINGS.ERROR_INIT_STRING_NAME); } - const _name = (name || INTERNALS.STRINGS.DEFAULT_APP_NAME).toUpperCase(); + const _name = (name || DEFAULT_APP_NAME).toUpperCase(); // return an existing app if found // todo in v4 remove deprecation and throw an error @@ -143,25 +147,25 @@ export default { * @param InstanceClass * @return {function(FirebaseApp=)} */ - moduleAndStatics(moduleName: FirebaseModuleName, statics: S, InstanceClass: Class): FirebaseModuleAndStatics { + moduleAndStatics(namespace: FirebaseNamespace, statics: S, moduleName: FirebaseModuleName): FirebaseModuleAndStatics { const getModule = (app?: FirebaseApp): FirebaseModule => { let firebaseApp = app; // throw an error if it's not a valid app instance - if (firebaseApp && !(firebaseApp instanceof FirebaseApp)) throw new Error(INTERNALS.STRINGS.ERROR_NOT_APP(moduleName)); + if (firebaseApp && !(firebaseApp instanceof FirebaseApp)) throw new Error(INTERNALS.STRINGS.ERROR_NOT_APP(namespace)); // default to the 'DEFAULT' app if no arg provided - will throw an error // if default app not initialized - else if (!firebaseApp) firebaseApp = this.app(INTERNALS.STRINGS.DEFAULT_APP_NAME); - if (moduleName === 'crashlytics') { - return firebaseApp.fabric[moduleName](); + else if (!firebaseApp) firebaseApp = this.app(DEFAULT_APP_NAME); + if (namespace === 'crashlytics') { + return firebaseApp.fabric[namespace](); } - const module = firebaseApp[moduleName]; + const module = firebaseApp[namespace]; return module(); }; return Object.assign(getModule, statics, { - nativeModuleExists: !!NativeModules[InstanceClass._NATIVE_MODULE], + nativeModuleExists: !!NativeModules[moduleName], }); }, }; diff --git a/lib/utils/events.js b/lib/utils/events.js index 90be83c1..659be82b 100644 --- a/lib/utils/events.js +++ b/lib/utils/events.js @@ -1,11 +1,11 @@ /** * @flow */ -import { NativeEventEmitter } from 'react-native'; +import { NativeEventEmitter, NativeModules } from 'react-native'; import EventEmitter from './emitter/EventEmitter'; -import { getRawNativeModule } from './native'; import type ModuleBase from './ModuleBase'; +import type { FirebaseModuleConfig, FirebaseModuleName } from '../types'; const NATIVE_EMITTERS: { [string]: NativeEventEmitter } = {}; const NATIVE_SUBSCRIPTIONS: { [string]: boolean } = {}; @@ -16,9 +16,9 @@ export const getAppEventName = (module: ModuleBase, eventName: string): string = return `${module._firebaseApp._name}-${eventName}`; }; -const getNativeEmitter = (module: ModuleBase): NativeEventEmitter => { - const name = `${module._appName}-${module._module}`; - const nativeModule = getRawNativeModule(module); +const getNativeEmitter = (moduleName: FirebaseModuleName, module: ModuleBase): NativeEventEmitter => { + const name = `${module.app.name}-${moduleName}`; + const nativeModule = NativeModules[moduleName]; if (!NATIVE_EMITTERS[name]) { NATIVE_EMITTERS[name] = new NativeEventEmitter(nativeModule); } @@ -35,9 +35,9 @@ const getNativeEmitter = (module: ModuleBase): NativeEventEmitter => { * @param eventName * @private */ -const subscribeToNativeModuleEvents = (module: ModuleBase, eventName: string): void => { +const subscribeToNativeModuleEvents = (moduleName: FirebaseModuleName, module: ModuleBase, eventName: string): void => { if (!NATIVE_SUBSCRIPTIONS[eventName]) { - const nativeEmitter = getNativeEmitter(module); + const nativeEmitter = getNativeEmitter(moduleName, module); nativeEmitter.addListener(eventName, (event) => { if (event.appName) { // native event has an appName property - auto prefix and internally emit @@ -52,10 +52,11 @@ const subscribeToNativeModuleEvents = (module: ModuleBase, eventName: string): v } }; -export const initialiseNativeModuleEventEmitter = (module: ModuleBase, events: string[]): void => { +export const initialiseNativeModuleEventEmitter = (module: ModuleBase, config: FirebaseModuleConfig): void => { + const { events, moduleName } = config; if (events && events.length) { for (let i = 0, len = events.length; i < len; i++) { - subscribeToNativeModuleEvents(module, events[i]); + subscribeToNativeModuleEvents(moduleName, module, events[i]); } } }; diff --git a/lib/utils/internals.js b/lib/utils/internals.js index 53bbc73c..907c63da 100644 --- a/lib/utils/internals.js +++ b/lib/utils/internals.js @@ -1,12 +1,7 @@ /** * @flow */ -import { Platform, NativeModules } from 'react-native'; - -import ModuleBase from './ModuleBase'; -import SyncTree from './SyncTree'; - -const DEFAULT_APP_NAME = Platform.OS === 'ios' ? '__FIRAPP_DEFAULT' : '[DEFAULT]'; +import { Platform } from 'react-native'; const NAMESPACE_PODS = { admob: 'Firebase/AdMob', @@ -186,8 +181,8 @@ export default { /** * @return {string} */ - ERROR_UNSUPPORTED_MODULE_METHOD(module: Class, method: string) { - return `firebase.${module._NAMESPACE}().${method}() is unsupported by the native Firebase SDKs.`; + ERROR_UNSUPPORTED_MODULE_METHOD(namespace: string, method: string) { + return `firebase.${namespace}().${method}() is unsupported by the native Firebase SDKs.`; }, @@ -214,10 +209,5 @@ export default { 'For more information on how to resolve this issue, configure Play Services checks or for guides on how to validate Play Services on your users devices see the link below:' + '\r\n\r\nhttp://invertase.link/play-services'; }, - - - DEFAULT_APP_NAME, }, - - SyncTree: NativeModules.RNFirebaseDatabase ? new SyncTree(NativeModules.RNFirebaseDatabase) : null, }; diff --git a/lib/utils/log.js b/lib/utils/log.js index 73f5f83d..e16eca99 100644 --- a/lib/utils/log.js +++ b/lib/utils/log.js @@ -14,11 +14,12 @@ import type ModuleBase from './ModuleBase'; const NATIVE_LOGGERS: { [ModuleBase]: Object } = {}; -export const getLogger = (module: ModuleBase) => { +export const getLogger = (module: ModuleBase) => NATIVE_LOGGERS[module]; + +export const initialiseLogger = (module: ModuleBase, logNamespace: string) => { if (!NATIVE_LOGGERS[module]) { - NATIVE_LOGGERS[module] = require('bows')(`🔥 ${module._namespace.toUpperCase()}`); + NATIVE_LOGGERS[module] = require('bows')(`🔥 ${logNamespace.toUpperCase()}`); } - return NATIVE_LOGGERS[module]; }; export default class Log { diff --git a/lib/utils/native.js b/lib/utils/native.js index a6ff5926..d6404a47 100644 --- a/lib/utils/native.js +++ b/lib/utils/native.js @@ -2,20 +2,21 @@ * @flow */ import { NativeModules } from 'react-native'; +import { initialiseNativeModuleEventEmitter } from './events'; import INTERNALS from './internals'; import type ModuleBase from './ModuleBase'; +import type { FirebaseModuleConfig } from '../types'; // Firebase Native SDKs that support multiple app instances const MULTI_APP_MODULES = [ - 'auth', - 'database', - 'firestore', - 'storage', + 'RNFirebaseAuth', + 'RNFirebaseDatabase', + 'RNFirebaseFirestore', + 'RNFirebaseStorage', ]; const NATIVE_MODULES: { [ModuleBase]: Object } = {}; -const RAW_NATIVE_MODULES: { [ModuleBase]: Object } = {}; /** * Prepends appName arg to all native method calls @@ -40,23 +41,23 @@ export const getNativeModule = (module: ModuleBase): Object => { return NATIVE_MODULES[module]; }; -export const getRawNativeModule = (module: ModuleBase): Object => { - return RAW_NATIVE_MODULES[module]; -}; +export const initialiseNativeModule = (module: ModuleBase, config: FirebaseModuleConfig): Object => { + const { moduleName, namespace } = config; + const nativeModule = NativeModules[moduleName]; -export const initialiseNativeModule = (module: ModuleBase): void => { - const nativeModule = NativeModules[module.constructor._NATIVE_MODULE]; - - if (!nativeModule && !module.constructor._NATIVE_DISABLED) { - throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(module.constructor._NAMESPACE, module.constructor._NATIVE_MODULE)); + if (!nativeModule && namespace !== 'utils') { + throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(namespace, moduleName)); } // used by the modules that extend ModuleBase // to access their native module counterpart - RAW_NATIVE_MODULES[module] = nativeModule; - if (!MULTI_APP_MODULES.includes(module._module.toLowerCase())) { + if (!MULTI_APP_MODULES.includes(moduleName)) { NATIVE_MODULES[module] = nativeModule; } else { - NATIVE_MODULES[module] = nativeWithApp(module._appName, nativeModule); + NATIVE_MODULES[module] = nativeWithApp(module.app.name, nativeModule); } + + initialiseNativeModuleEventEmitter(module, config); + + return NATIVE_MODULES[module]; }; diff --git a/tests/src/tests/core/coreTests.js b/tests/src/tests/core/coreTests.js index b7e971a4..5134dcbe 100644 --- a/tests/src/tests/core/coreTests.js +++ b/tests/src/tests/core/coreTests.js @@ -53,7 +53,7 @@ function coreTests({ describe, it }) { it('it should provide an array of apps', () => { should.equal(!!RNFirebase.apps.length, true); - should.equal(RNFirebase.apps.includes(RNFirebase.app(RNFirebase.utils.DEFAULT_APP_NAME)), true); + should.equal(RNFirebase.apps.includes(RNFirebase.app('[DEFAULT]')), true); return Promise.resolve(); }); From a80748bfbff3012a9e4f9ffe56c97e6bd7e11e85 Mon Sep 17 00:00:00 2001 From: Krystof Celba Date: Thu, 4 Jan 2018 03:39:10 +0100 Subject: [PATCH 50/56] [typings][typescript] Add missing types for Crashlytics --- lib/index.d.ts | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/lib/index.d.ts b/lib/index.d.ts index 688dd9bc..1eff94bf 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -64,6 +64,10 @@ declare module "react-native-firebase" { */ crash(): RNFirebase.crash.Crash; + static fabric: { + crashlytics(): RNFirebase.crashlytics.Crashlytics; + }; + apps: Array; googleApiAvailability: RNFirebase.GoogleApiAvailabilityType; @@ -846,5 +850,50 @@ declare module "react-native-firebase" { [key: string]: any; } } + + namespace crashlytics { + + interface Crashlytics { + /** + * Forces a crash. Useful for testing your application is set up correctly. + */ + crash(): void; + + /** + * Logs a message that will appear in any subsequent crash reports. + */ + log(message: string): void; + + /** + * Logs a non fatal exception. + */ + recordError(code: number, message: string): void; + + /** + * Set a boolean value to show alongside any subsequent crash reports. + */ + setBoolValue(key: string, value: boolean): void; + + /** + * Set a float value to show alongside any subsequent crash reports. + */ + setFloatValue(key: string, value: number): void; + + /** + * Set an integer value to show alongside any subsequent crash reports. + */ + setIntValue(key: string, value: number): void; + + /** + * Set a string value to show alongside any subsequent crash reports. + */ + setStringValue(key: string, value: string): void; + + /** + * Set the user ID to show alongside any subsequent crash reports. + */ + setUserIdentifier(userId: string): void; + } + } } } From 80cb54ee6d79e36b783de54b626ffd50fad6a971 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 5 Jan 2018 17:20:02 +0000 Subject: [PATCH 51/56] [internals][types] Last part of internal refactor; Got rid of remaining flow errors --- .flowconfig | 3 +- lib/modules/admob/index.js | 11 +++-- lib/modules/analytics/index.js | 25 +++++----- lib/modules/auth/ConfirmationResult.js | 3 +- lib/modules/auth/PhoneAuthListener.js | 14 ++++-- lib/modules/auth/User.js | 25 +++++----- lib/modules/auth/index.js | 37 +++++++------- lib/modules/config/index.js | 29 +++++------ lib/modules/core/firebase-app.js | 5 +- lib/modules/core/firebase.js | 8 +-- lib/modules/crash/index.js | 17 ++++--- lib/modules/database/index.js | 22 ++++----- lib/modules/database/reference.js | 52 +++++++++++--------- lib/modules/database/transaction.js | 29 +++++------ lib/modules/fabric/crashlytics/index.js | 23 ++++----- lib/modules/firestore/CollectionReference.js | 9 ++-- lib/modules/firestore/DocumentReference.js | 40 ++++++++++----- lib/modules/firestore/Query.js | 48 ++++++++++++------ lib/modules/firestore/WriteBatch.js | 4 +- lib/modules/firestore/index.js | 6 +-- lib/modules/links/index.js | 15 +++--- lib/modules/messaging/index.js | 39 ++++++++------- lib/modules/perf/Trace.js | 11 +++-- lib/modules/perf/index.js | 9 ++-- lib/modules/storage/index.js | 19 +++---- lib/modules/storage/reference.js | 15 +++--- lib/modules/utils/index.js | 16 +++--- lib/utils/ModuleBase.js | 27 +++++----- lib/utils/ReferenceBase.js | 7 +-- lib/utils/SyncTree.js | 33 +++++++------ lib/utils/apps.js | 44 +++++++++-------- lib/utils/events.js | 2 +- lib/utils/index.js | 8 +-- lib/utils/internals.js | 8 ++- lib/utils/log.js | 1 + 35 files changed, 358 insertions(+), 306 deletions(-) diff --git a/.flowconfig b/.flowconfig index 96622d4e..2130616f 100644 --- a/.flowconfig +++ b/.flowconfig @@ -50,7 +50,7 @@ module.system=haste emoji=true -munge_underscores=false +munge_underscores=true module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' @@ -69,6 +69,7 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-6]\\|[1 suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError +suppress_comment=\\(.\\|\n\\)*\\$FlowBug.* unsafe.enable_getters_and_setters=true diff --git a/lib/modules/admob/index.js b/lib/modules/admob/index.js index 8a81f873..84879f18 100644 --- a/lib/modules/admob/index.js +++ b/lib/modules/admob/index.js @@ -4,6 +4,7 @@ */ import { SharedEventEmitter } from '../../utils/events'; import { getLogger } from '../../utils/log'; +import { getNativeModule } from '../../utils/native'; import ModuleBase from '../../utils/ModuleBase'; import Interstitial from './Interstitial'; @@ -18,7 +19,7 @@ import EventTypes, { RewardedVideoEventTypes, } from './EventTypes'; -import type FirebaseApp from '../core/firebase-app'; +import type App from '../core/firebase-app'; type NativeEvent = { adUnit: string, @@ -38,8 +39,8 @@ export default class AdMob extends ModuleBase { _appId: ?string; _initialized: boolean; - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, { + constructor(app: App) { + super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, namespace: NAMESPACE, @@ -80,7 +81,7 @@ export default class AdMob extends ModuleBase { } else { this._initialized = true; this._appId = appId; - this._native.initialize(appId); + getNativeModule(this).initialize(appId); } } @@ -89,7 +90,7 @@ export default class AdMob extends ModuleBase { getLogger(this).warn('AdMob needs to be initialized before opening the dev menu!'); } else { getLogger(this).info('Opening debug menu'); - this._native.openDebugMenu(this._appId); + getNativeModule(this).openDebugMenu(this._appId); } } diff --git a/lib/modules/analytics/index.js b/lib/modules/analytics/index.js index dbff883c..44d8464f 100644 --- a/lib/modules/analytics/index.js +++ b/lib/modules/analytics/index.js @@ -2,9 +2,10 @@ * @flow * Analytics representation wrapper */ -import ModuleBase from './../../utils/ModuleBase'; +import ModuleBase from '../../utils/ModuleBase'; +import { getNativeModule } from '../../utils/native'; -import type FirebaseApp from '../core/firebase-app'; +import type App from '../core/firebase-app'; const AlphaNumericUnderscore = /^[a-zA-Z0-9_]+$/; @@ -28,8 +29,8 @@ export const MODULE_NAME = 'RNFirebaseAnalytics'; export const NAMESPACE = 'analytics'; export default class Analytics extends ModuleBase { - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, { + constructor(app: App) { + super(app, { moduleName: MODULE_NAME, namespace: NAMESPACE, }); @@ -60,7 +61,7 @@ export default class Analytics extends ModuleBase { // types are supported. String parameter values can be up to 36 characters long. The "firebase_" // prefix is reserved and should not be used for parameter names. - this._native.logEvent(name, params); + getNativeModule(this).logEvent(name, params); } /** @@ -68,7 +69,7 @@ export default class Analytics extends ModuleBase { * @param enabled */ setAnalyticsCollectionEnabled(enabled: boolean): void { - this._native.setAnalyticsCollectionEnabled(enabled); + getNativeModule(this).setAnalyticsCollectionEnabled(enabled); } /** @@ -77,7 +78,7 @@ export default class Analytics extends ModuleBase { * @param screenClassOverride */ setCurrentScreen(screenName: string, screenClassOverride: string): void { - this._native.setCurrentScreen(screenName, screenClassOverride); + getNativeModule(this).setCurrentScreen(screenName, screenClassOverride); } /** @@ -85,7 +86,7 @@ export default class Analytics extends ModuleBase { * @param milliseconds */ setMinimumSessionDuration(milliseconds: number = 10000): void { - this._native.setMinimumSessionDuration(milliseconds); + getNativeModule(this).setMinimumSessionDuration(milliseconds); } /** @@ -93,7 +94,7 @@ export default class Analytics extends ModuleBase { * @param milliseconds */ setSessionTimeoutDuration(milliseconds: number = 1800000): void { - this._native.setSessionTimeoutDuration(milliseconds); + getNativeModule(this).setSessionTimeoutDuration(milliseconds); } /** @@ -101,7 +102,7 @@ export default class Analytics extends ModuleBase { * @param id */ setUserId(id: string): void { - this._native.setUserId(id); + getNativeModule(this).setUserId(id); } /** @@ -110,7 +111,7 @@ export default class Analytics extends ModuleBase { * @param value */ setUserProperty(name: string, value: string): void { - this._native.setUserProperty(name, value); + getNativeModule(this).setUserProperty(name, value); } /** @@ -120,7 +121,7 @@ export default class Analytics extends ModuleBase { */ setUserProperties(object: Object): void { for (const property of Object.keys(object)) { - this._native.setUserProperty(property, object[property]); + getNativeModule(this).setUserProperty(property, object[property]); } } } diff --git a/lib/modules/auth/ConfirmationResult.js b/lib/modules/auth/ConfirmationResult.js index a2b80b72..340be9cb 100644 --- a/lib/modules/auth/ConfirmationResult.js +++ b/lib/modules/auth/ConfirmationResult.js @@ -2,6 +2,7 @@ * @flow * ConfirmationResult representation wrapper */ +import { getNativeModule } from '../../utils/native'; import type Auth from './'; import type User from './User'; @@ -25,7 +26,7 @@ export default class ConfirmationResult { * @return {*} */ confirm(verificationCode: string): Promise { - return this._auth._interceptUserValue(this._auth._native._confirmVerificationCode(verificationCode)); + return this._auth._interceptUserValue(getNativeModule(this._auth)._confirmVerificationCode(verificationCode)); } get verificationId(): string | null { diff --git a/lib/modules/auth/PhoneAuthListener.js b/lib/modules/auth/PhoneAuthListener.js index 9503d8cf..648b249e 100644 --- a/lib/modules/auth/PhoneAuthListener.js +++ b/lib/modules/auth/PhoneAuthListener.js @@ -1,7 +1,8 @@ // @flow import INTERNALS from '../../utils/internals'; import { SharedEventEmitter } from '../../utils/events'; -import { generatePushID, isFunction, isAndroid, isIOS, isString, nativeToJSError } from './../../utils'; +import { generatePushID, isFunction, isAndroid, isIOS, isString, nativeToJSError } from '../../utils'; +import { getNativeModule } from '../../utils/native'; import type Auth from './'; @@ -20,7 +21,7 @@ type PhoneAuthError = { }; export default class PhoneAuthListener { - _auth: Object; + _auth: Auth; _timeout: number; _publicEvents: Object; _internalEvents: Object; @@ -69,7 +70,7 @@ export default class PhoneAuthListener { // start verification flow natively if (isAndroid) { - this._auth._native.verifyPhoneNumber( + getNativeModule(this._auth).verifyPhoneNumber( phoneNumber, this._phoneAuthRequestKey, this._timeout, @@ -77,7 +78,7 @@ export default class PhoneAuthListener { } if (isIOS) { - this._auth._native.verifyPhoneNumber( + getNativeModule(this._auth).verifyPhoneNumber( phoneNumber, this._phoneAuthRequestKey, ); @@ -93,6 +94,7 @@ export default class PhoneAuthListener { for (let i = 0, len = events.length; i < len; i++) { const type = events[i]; + // $FlowBug: Flow doesn't support indexable signatures on classes: https://github.com/facebook/flow/issues/1323 SharedEventEmitter.once(this._internalEvents[type], this[`_${type}Handler`].bind(this)); } } @@ -121,7 +123,7 @@ export default class PhoneAuthListener { * @private */ _emitToErrorCb(snapshot) { - const error = snapshot.error; + const { error } = snapshot; if (this._reject) this._reject(error); SharedEventEmitter.emit(this._publicEvents.error, error); } @@ -296,6 +298,7 @@ export default class PhoneAuthListener { */ then(fn: () => PhoneAuthSnapshot) { this._promiseDeferred(); + // $FlowFixMe: Unsure how to annotate `bind` here if (this._promise) return this._promise.then.bind(this._promise)(fn); return undefined; // will never get here - just to keep flow happy } @@ -306,6 +309,7 @@ export default class PhoneAuthListener { */ catch(fn: () => Error) { this._promiseDeferred(); + // $FlowFixMe: Unsure how to annotate `bind` here if (this._promise) return this._promise.catch.bind(this._promise)(fn); return undefined; // will never get here - just to keep flow happy } diff --git a/lib/modules/auth/User.js b/lib/modules/auth/User.js index aa6d5903..b357915e 100644 --- a/lib/modules/auth/User.js +++ b/lib/modules/auth/User.js @@ -1,8 +1,9 @@ -/** +getNativeModule(this._auth)/** * @flow * User representation wrapper */ import INTERNALS from '../../utils/internals'; +import { getNativeModule } from '../../utils/native'; import type Auth from './'; import type { ActionCodeSettings, AuthCredential } from '../../types'; @@ -92,7 +93,7 @@ export default class User { */ delete(): Promise { return this._auth - ._interceptUndefinedUserValue(this._auth._native.delete()); + ._interceptUndefinedUserValue(getNativeModule(this._auth).delete()); } /** @@ -100,7 +101,7 @@ export default class User { * @return {Promise} */ getIdToken(forceRefresh: boolean = false): Promise { - return this._auth._native.getToken(forceRefresh); + return getNativeModule(this._auth).getToken(forceRefresh); } /** @@ -109,7 +110,7 @@ export default class User { */ linkWithCredential(credential: AuthCredential): Promise { return this._auth - ._interceptUserValue(this._auth._native.link(credential.providerId, credential.token, credential.secret)); + ._interceptUserValue(getNativeModule(this._auth).link(credential.providerId, credential.token, credential.secret)); } /** @@ -118,7 +119,7 @@ export default class User { */ reauthenticateWithCredential(credential: AuthCredential): Promise { return this._auth - ._interceptUndefinedUserValue(this._auth._native.reauthenticate(credential.providerId, credential.token, credential.secret)); + ._interceptUndefinedUserValue(getNativeModule(this._auth).reauthenticate(credential.providerId, credential.token, credential.secret)); } /** @@ -127,7 +128,7 @@ export default class User { */ reload(): Promise { return this._auth - ._interceptUndefinedUserValue(this._auth._native.reload()); + ._interceptUndefinedUserValue(getNativeModule(this._auth).reload()); } /** @@ -135,7 +136,7 @@ export default class User { */ sendEmailVerification(actionCodeSettings?: ActionCodeSettings): Promise { return this._auth - ._interceptUndefinedUserValue(this._auth._native.sendEmailVerification(actionCodeSettings)); + ._interceptUndefinedUserValue(getNativeModule(this._auth).sendEmailVerification(actionCodeSettings)); } toJSON(): Object { @@ -148,7 +149,7 @@ export default class User { * @return {Promise.|*} */ unlink(providerId: string): Promise { - return this._auth._interceptUserValue(this._auth._native.unlink(providerId)); + return this._auth._interceptUserValue(getNativeModule(this._auth).unlink(providerId)); } /** @@ -159,7 +160,7 @@ export default class User { */ updateEmail(email: string): Promise { return this._auth - ._interceptUndefinedUserValue(this._auth._native.updateEmail(email)); + ._interceptUndefinedUserValue(getNativeModule(this._auth).updateEmail(email)); } /** @@ -169,7 +170,7 @@ export default class User { */ updatePassword(password: string): Promise { return this._auth - ._interceptUndefinedUserValue(this._auth._native.updatePassword(password)); + ._interceptUndefinedUserValue(getNativeModule(this._auth).updatePassword(password)); } /** @@ -179,7 +180,7 @@ export default class User { */ updateProfile(updates: Object = {}): Promise { return this._auth - ._interceptUndefinedUserValue(this._auth._native.updateProfile(updates)); + ._interceptUndefinedUserValue(getNativeModule(this._auth).updateProfile(updates)); } /** @@ -189,7 +190,7 @@ export default class User { */ getToken(forceRefresh: boolean = false): Promise { console.warn('Deprecated firebase.User.prototype.getToken in favor of firebase.User.prototype.getIdToken.'); - return this._auth._native.getToken(forceRefresh); + return getNativeModule(this._auth).getToken(forceRefresh); } /** diff --git a/lib/modules/auth/index.js b/lib/modules/auth/index.js index acf8e0a5..224978a5 100644 --- a/lib/modules/auth/index.js +++ b/lib/modules/auth/index.js @@ -6,6 +6,7 @@ import User from './User'; import ModuleBase from '../../utils/ModuleBase'; import { getAppEventName, SharedEventEmitter } from '../../utils/events'; import { getLogger } from '../../utils/log'; +import { getNativeModule } from '../../utils/native'; import INTERNALS from '../../utils/internals'; import ConfirmationResult from './ConfirmationResult'; @@ -20,7 +21,7 @@ import FacebookAuthProvider from './providers/FacebookAuthProvider'; import PhoneAuthListener from './PhoneAuthListener'; import type { ActionCodeSettings, AuthCredential } from '../../types'; -import type FirebaseApp from '../core/firebase-app'; +import type App from '../core/firebase-app'; type AuthResult = { authenticated: boolean, @@ -39,8 +40,8 @@ export default class Auth extends ModuleBase { _authResult: AuthResult | null; _user: User | null; - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, { + constructor(app: App) { + super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, namespace: NAMESPACE, @@ -69,8 +70,8 @@ export default class Auth extends ModuleBase { this._onInternalIdTokenChanged.bind(this), ); - this._native.addAuthStateListener(); - this._native.addIdTokenListener(); + getNativeModule(this).addAuthStateListener(); + getNativeModule(this).addIdTokenListener(); } /** @@ -200,7 +201,7 @@ export default class Auth extends ModuleBase { * @return {Promise} */ signOut(): Promise { - return this._interceptUndefinedUserValue(this._native.signOut()); + return this._interceptUndefinedUserValue(getNativeModule(this).signOut()); } /** @@ -208,7 +209,7 @@ export default class Auth extends ModuleBase { * @return {Promise} A promise resolved upon completion */ signInAnonymously(): Promise { - return this._interceptUserValue(this._native.signInAnonymously()); + return this._interceptUserValue(getNativeModule(this).signInAnonymously()); } /** @@ -218,7 +219,7 @@ export default class Auth extends ModuleBase { * @return {Promise} A promise indicating the completion */ createUserWithEmailAndPassword(email: string, password: string): Promise { - return this._interceptUserValue(this._native.createUserWithEmailAndPassword(email, password)); + return this._interceptUserValue(getNativeModule(this).createUserWithEmailAndPassword(email, password)); } /** @@ -228,7 +229,7 @@ export default class Auth extends ModuleBase { * @return {Promise} A promise that is resolved upon completion */ signInWithEmailAndPassword(email: string, password: string): Promise { - return this._interceptUserValue(this._native.signInWithEmailAndPassword(email, password)); + return this._interceptUserValue(getNativeModule(this).signInWithEmailAndPassword(email, password)); } /** @@ -237,7 +238,7 @@ export default class Auth extends ModuleBase { * @return {Promise} A promise resolved upon completion */ signInWithCustomToken(customToken: string): Promise { - return this._interceptUserValue(this._native.signInWithCustomToken(customToken)); + return this._interceptUserValue(getNativeModule(this).signInWithCustomToken(customToken)); } /** @@ -246,7 +247,7 @@ export default class Auth extends ModuleBase { */ signInWithCredential(credential: AuthCredential): Promise { return this._interceptUserValue( - this._native.signInWithCredential( + getNativeModule(this).signInWithCredential( credential.providerId, credential.token, credential.secret, ), ); @@ -257,7 +258,7 @@ export default class Auth extends ModuleBase { * */ signInWithPhoneNumber(phoneNumber: string): Promise { - return this._native.signInWithPhoneNumber(phoneNumber).then((result) => { + return getNativeModule(this).signInWithPhoneNumber(phoneNumber).then((result) => { return new ConfirmationResult(this, result.verificationId); }); } @@ -280,7 +281,7 @@ export default class Auth extends ModuleBase { * @param {string} email The email to send password reset instructions */ sendPasswordResetEmail(email: string, actionCodeSettings?: ActionCodeSettings): Promise { - return this._native.sendPasswordResetEmail(email, actionCodeSettings); + return getNativeModule(this).sendPasswordResetEmail(email, actionCodeSettings); } /** @@ -292,7 +293,7 @@ export default class Auth extends ModuleBase { * @return {Promise.} */ confirmPasswordReset(code: string, newPassword: string): Promise { - return this._native.confirmPasswordReset(code, newPassword); + return getNativeModule(this).confirmPasswordReset(code, newPassword); } /** @@ -303,7 +304,7 @@ export default class Auth extends ModuleBase { * @return {Promise.} */ applyActionCode(code: string): Promise { - return this._native.applyActionCode(code); + return getNativeModule(this).applyActionCode(code); } /** @@ -314,7 +315,7 @@ export default class Auth extends ModuleBase { * @return {Promise.|Promise} */ checkActionCode(code: string): Promise { - return this._native.checkActionCode(code); + return getNativeModule(this).checkActionCode(code); } /** @@ -322,7 +323,7 @@ export default class Auth extends ModuleBase { * @return {Promise} */ getCurrentUser(): Promise { - return this._interceptUserValue(this._native.getCurrentUser()); + return this._interceptUserValue(getNativeModule(this).getCurrentUser()); } /** @@ -330,7 +331,7 @@ export default class Auth extends ModuleBase { * @return {Promise} */ fetchProvidersForEmail(email: string): Promise> { - return this._native.fetchProvidersForEmail(email); + return getNativeModule(this).fetchProvidersForEmail(email); } /** diff --git a/lib/modules/config/index.js b/lib/modules/config/index.js index ea3ab5cb..ab34b94b 100644 --- a/lib/modules/config/index.js +++ b/lib/modules/config/index.js @@ -3,9 +3,10 @@ * Remote Config representation wrapper */ import { getLogger } from '../../utils/log'; -import ModuleBase from './../../utils/ModuleBase'; +import ModuleBase from '../../utils/ModuleBase'; +import { getNativeModule } from '../../utils/native'; -import type FirebaseApp from '../core/firebase-app'; +import type App from '../core/firebase-app'; type NativeValue = { stringValue?: string, @@ -24,8 +25,8 @@ export const NAMESPACE = 'config'; export default class RemoteConfig extends ModuleBase { _developerModeEnabled: boolean; - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, { + constructor(app: App) { + super(app, { moduleName: MODULE_NAME, namespace: NAMESPACE, }); @@ -43,7 +44,7 @@ export default class RemoteConfig extends ModuleBase { source: nativeValue.source, val() { if (nativeValue.boolValue !== null && (nativeValue.stringValue === 'true' || nativeValue.stringValue === 'false' || nativeValue.stringValue === null)) return nativeValue.boolValue; - if (nativeValue.numberValue !== null && (nativeValue.stringValue == null || nativeValue.stringValue === '' || `${nativeValue.numberValue}` === nativeValue.stringValue)) return nativeValue.numberValue; + if (nativeValue.numberValue !== null && nativeValue.numberValue !== undefined && (nativeValue.stringValue == null || nativeValue.stringValue === '' || nativeValue.numberValue.toString() === nativeValue.stringValue)) return nativeValue.numberValue; if (nativeValue.dataValue !== nativeValue.stringValue && (nativeValue.stringValue == null || nativeValue.stringValue === '')) return nativeValue.dataValue; return nativeValue.stringValue; }, @@ -56,7 +57,7 @@ export default class RemoteConfig extends ModuleBase { enableDeveloperMode() { if (!this._developerModeEnabled) { getLogger(this).debug('Enabled developer mode'); - this._native.enableDeveloperMode(); + getNativeModule(this).enableDeveloperMode(); this._developerModeEnabled = true; } } @@ -69,10 +70,10 @@ export default class RemoteConfig extends ModuleBase { fetch(expiration?: number) { if (expiration !== undefined) { getLogger(this).debug(`Fetching remote config data with expiration ${expiration.toString()}`); - return this._native.fetchWithExpirationDuration(expiration); + return getNativeModule(this).fetchWithExpirationDuration(expiration); } getLogger(this).debug('Fetching remote config data'); - return this._native.fetch(); + return getNativeModule(this).fetch(); } /** @@ -83,7 +84,7 @@ export default class RemoteConfig extends ModuleBase { */ activateFetched() { getLogger(this).debug('Activating remote config'); - return this._native.activateFetched(); + return getNativeModule(this).activateFetched(); } /** @@ -100,7 +101,7 @@ export default class RemoteConfig extends ModuleBase { * } */ getValue(key: String) { - return this._native + return getNativeModule(this) .getValue(key || '') .then(this._nativeValueToJS); } @@ -120,7 +121,7 @@ export default class RemoteConfig extends ModuleBase { * } */ getValues(keys: Array) { - return this._native + return getNativeModule(this) .getValues(keys || []) .then((nativeValues) => { const values: { [String]: Object } = {}; @@ -137,7 +138,7 @@ export default class RemoteConfig extends ModuleBase { * @returns {*|Promise.>} */ getKeysByPrefix(prefix?: String) { - return this._native.getKeysByPrefix(prefix); + return getNativeModule(this).getKeysByPrefix(prefix); } /** @@ -145,7 +146,7 @@ export default class RemoteConfig extends ModuleBase { * @param defaults: A dictionary mapping a String key to a Object values. */ setDefaults(defaults: Object) { - this._native.setDefaults(defaults); + getNativeModule(this).setDefaults(defaults); } /** @@ -153,7 +154,7 @@ export default class RemoteConfig extends ModuleBase { * @param resource: The plist file name or resource ID */ setDefaultsFromResource(resource: String | number) { - this._native.setDefaultsFromResource(resource); + getNativeModule(this).setDefaultsFromResource(resource); } } diff --git a/lib/modules/core/firebase-app.js b/lib/modules/core/firebase-app.js index ae340e44..a10eb140 100644 --- a/lib/modules/core/firebase-app.js +++ b/lib/modules/core/firebase-app.js @@ -29,7 +29,7 @@ import type { const FirebaseCoreModule = NativeModules.RNFirebase; -export default class FirebaseApp { +export default class App { _extendedProps: { [string] : boolean }; _initialized: boolean = false; _name: string; @@ -119,6 +119,7 @@ export default class FirebaseApp { throw new Error(INTERNALS.STRINGS.ERROR_PROTECTED_PROP(key)); } + // $FlowBug: Flow doesn't support indexable signatures on classes: https://github.com/facebook/flow/issues/1323 this[key] = props[key]; this._extendedProps[key] = true; } @@ -145,7 +146,7 @@ export default class FirebaseApp { * * @return {*} */ - onReady(): Promise { + onReady(): Promise { if (this._initialized) return Promise.resolve(this); return new Promise((resolve, reject) => { diff --git a/lib/modules/core/firebase.js b/lib/modules/core/firebase.js index 7bd151b6..72ff3eef 100644 --- a/lib/modules/core/firebase.js +++ b/lib/modules/core/firebase.js @@ -6,7 +6,7 @@ import { NativeModules } from 'react-native'; import APPS from '../../utils/apps'; import INTERNALS from '../../utils/internals'; -import FirebaseApp from './firebase-app'; +import App from './firebase-app'; // module imports import { statics as AdMobStatics, MODULE_NAME as AdmobModuleName } from '../admob'; @@ -88,7 +88,7 @@ class FirebaseCore { * @param name * @return {*} */ - initializeApp(options: FirebaseOptions, name: string): FirebaseApp { + initializeApp(options: FirebaseOptions, name: string): App { return APPS.initializeApp(options, name); } @@ -101,7 +101,7 @@ class FirebaseCore { * @param name * @return {*} */ - app(name?: string): FirebaseApp { + app(name?: string): App { return APPS.app(name); } @@ -109,7 +109,7 @@ class FirebaseCore { * A (read-only) array of all initialized apps. * @return {Array} */ - get apps(): Array { + get apps(): Array { return APPS.apps(); } } diff --git a/lib/modules/crash/index.js b/lib/modules/crash/index.js index 9d2a2042..48fbbea4 100644 --- a/lib/modules/crash/index.js +++ b/lib/modules/crash/index.js @@ -3,16 +3,17 @@ * Crash Reporting representation wrapper */ import ModuleBase from '../../utils/ModuleBase'; +import { getNativeModule } from '../../utils/native'; -import type FirebaseApp from '../core/firebase-app'; +import type App from '../core/firebase-app'; import type { FirebaseError } from '../../types'; export const MODULE_NAME = 'RNFirebaseCrash'; export const NAMESPACE = 'crash'; export default class Crash extends ModuleBase { - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, { + constructor(app: App) { + super(app, { moduleName: MODULE_NAME, namespace: NAMESPACE, }); @@ -23,7 +24,7 @@ export default class Crash extends ModuleBase { * @param enabled */ setCrashCollectionEnabled(enabled: boolean): void { - this._native.setCrashCollectionEnabled(enabled); + getNativeModule(this).setCrashCollectionEnabled(enabled); } /** @@ -31,7 +32,7 @@ export default class Crash extends ModuleBase { * @returns {Promise.} */ isCrashCollectionEnabled(): Promise { - return this._native.isCrashCollectionEnabled(); + return getNativeModule(this).isCrashCollectionEnabled(); } /** @@ -39,7 +40,7 @@ export default class Crash extends ModuleBase { * @param {string} message */ log(message: string): void { - this._native.log(message); + getNativeModule(this).log(message); } /** @@ -50,7 +51,7 @@ export default class Crash extends ModuleBase { * @param {string} tag */ logcat(level: number, tag: string, message: string): void { - this._native.logcat(level, tag, message); + getNativeModule(this).logcat(level, tag, message); } /** @@ -77,7 +78,7 @@ export default class Crash extends ModuleBase { errorMessage = `${errorMessage} - ${stackRows[i]}\r\n`; } - this._native.report(errorMessage); + getNativeModule(this).report(errorMessage); } } diff --git a/lib/modules/database/index.js b/lib/modules/database/index.js index cfac1094..f40e7ac6 100644 --- a/lib/modules/database/index.js +++ b/lib/modules/database/index.js @@ -1,4 +1,4 @@ -/** +getNativeModule(this)/** * @flow * Database representation wrapper */ @@ -6,9 +6,10 @@ import { NativeModules } from 'react-native'; import Reference from './reference'; import TransactionHandler from './transaction'; -import ModuleBase from './../../utils/ModuleBase'; +import ModuleBase from '../../utils/ModuleBase'; +import { getNativeModule } from '../../utils/native'; -import type FirebaseApp from '../core/firebase-app'; +import type App from '../core/firebase-app'; const NATIVE_EVENTS = [ 'database_transaction_event', @@ -26,19 +27,16 @@ export default class Database extends ModuleBase { _serverTimeOffset: number; _transactionHandler: TransactionHandler; - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, { - persistence: false, - ...options, - }, { + constructor(app: App, options: Object = {}) { + super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, namespace: NAMESPACE, }); this._transactionHandler = new TransactionHandler(this); - if (this._options.persistence) { - this._native.setPersistence(this._options.persistence); + if (options.persistence) { + getNativeModule(this).setPersistence(options.persistence); } // server time listener @@ -66,14 +64,14 @@ export default class Database extends ModuleBase { * */ goOnline(): void { - this._native.goOnline(); + getNativeModule(this).goOnline(); } /** * */ goOffline(): void { - this._native.goOffline(); + getNativeModule(this).goOffline(); } /** diff --git a/lib/modules/database/reference.js b/lib/modules/database/reference.js index fbb2a7e2..42f41a96 100644 --- a/lib/modules/database/reference.js +++ b/lib/modules/database/reference.js @@ -6,6 +6,7 @@ import Query from './query.js'; import Snapshot from './snapshot'; import Disconnect from './disconnect'; import { getLogger } from '../../utils/log'; +import { getNativeModule } from '../../utils/native'; import ReferenceBase from '../../utils/ReferenceBase'; import { @@ -80,7 +81,7 @@ export default class Reference extends ReferenceBase { _refListeners: { [listenerId: number]: DatabaseListener }; constructor(database: Database, path: string, existingModifiers?: Array) { - super(path, database); + super(path); this._promise = null; this._refListeners = {}; this._database = database; @@ -99,7 +100,7 @@ export default class Reference extends ReferenceBase { * @returns {*} */ keepSynced(bool: boolean): Promise { - return this._database._native.keepSynced(this._getRefKey(), this.path, this._query.getModifiers(), bool); + return getNativeModule(this._database).keepSynced(this._getRefKey(), this.path, this._query.getModifiers(), bool); } /** @@ -112,7 +113,7 @@ export default class Reference extends ReferenceBase { */ set(value: any, onComplete?: Function): Promise { return promiseOrCallback( - this._database._native.set(this.path, this._serializeAnyType(value)), + getNativeModule(this._database).set(this.path, this._serializeAnyType(value)), onComplete, ); } @@ -129,7 +130,7 @@ export default class Reference extends ReferenceBase { const _priority = this._serializeAnyType(priority); return promiseOrCallback( - this._database._native.setPriority(this.path, _priority), + getNativeModule(this._database).setPriority(this.path, _priority), onComplete, ); } @@ -148,7 +149,7 @@ export default class Reference extends ReferenceBase { const _priority = this._serializeAnyType(priority); return promiseOrCallback( - this._database._native.setWithPriority(this.path, _value, _priority), + getNativeModule(this._database).setWithPriority(this.path, _value, _priority), onComplete, ); } @@ -165,7 +166,7 @@ export default class Reference extends ReferenceBase { const value = this._serializeObject(val); return promiseOrCallback( - this._database._native.update(this.path, value), + getNativeModule(this._database).update(this.path, value), onComplete, ); } @@ -179,7 +180,7 @@ export default class Reference extends ReferenceBase { */ remove(onComplete?: Function): Promise { return promiseOrCallback( - this._database._native.remove(this.path), + getNativeModule(this._database).remove(this.path), onComplete, ); } @@ -235,7 +236,7 @@ export default class Reference extends ReferenceBase { cancelOrContext: (error: FirebaseError) => void, context?: Object, ) { - return this._database._native.once(this._getRefKey(), this.path, this._query.getModifiers(), eventName) + return getNativeModule(this._database).once(this._getRefKey(), this.path, this._query.getModifiers(), eventName) .then(({ snapshot }) => { const _snapshot = new Snapshot(this, snapshot); @@ -270,7 +271,9 @@ export default class Reference extends ReferenceBase { // if callback provided then internally call the set promise with value if (isFunction(onComplete)) { return promise + // $FlowBug: Reports that onComplete can change to null despite the null check: https://github.com/facebook/flow/issues/1655 .then(() => onComplete(null, newRef)) + // $FlowBug: Reports that onComplete can change to null despite the null check: https://github.com/facebook/flow/issues/1655 .catch(error => onComplete(error, null)); } @@ -620,7 +623,7 @@ export default class Reference extends ReferenceBase { * * {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#on} */ - on(eventType: string, callback: () => any, cancelCallbackOrContext?: () => any, context?: Object): Function { + on(eventType: string, callback: (Snapshot) => any, cancelCallbackOrContext?: (Object) => any | Object, context?: Object): Function { if (!eventType) { throw new Error('Query.on failed: Function called with 0 arguments. Expects at least 2.'); } @@ -657,28 +660,29 @@ export default class Reference extends ReferenceBase { eventRegistrationKey, }; - SyncTree.addRegistration(registrationObj, _context ? callback.bind(_context) : callback); + SyncTree.addRegistration({ + ...registrationObj, + listener: _context ? callback.bind(_context) : callback, + }); - if (isFunction(cancelCallbackOrContext)) { + if (cancelCallbackOrContext && isFunction(cancelCallbackOrContext)) { // cancellations have their own separate registration // as these are one off events, and they're not guaranteed // to occur either, only happens on failure to register on native - SyncTree.addRegistration( - { - ref: this, - once: true, - path: this.path, - key: this._getRefKey(), - appName: this._database.app.name, - eventType: `${eventType}$cancelled`, - eventRegistrationKey: registrationCancellationKey, - }, - _context ? cancelCallbackOrContext.bind(_context) : cancelCallbackOrContext, - ); + SyncTree.addRegistration({ + ref: this, + once: true, + path: this.path, + key: this._getRefKey(), + appName: this._database.app.name, + eventType: `${eventType}$cancelled`, + eventRegistrationKey: registrationCancellationKey, + listener: _context ? cancelCallbackOrContext.bind(_context) : cancelCallbackOrContext, + }); } // initialise the native listener if not already listening - this._database._native.on({ + getNativeModule(this._database).on({ eventType, path: this.path, key: this._getRefKey(), diff --git a/lib/modules/database/transaction.js b/lib/modules/database/transaction.js index 79d7bcf3..1711d441 100644 --- a/lib/modules/database/transaction.js +++ b/lib/modules/database/transaction.js @@ -4,17 +4,27 @@ */ import { getAppEventName, SharedEventEmitter } from '../../utils/events'; import { getLogger } from '../../utils/log'; +import { getNativeModule } from '../../utils/native'; import type Database from './'; let transactionId = 0; +/** + * Uses the push id generator to create a transaction id + * @returns {number} + * @private + */ +const generateTransactionId = (): number => { + return transactionId++; +}; + /** * @class TransactionHandler */ export default class TransactionHandler { _database: Database; _transactionListener: Function; - _transactions: { [string]: Object } + _transactions: { [number]: Object } constructor(database: Database) { this._transactions = {}; @@ -34,7 +44,7 @@ export default class TransactionHandler { * @param applyLocally */ add(reference: Object, transactionUpdater: Function, onComplete?: Function, applyLocally?: boolean = false) { - const id = this._generateTransactionId(); + const id = generateTransactionId(); this._transactions[id] = { id, @@ -46,22 +56,13 @@ export default class TransactionHandler { started: true, }; - this._database._native.transactionStart(reference.path, id, applyLocally); + getNativeModule(this._database).transactionStart(reference.path, id, applyLocally); } /** * INTERNALS */ - /** - * Uses the push id generator to create a transaction id - * @returns {string} - * @private - */ - _generateTransactionId(): string { - return transactionId++; - } - /** * * @param event @@ -103,7 +104,7 @@ export default class TransactionHandler { abort = true; } - this._database._native.transactionTryCommit(id, { value: newValue, abort }); + getNativeModule(this._database).transactionTryCommit(id, { value: newValue, abort }); } } @@ -117,7 +118,7 @@ export default class TransactionHandler { if (transaction && !transaction.completed) { transaction.completed = true; try { - transaction.onComplete(new Error(event.error.message, event.error.code), null); + transaction.onComplete(event.error, false, null); } finally { setImmediate(() => { delete this._transactions[event.id]; diff --git a/lib/modules/fabric/crashlytics/index.js b/lib/modules/fabric/crashlytics/index.js index 5c55bb0c..789c9af8 100644 --- a/lib/modules/fabric/crashlytics/index.js +++ b/lib/modules/fabric/crashlytics/index.js @@ -3,15 +3,16 @@ * Crash Reporting representation wrapper */ import ModuleBase from '../../../utils/ModuleBase'; +import { getNativeModule } from '../../../utils/native'; -import type FirebaseApp from '../../core/firebase-app'; +import type App from '../../core/firebase-app'; export const MODULE_NAME = 'RNFirebaseCrashlytics'; export const NAMESPACE = 'crashlytics'; export default class Crashlytics extends ModuleBase { - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, { + constructor(app: App) { + super(app, { moduleName: MODULE_NAME, namespace: NAMESPACE, }); @@ -21,7 +22,7 @@ export default class Crashlytics extends ModuleBase { * Forces a crash. Useful for testing your application is set up correctly. */ crash(): void { - this._native.crash(); + getNativeModule(this).crash(); } /** @@ -29,7 +30,7 @@ export default class Crashlytics extends ModuleBase { * @param {string} message */ log(message: string): void { - this._native.log(message); + getNativeModule(this).log(message); } /** @@ -38,42 +39,42 @@ export default class Crashlytics extends ModuleBase { * @param {string} message */ recordError(code: number, message: string): void { - this._native.recordError(code, message); + getNativeModule(this).recordError(code, message); } /** * Set a boolean value to show alongside any subsequent crash reports. */ setBoolValue(key: string, value: boolean): void { - this._native.setBoolValue(key, value); + getNativeModule(this).setBoolValue(key, value); } /** * Set a float value to show alongside any subsequent crash reports. */ setFloatValue(key: string, value: number): void { - this._native.setFloatValue(key, value); + getNativeModule(this).setFloatValue(key, value); } /** * Set an integer value to show alongside any subsequent crash reports. */ setIntValue(key: string, value: number): void { - this._native.setIntValue(key, value); + getNativeModule(this).setIntValue(key, value); } /** * Set a string value to show alongside any subsequent crash reports. */ setStringValue(key: string, value: string): void { - this._native.setStringValue(key, value); + getNativeModule(this).setStringValue(key, value); } /** * Set the user ID to show alongside any subsequent crash reports. */ setUserIdentifier(userId: string): void { - this._native.setUserIdentifier(userId); + getNativeModule(this).setUserIdentifier(userId); } } diff --git a/lib/modules/firestore/CollectionReference.js b/lib/modules/firestore/CollectionReference.js index 87598b57..c3cba570 100644 --- a/lib/modules/firestore/CollectionReference.js +++ b/lib/modules/firestore/CollectionReference.js @@ -6,11 +6,10 @@ import DocumentReference from './DocumentReference'; import Query from './Query'; import { firestoreAutoId } from '../../utils'; -import type DocumentSnapshot from './DocumentSnapshot'; import type Firestore from './'; import type { FirestoreQueryDirection, FirestoreQueryOperator } from '../../types'; import type Path from './Path'; -import type { Observer, QueryListenOptions } from './Query'; +import type { Observer, ObserverOnError, ObserverOnNext, QueryListenOptions } from './Query'; import type QuerySnapshot from './QuerySnapshot'; /** @@ -75,9 +74,9 @@ export default class CollectionReference { } onSnapshot( - optionsOrObserverOrOnNext: QueryListenOptions | Observer | (DocumentSnapshot) => void, - observerOrOnNextOrOnError?: Observer | (DocumentSnapshot) => void | (Object) => void, - onError?: (Object) => void, + optionsOrObserverOrOnNext: QueryListenOptions | Observer | ObserverOnNext, + observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError, + onError?: ObserverOnError, ): () => void { return this._query.onSnapshot(optionsOrObserverOrOnNext, observerOrOnNextOrOnError, onError); } diff --git a/lib/modules/firestore/DocumentReference.js b/lib/modules/firestore/DocumentReference.js index 0befcbfd..e401d4f1 100644 --- a/lib/modules/firestore/DocumentReference.js +++ b/lib/modules/firestore/DocumentReference.js @@ -8,6 +8,7 @@ import { buildNativeMap } from './utils/serialize'; import { getAppEventName, SharedEventEmitter } from '../../utils/events'; import { getLogger } from '../../utils/log'; import { firestoreAutoId, isFunction, isObject, isString } from '../../utils'; +import { getNativeModule } from '../../utils/native'; import type Firestore from './'; import type { FirestoreNativeDocumentSnapshot, FirestoreWriteOptions } from '../../types'; @@ -67,12 +68,12 @@ export default class DocumentReference { } delete(): Promise { - return this._firestore._native + return getNativeModule(this._firestore) .documentDelete(this.path); } get(): Promise { - return this._firestore._native + return getNativeModule(this._firestore) .documentGet(this.path) .then(result => new DocumentSnapshot(this._firestore, result)); } @@ -82,15 +83,18 @@ export default class DocumentReference { observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError, onError?: ObserverOnError, ) { - let observer = {}; + let observer: Observer; let docListenOptions = {}; // Called with: onNext, ?onError if (isFunction(optionsOrObserverOrOnNext)) { - observer.next = optionsOrObserverOrOnNext; if (observerOrOnNextOrOnError && !isFunction(observerOrOnNextOrOnError)) { throw new Error('DocumentReference.onSnapshot failed: Second argument must be a valid function.'); } - observer.error = observerOrOnNextOrOnError; + // $FlowBug: Not coping with the overloaded method signature + observer = { + next: optionsOrObserverOrOnNext, + error: observerOrOnNextOrOnError, + }; } else if (optionsOrObserverOrOnNext && isObject(optionsOrObserverOrOnNext)) { // Called with: Observer if (optionsOrObserverOrOnNext.next) { @@ -98,7 +102,11 @@ export default class DocumentReference { if (optionsOrObserverOrOnNext.error && !isFunction(optionsOrObserverOrOnNext.error)) { throw new Error('DocumentReference.onSnapshot failed: Observer.error must be a valid function.'); } - observer = optionsOrObserverOrOnNext; + // $FlowBug: Not coping with the overloaded method signature + observer = { + next: optionsOrObserverOrOnNext.next, + error: optionsOrObserverOrOnNext.error, + }; } else { throw new Error('DocumentReference.onSnapshot failed: Observer.next must be a valid function.'); } @@ -106,18 +114,24 @@ export default class DocumentReference { docListenOptions = optionsOrObserverOrOnNext; // Called with: Options, onNext, ?onError if (isFunction(observerOrOnNextOrOnError)) { - observer.next = observerOrOnNextOrOnError; if (onError && !isFunction(onError)) { throw new Error('DocumentReference.onSnapshot failed: Third argument must be a valid function.'); } - observer.error = onError; + // $FlowBug: Not coping with the overloaded method signature + observer = { + next: observerOrOnNextOrOnError, + error: onError, + }; // Called with Options, Observer } else if (observerOrOnNextOrOnError && isObject(observerOrOnNextOrOnError) && observerOrOnNextOrOnError.next) { if (isFunction(observerOrOnNextOrOnError.next)) { if (observerOrOnNextOrOnError.error && !isFunction(observerOrOnNextOrOnError.error)) { throw new Error('DocumentReference.onSnapshot failed: Observer.error must be a valid function.'); } - observer = observerOrOnNextOrOnError; + observer = { + next: observerOrOnNextOrOnError.next, + error: observerOrOnNextOrOnError.error, + }; } else { throw new Error('DocumentReference.onSnapshot failed: Observer.next must be a valid function.'); } @@ -152,7 +166,7 @@ export default class DocumentReference { } // Add the native listener - this._firestore._native + getNativeModule(this._firestore) .documentOnSnapshot(this.path, listenerId, docListenOptions); // Return an unsubscribe method @@ -161,7 +175,7 @@ export default class DocumentReference { set(data: Object, writeOptions?: FirestoreWriteOptions): Promise { const nativeData = buildNativeMap(data); - return this._firestore._native + return getNativeModule(this._firestore) .documentSet(this.path, nativeData, writeOptions); } @@ -185,7 +199,7 @@ export default class DocumentReference { } } const nativeData = buildNativeMap(data); - return this._firestore._native + return getNativeModule(this._firestore) .documentUpdate(this.path, nativeData); } @@ -201,7 +215,7 @@ export default class DocumentReference { getLogger(this._firestore).info('Removing onDocumentSnapshot listener'); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`), listener); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`), listener); - this._firestore._native + getNativeModule(this._firestore) .documentOffSnapshot(this.path, listenerId); } } diff --git a/lib/modules/firestore/Query.js b/lib/modules/firestore/Query.js index 5f5b9129..5d26f977 100644 --- a/lib/modules/firestore/Query.js +++ b/lib/modules/firestore/Query.js @@ -8,6 +8,7 @@ import { buildNativeArray, buildTypeMap } from './utils/serialize'; import { getAppEventName, SharedEventEmitter } from '../../utils/events'; import { getLogger } from '../../utils/log'; import { firestoreAutoId, isFunction, isObject } from '../../utils'; +import { getNativeModule } from '../../utils/native'; import type Firestore from './'; import type { FirestoreQueryDirection, FirestoreQueryOperator } from '../../types'; @@ -53,9 +54,12 @@ export type QueryListenOptions = { includeQueryMetadataChanges: boolean, } +export type ObserverOnError = (Object) => void; +export type ObserverOnNext = (QuerySnapshot) => void; + export type Observer = { - next: (DocumentSnapshot) => void, - error?: (Object) => void, + error?: ObserverOnError, + next: ObserverOnNext, } /** @@ -119,7 +123,7 @@ export default class Query { } get(): Promise { - return this._firestore._native + return getNativeModule(this._firestore) .collectionGet( this._referencePath.relativeName, this._fieldFilters, @@ -147,19 +151,22 @@ export default class Query { } onSnapshot( - optionsOrObserverOrOnNext: QueryListenOptions | Observer | (DocumentSnapshot) => void, - observerOrOnNextOrOnError?: Observer | (DocumentSnapshot) => void | (Object) => void, - onError?: (Object) => void, + optionsOrObserverOrOnNext: QueryListenOptions | Observer | ObserverOnNext, + observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError, + onError?: ObserverOnError, ) { - let observer = {}; + let observer: Observer; let queryListenOptions = {}; // Called with: onNext, ?onError if (isFunction(optionsOrObserverOrOnNext)) { - observer.next = optionsOrObserverOrOnNext; if (observerOrOnNextOrOnError && !isFunction(observerOrOnNextOrOnError)) { throw new Error('Query.onSnapshot failed: Second argument must be a valid function.'); } - observer.error = observerOrOnNextOrOnError; + // $FlowBug: Not coping with the overloaded method signature + observer = { + next: optionsOrObserverOrOnNext, + error: observerOrOnNextOrOnError, + }; } else if (optionsOrObserverOrOnNext && isObject(optionsOrObserverOrOnNext)) { // Called with: Observer if (optionsOrObserverOrOnNext.next) { @@ -167,7 +174,11 @@ export default class Query { if (optionsOrObserverOrOnNext.error && !isFunction(optionsOrObserverOrOnNext.error)) { throw new Error('Query.onSnapshot failed: Observer.error must be a valid function.'); } - observer = optionsOrObserverOrOnNext; + // $FlowBug: Not coping with the overloaded method signature + observer = { + next: optionsOrObserverOrOnNext.next, + error: optionsOrObserverOrOnNext.error, + }; } else { throw new Error('Query.onSnapshot failed: Observer.next must be a valid function.'); } @@ -175,18 +186,24 @@ export default class Query { queryListenOptions = optionsOrObserverOrOnNext; // Called with: Options, onNext, ?onError if (isFunction(observerOrOnNextOrOnError)) { - observer.next = observerOrOnNextOrOnError; if (onError && !isFunction(onError)) { throw new Error('Query.onSnapshot failed: Third argument must be a valid function.'); } - observer.error = onError; + // $FlowBug: Not coping with the overloaded method signature + observer = { + next: observerOrOnNextOrOnError, + error: onError, + }; // Called with Options, Observer } else if (observerOrOnNextOrOnError && isObject(observerOrOnNextOrOnError) && observerOrOnNextOrOnError.next) { if (isFunction(observerOrOnNextOrOnError.next)) { if (observerOrOnNextOrOnError.error && !isFunction(observerOrOnNextOrOnError.error)) { throw new Error('Query.onSnapshot failed: Observer.error must be a valid function.'); } - observer = observerOrOnNextOrOnError; + observer = { + next: observerOrOnNextOrOnError.next, + error: observerOrOnNextOrOnError.error, + }; } else { throw new Error('Query.onSnapshot failed: Observer.next must be a valid function.'); } @@ -199,7 +216,6 @@ export default class Query { } else { throw new Error('Query.onSnapshot failed: Called with invalid arguments.'); } - const listenerId = firestoreAutoId(); const listener = (nativeQuerySnapshot) => { @@ -222,7 +238,7 @@ export default class Query { } // Add the native listener - this._firestore._native + getNativeModule(this._firestore) .collectionOnSnapshot( this._referencePath.relativeName, this._fieldFilters, @@ -339,7 +355,7 @@ export default class Query { getLogger(this._firestore).info('Removing onQuerySnapshot listener'); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onQuerySnapshot:${listenerId}`), listener); SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onQuerySnapshotError:${listenerId}`), listener); - this._firestore._native + getNativeModule(this._firestore) .collectionOffSnapshot( this._referencePath.relativeName, this._fieldFilters, diff --git a/lib/modules/firestore/WriteBatch.js b/lib/modules/firestore/WriteBatch.js index 6d687ac9..2b315de2 100644 --- a/lib/modules/firestore/WriteBatch.js +++ b/lib/modules/firestore/WriteBatch.js @@ -4,6 +4,7 @@ */ import { buildNativeMap } from './utils/serialize'; import { isObject, isString } from '../../utils'; +import { getNativeModule } from '../../utils/native'; import type DocumentReference from './DocumentReference'; import type Firestore from './'; @@ -29,8 +30,7 @@ export default class WriteBatch { } commit(): Promise { - return this._firestore._native - .documentBatch(this._writes); + return getNativeModule(this._firestore).documentBatch(this._writes); } delete(docRef: DocumentReference): WriteBatch { diff --git a/lib/modules/firestore/index.js b/lib/modules/firestore/index.js index ac78e497..7061ed4b 100644 --- a/lib/modules/firestore/index.js +++ b/lib/modules/firestore/index.js @@ -15,7 +15,7 @@ import WriteBatch from './WriteBatch'; import INTERNALS from '../../utils/internals'; import type DocumentSnapshot from './DocumentSnapshot'; -import type FirebaseApp from '../core/firebase-app'; +import type App from '../core/firebase-app'; import type QuerySnapshot from './QuerySnapshot'; type CollectionSyncEvent = { @@ -48,8 +48,8 @@ export const NAMESPACE = 'firestore'; export default class Firestore extends ModuleBase { _referencePath: Path; - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, { + constructor(app: App) { + super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, namespace: NAMESPACE, diff --git a/lib/modules/links/index.js b/lib/modules/links/index.js index 411a2427..1ca4f3ca 100644 --- a/lib/modules/links/index.js +++ b/lib/modules/links/index.js @@ -4,9 +4,10 @@ */ import { SharedEventEmitter } from '../../utils/events'; import ModuleBase from '../../utils/ModuleBase'; -import { areObjectKeysContainedInOther, isObject, isString } from './../../utils'; +import { areObjectKeysContainedInOther, isObject, isString } from '../../utils'; +import { getNativeModule } from '../../utils/native'; -import type FirebaseApp from '../core/firebase-app'; +import type App from '../core/firebase-app'; const EVENT_TYPE = { Link: 'dynamic_link_received', @@ -70,8 +71,8 @@ function checkForMandatoryParameters(parameters: Object): void { * @class Links */ export default class Links extends ModuleBase { - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, { + constructor(app: App) { + super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, namespace: NAMESPACE, @@ -87,7 +88,7 @@ export default class Links extends ModuleBase { * @returns {Promise.} */ getInitialLink(): Promise { - return this._native.getInitialLink(); + return getNativeModule(this).getInitialLink(); } /** @@ -109,7 +110,7 @@ export default class Links extends ModuleBase { try { checkForMandatoryParameters(parameters); validateParameters(parameters); - return this._native.createDynamicLink(parameters); + return getNativeModule(this).createDynamicLink(parameters); } catch (error) { return Promise.reject(error); } @@ -124,7 +125,7 @@ export default class Links extends ModuleBase { try { checkForMandatoryParameters(parameters); validateParameters(parameters); - return this._native.createShortDynamicLink(parameters); + return getNativeModule(this).createShortDynamicLink(parameters); } catch (error) { return Promise.reject(error); } diff --git a/lib/modules/messaging/index.js b/lib/modules/messaging/index.js index ab365583..0686f860 100644 --- a/lib/modules/messaging/index.js +++ b/lib/modules/messaging/index.js @@ -6,8 +6,9 @@ import { Platform, NativeModules } from 'react-native'; import { SharedEventEmitter } from '../../utils/events'; import ModuleBase from '../../utils/ModuleBase'; import RemoteMessage from './RemoteMessage'; +import { getNativeModule } from '../../utils/native'; -import type FirebaseApp from '../core/firebase-app'; +import type App from '../core/firebase-app'; const EVENT_TYPE = { RefreshToken: 'messaging_token_refreshed', @@ -86,8 +87,8 @@ export const NAMESPACE = 'messaging'; * @class Messaging */ export default class Messaging extends ModuleBase { - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, { + constructor(app: App) { + super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, namespace: NAMESPACE, @@ -115,7 +116,7 @@ export default class Messaging extends ModuleBase { * @returns {*} */ getInitialNotification(): Promise { - return this._native.getInitialNotification(); + return getNativeModule(this).getInitialNotification(); } /** @@ -123,7 +124,7 @@ export default class Messaging extends ModuleBase { * @returns {*|Promise.} */ getToken(): Promise { - return this._native.getToken(); + return getNativeModule(this).getToken(); } /** @@ -131,7 +132,7 @@ export default class Messaging extends ModuleBase { * @returns {*|Promise.<*>} */ deleteInstanceId(): Promise { - return this._native.deleteInstanceId(); + return getNativeModule(this).deleteInstanceId(); } /** @@ -143,7 +144,7 @@ export default class Messaging extends ModuleBase { const _notification = Object.assign({}, notification); _notification.id = _notification.id || new Date().getTime().toString(); _notification.local_notification = true; - return this._native.createLocalNotification(_notification); + return getNativeModule(this).createLocalNotification(_notification); } /** @@ -155,7 +156,7 @@ export default class Messaging extends ModuleBase { const _notification = Object.assign({}, notification); if (!notification.id) return Promise.reject(new Error('An id is required to schedule a local notification.')); _notification.local_notification = true; - return this._native.scheduleLocalNotification(_notification); + return getNativeModule(this).scheduleLocalNotification(_notification); } /** @@ -163,7 +164,7 @@ export default class Messaging extends ModuleBase { * @returns {Promise.} */ getScheduledLocalNotifications(): Promise { - return this._native.getScheduledLocalNotifications(); + return getNativeModule(this).getScheduledLocalNotifications(); } /** @@ -174,8 +175,8 @@ export default class Messaging extends ModuleBase { */ cancelLocalNotification(id: string): Promise { if (!id) return Promise.reject(new Error('Missing notification id')); - if (id === '*') return this._native.cancelAllLocalNotifications(); - return this._native.cancelLocalNotification(id); + if (id === '*') return getNativeModule(this).cancelAllLocalNotifications(); + return getNativeModule(this).cancelLocalNotification(id); } /** @@ -186,8 +187,8 @@ export default class Messaging extends ModuleBase { */ removeDeliveredNotification(id: string): Promise { if (!id) return Promise.reject(new Error('Missing notification id')); - if (id === '*') return this._native.removeAllDeliveredNotifications(); - return this._native.removeDeliveredNotification(id); + if (id === '*') return getNativeModule(this).removeAllDeliveredNotifications(); + return getNativeModule(this).removeDeliveredNotification(id); } /** @@ -196,7 +197,7 @@ export default class Messaging extends ModuleBase { * @returns {*|Promise.<*>} */ requestPermissions(): Promise { - return this._native.requestPermissions(); + return getNativeModule(this).requestPermissions(); } @@ -205,7 +206,7 @@ export default class Messaging extends ModuleBase { * @param n */ setBadgeNumber(n: number): void { - this._native.setBadgeNumber(n); + getNativeModule(this).setBadgeNumber(n); } /** @@ -213,7 +214,7 @@ export default class Messaging extends ModuleBase { * @returns {Promise.} */ getBadgeNumber(): Promise { - return this._native.getBadgeNumber(); + return getNativeModule(this).getBadgeNumber(); } /** @@ -254,7 +255,7 @@ export default class Messaging extends ModuleBase { * @param topic */ subscribeToTopic(topic: string): void { - this._native.subscribeToTopic(topic); + getNativeModule(this).subscribeToTopic(topic); } /** @@ -262,7 +263,7 @@ export default class Messaging extends ModuleBase { * @param topic */ unsubscribeFromTopic(topic: string): void { - this._native.unsubscribeFromTopic(topic); + getNativeModule(this).unsubscribeFromTopic(topic); } /** @@ -274,7 +275,7 @@ export default class Messaging extends ModuleBase { throw new Error('messaging().send requires an instance of RemoteMessage as the first argument.'); } - return this._native.send(remoteMessage.toJSON()); + return getNativeModule(this).send(remoteMessage.toJSON()); } } diff --git a/lib/modules/perf/Trace.js b/lib/modules/perf/Trace.js index 5b5614b1..5fd54608 100644 --- a/lib/modules/perf/Trace.js +++ b/lib/modules/perf/Trace.js @@ -2,26 +2,27 @@ * @flow * Trace representation wrapper */ +import { getNativeModule } from '../../utils/native'; import type PerformanceMonitoring from './'; export default class Trace { identifier: string; - perf: PerformanceMonitoring; + _perf: PerformanceMonitoring; constructor(perf: PerformanceMonitoring, identifier: string) { - this.perf = perf; + this._perf = perf; this.identifier = identifier; } start(): void { - this.perf._native.start(this.identifier); + getNativeModule(this._perf).start(this.identifier); } stop(): void { - this.perf._native.stop(this.identifier); + getNativeModule(this._perf).stop(this.identifier); } incrementCounter(event: string): void { - this.perf._native.incrementCounter(this.identifier, event); + getNativeModule(this._perf).incrementCounter(this.identifier, event); } } diff --git a/lib/modules/perf/index.js b/lib/modules/perf/index.js index 7ac349c3..165919ad 100644 --- a/lib/modules/perf/index.js +++ b/lib/modules/perf/index.js @@ -4,15 +4,16 @@ */ import Trace from './Trace'; import ModuleBase from '../../utils/ModuleBase'; +import { getNativeModule } from '../../utils/native'; -import type FirebaseApp from '../core/firebase-app'; +import type App from '../core/firebase-app'; export const MODULE_NAME = 'RNFirebasePerformance'; export const NAMESPACE = 'perf'; export default class PerformanceMonitoring extends ModuleBase { - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, { + constructor(app: App) { + super(app, { moduleName: MODULE_NAME, namespace: NAMESPACE, }); @@ -24,7 +25,7 @@ export default class PerformanceMonitoring extends ModuleBase { * @returns {*} */ setPerformanceCollectionEnabled(enabled: boolean): void { - this._native.setPerformanceCollectionEnabled(enabled); + getNativeModule(this).setPerformanceCollectionEnabled(enabled); } /** diff --git a/lib/modules/storage/index.js b/lib/modules/storage/index.js index 77f0400f..f0f86282 100644 --- a/lib/modules/storage/index.js +++ b/lib/modules/storage/index.js @@ -7,9 +7,10 @@ import { NativeModules } from 'react-native'; import StorageRef from './reference'; import { getAppEventName, SharedEventEmitter } from '../../utils/events'; import { getLogger } from '../../utils/log'; -import ModuleBase from './../../utils/ModuleBase'; +import ModuleBase from '../../utils/ModuleBase'; +import { getNativeModule } from '../../utils/native'; -import type FirebaseApp from '../core/firebase-app'; +import type App from '../core/firebase-app'; const FirebaseStorage = NativeModules.RNFirebaseStorage; @@ -24,11 +25,11 @@ export const NAMESPACE = 'storage'; export default class Storage extends ModuleBase { /** * - * @param firebaseApp + * @param app * @param options */ - constructor(firebaseApp: FirebaseApp, options: Object = {}) { - super(firebaseApp, options, { + constructor(app: App) { + super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, namespace: NAMESPACE, @@ -61,7 +62,7 @@ export default class Storage extends ModuleBase { * @param url * @returns {StorageReference} */ - refFromURL(url: string): Promise { + refFromURL(url: string): StorageRef { // TODO don't think this is correct? return new StorageRef(this, `url::${url}`); } @@ -72,7 +73,7 @@ export default class Storage extends ModuleBase { * @param time The new maximum operation retry time in milliseconds. */ setMaxOperationRetryTime(time: number): void { - this._native.setMaxOperationRetryTime(time); + getNativeModule(this).setMaxOperationRetryTime(time); } /** @@ -81,7 +82,7 @@ export default class Storage extends ModuleBase { * @param time The new maximum upload retry time in milliseconds. */ setMaxUploadRetryTime(time: number): void { - this._native.setMaxUploadRetryTime(time); + getNativeModule(this).setMaxUploadRetryTime(time); } /** @@ -90,7 +91,7 @@ export default class Storage extends ModuleBase { * @param time The new maximum download retry time in milliseconds. */ setMaxDownloadRetryTime(time: number): void { - this._native.setMaxDownloadRetryTime(time); + getNativeModule(this).setMaxDownloadRetryTime(time); } /** diff --git a/lib/modules/storage/reference.js b/lib/modules/storage/reference.js index d38c5d2a..8db997ad 100644 --- a/lib/modules/storage/reference.js +++ b/lib/modules/storage/reference.js @@ -4,6 +4,7 @@ */ import ReferenceBase from '../../utils/ReferenceBase'; import StorageTask, { UPLOAD_TASK, DOWNLOAD_TASK } from './task'; +import { getNativeModule } from '../../utils/native'; import type Storage from './'; @@ -14,7 +15,7 @@ export default class StorageReference extends ReferenceBase { _storage: Storage; constructor(storage: Storage, path: string) { - super(path, storage); + super(path); this._storage = storage; } @@ -40,7 +41,7 @@ export default class StorageReference extends ReferenceBase { * @returns {Promise.|*} */ delete(): Promise { - return this._storage._native.delete(this.path); + return getNativeModule(this._storage).delete(this.path); } /** @@ -48,7 +49,7 @@ export default class StorageReference extends ReferenceBase { * @returns {Promise.|*} */ getDownloadURL(): Promise { - return this._storage._native.getDownloadURL(this.path); + return getNativeModule(this._storage).getDownloadURL(this.path); } /** @@ -56,7 +57,7 @@ export default class StorageReference extends ReferenceBase { * @returns {Promise.|*} */ getMetadata(): Promise { - return this._storage._native.getMetadata(this.path); + return getNativeModule(this._storage).getMetadata(this.path); } /** @@ -65,7 +66,7 @@ export default class StorageReference extends ReferenceBase { * @returns {Promise.|*} */ updateMetadata(metadata: Object = {}): Promise { - return this._storage._native.updateMetadata(this.path, metadata); + return getNativeModule(this._storage).updateMetadata(this.path, metadata); } /** @@ -74,7 +75,7 @@ export default class StorageReference extends ReferenceBase { * @return {Promise} */ downloadFile(filePath: string): Promise { - return new StorageTask(DOWNLOAD_TASK, this._storage._native.downloadFile(this.path, filePath), this); + return new StorageTask(DOWNLOAD_TASK, getNativeModule(this._storage).downloadFile(this.path, filePath), this); } /** @@ -93,6 +94,6 @@ export default class StorageReference extends ReferenceBase { */ putFile(filePath: Object, metadata: Object = {}): Promise { const _filePath = filePath.replace('file://', ''); - return new StorageTask(UPLOAD_TASK, this._module._native.putFile(this.path, _filePath, metadata), this); + return new StorageTask(UPLOAD_TASK, getNativeModule(this._storage).putFile(this.path, _filePath, metadata), this); } } diff --git a/lib/modules/utils/index.js b/lib/modules/utils/index.js index 9e3cc5db..6b9ade59 100644 --- a/lib/modules/utils/index.js +++ b/lib/modules/utils/index.js @@ -25,25 +25,23 @@ export default class RNFirebaseUtils extends ModuleBase { * */ checkPlayServicesAvailability() { - if (isIOS) return null; + if (isIOS) return; - const { code } = this.playServicesAvailability; + const { status } = this.playServicesAvailability; if (!this.playServicesAvailability.isAvailable) { if (INTERNALS.OPTIONS.promptOnMissingPlayServices && this.playServicesAvailability.isUserResolvableError) { this.promptForPlayServices(); } else { - const error = INTERNALS.STRINGS.ERROR_PLAY_SERVICES(code); + const error = INTERNALS.STRINGS.ERROR_PLAY_SERVICES(status); if (INTERNALS.OPTIONS.errorOnMissingPlayServices) { - if (code === 2) console.warn(error); // only warn if it exists but may need an update + if (status === 2) console.warn(error); // only warn if it exists but may need an update else throw new Error(error); } else { console.warn(error); } } } - - return null; } promptForPlayServices() { @@ -64,10 +62,10 @@ export default class RNFirebaseUtils extends ModuleBase { /** * Set the global logging level for all logs. * - * @param booleanOrDebugString + * @param logLevel */ - set logLevel(booleanOrDebugString) { - INTERNALS.OPTIONS.logLevel = booleanOrDebugString; + set logLevel(logLevel: string) { + INTERNALS.OPTIONS.logLevel = logLevel; } /** diff --git a/lib/utils/ModuleBase.js b/lib/utils/ModuleBase.js index c93ba6ba..35ed7eb3 100644 --- a/lib/utils/ModuleBase.js +++ b/lib/utils/ModuleBase.js @@ -4,21 +4,18 @@ import { initialiseLogger } from './log'; import { initialiseNativeModule } from './native'; -import type FirebaseApp from '../modules/core/firebase-app'; +import type App from '../modules/core/firebase-app'; import type { FirebaseModuleConfig } from '../types'; export default class ModuleBase { - _firebaseApp: FirebaseApp; - _native: Object; - _options: Object; + _app: App; /** * - * @param firebaseApp - * @param options - * @param withEventEmitter + * @param app + * @param config */ - constructor(firebaseApp: FirebaseApp, options: Object, config: FirebaseModuleConfig) { + constructor(app: App, config: FirebaseModuleConfig) { if (!config.moduleName) { throw new Error('Missing module name'); } @@ -26,20 +23,18 @@ export default class ModuleBase { throw new Error('Missing namespace'); } const { moduleName } = config; - this._firebaseApp = firebaseApp; - this._options = options; + this._app = app; // check if native module exists as all native - // TODO: Get rid of this._native and change to using getNativeModule instead? - this._native = initialiseNativeModule(this, config); - initialiseLogger(this, `${firebaseApp.name}:${moduleName.replace('RNFirebase', '')}`); + initialiseNativeModule(this, config); + initialiseLogger(this, `${app.name}:${moduleName.replace('RNFirebase', '')}`); } /** - * Returns the FirebaseApp instance for current module + * Returns the App instance for current module * @return {*} */ - get app(): FirebaseApp { - return this._firebaseApp; + get app(): App { + return this._app; } } diff --git a/lib/utils/ReferenceBase.js b/lib/utils/ReferenceBase.js index 631d23a1..80e0eede 100644 --- a/lib/utils/ReferenceBase.js +++ b/lib/utils/ReferenceBase.js @@ -1,15 +1,10 @@ /** * @flow */ -import type Database from '../modules/database'; -import type Storage from '../modules/storage'; - export default class ReferenceBase { - _module: Database | Storage; path: string; - constructor(path: string, module: Database | Storage) { - this._module = module; + constructor(path: string) { this.path = path || '/'; } diff --git a/lib/utils/SyncTree.js b/lib/utils/SyncTree.js index c4213365..36c97c21 100644 --- a/lib/utils/SyncTree.js +++ b/lib/utils/SyncTree.js @@ -8,13 +8,15 @@ import DatabaseSnapshot from '../modules/database/snapshot'; import DatabaseReference from '../modules/database/reference'; import { isString, nativeToJSError } from '../utils'; +type Listener = (DatabaseSnapshot) => any; + type Registration = { key: string, path: string, once?: boolean, appName: string, eventType: string, - listener: Function, + listener: Listener, eventRegistrationKey: string, ref: DatabaseReference, } @@ -26,7 +28,7 @@ type Registration = { class SyncTree { _nativeEmitter: NativeEventEmitter; _reverseLookup: { [string]: Registration }; - _tree: { [string]: { [string]: { [string]: Function }}}; + _tree: { [string]: { [string]: { [string]: Listener }}}; constructor() { this._tree = {}; @@ -128,7 +130,7 @@ class SyncTree { * @param registrations * @return {number} */ - removeListenersForRegistrations(registrations: string | string[]) { + removeListenersForRegistrations(registrations: string | string[]): number { if (isString(registrations)) { this.removeRegistration(registrations); SharedEventEmitter.removeAllListeners(registrations); @@ -151,7 +153,7 @@ class SyncTree { * @param registrations * @return {Array} array of registrations removed */ - removeListenerRegistrations(listener, registrations: string[]) { + removeListenerRegistrations(listener: () => any, registrations: string[]) { if (!Array.isArray(registrations)) return []; const removed = []; @@ -181,7 +183,7 @@ class SyncTree { * @param path * @return {Array} */ - getRegistrationsByPath(path: string): Array { + getRegistrationsByPath(path: string): string[] { const out = []; const eventKeys = Object.keys(this._tree[path] || {}); @@ -199,7 +201,7 @@ class SyncTree { * @param eventType * @return {Array} */ - getRegistrationsByPathEvent(path: string, eventType: string): Array { + getRegistrationsByPathEvent(path: string, eventType: string): string[] { if (!this._tree[path]) return []; if (!this._tree[path][eventType]) return []; @@ -214,9 +216,9 @@ class SyncTree { * @param listener * @return {Array} */ - getOneByPathEventListener(path: string, eventType: string, listener: Function): Array { - if (!this._tree[path]) return []; - if (!this._tree[path][eventType]) return []; + getOneByPathEventListener(path: string, eventType: string, listener: Function): ?string { + if (!this._tree[path]) return null; + if (!this._tree[path][eventType]) return null; const registrationsForPathEvent = Object.entries(this._tree[path][eventType]); @@ -236,19 +238,20 @@ class SyncTree { * @param listener * @return {String} */ - addRegistration(parameters: Registration, listener: Function): string { + addRegistration(registration: Registration): string { const { - path, - eventType, eventRegistrationKey, + eventType, + listener, once, - } = parameters; + path, + } = registration; if (!this._tree[path]) this._tree[path] = {}; if (!this._tree[path][eventType]) this._tree[path][eventType] = {}; this._tree[path][eventType][eventRegistrationKey] = listener; - this._reverseLookup[eventRegistrationKey] = Object.assign({ listener }, parameters); + this._reverseLookup[eventRegistrationKey] = registration; if (once) { SharedEventEmitter.once( @@ -305,7 +308,7 @@ class SyncTree { * @private */ _onOnceRemoveRegistration(registration, listener) { - return (...args) => { + return (...args: any[]) => { this.removeRegistration(registration); listener(...args); }; diff --git a/lib/utils/apps.js b/lib/utils/apps.js index fcef8fa1..3be466e7 100644 --- a/lib/utils/apps.js +++ b/lib/utils/apps.js @@ -2,7 +2,7 @@ * @flow */ import { NativeModules } from 'react-native'; -import FirebaseApp from '../modules/core/firebase-app'; +import App from '../modules/core/firebase-app'; import INTERNALS from './internals'; import { isAndroid, isObject, isString } from './'; @@ -17,21 +17,22 @@ import type { const FirebaseCoreModule = NativeModules.RNFirebase; -const APPS: { [string]: FirebaseApp } = {}; -const APP_MODULES: { [FirebaseApp]: { [string]: FirebaseModule }} = {}; +const APPS: { [string]: App } = {}; +const APP_MODULES: { [App]: { [string]: FirebaseModule }} = {}; const DEFAULT_APP_NAME = '[DEFAULT]'; export default { DEFAULT_APP_NAME, - app(name?: string): FirebaseApp { + app(name?: string): App { const _name = name ? name.toUpperCase() : DEFAULT_APP_NAME; const app = APPS[_name]; if (!app) throw new Error(INTERNALS.STRINGS.ERROR_APP_NOT_INIT(_name)); return app; }, - apps(): Array { + apps(): Array { + // $FlowBug: Object.values always returns mixed type: https://github.com/facebook/flow/issues/2221 return Object.values(APPS); }, @@ -42,10 +43,10 @@ export default { * @return {function()} * @private */ - appModule(firebaseApp: FirebaseApp, namespace: FirebaseNamespace, InstanceClass: Class): () => FirebaseModule { + appModule(app: App, namespace: FirebaseNamespace, InstanceClass: Class): () => FirebaseModule { return (): M => { - if (!APP_MODULES[firebaseApp]) { - APP_MODULES[firebaseApp] = {}; + if (!APP_MODULES[app]) { + APP_MODULES[app] = {}; } if (isAndroid && namespace !== 'utils' && !INTERNALS.FLAGS.checkedPlayServices) { @@ -53,11 +54,11 @@ export default { this.utils().checkPlayServicesAvailability(); } - if (!APP_MODULES[firebaseApp][namespace]) { - APP_MODULES[firebaseApp][namespace] = new InstanceClass(firebaseApp, firebaseApp.options); + if (!APP_MODULES[app][namespace]) { + APP_MODULES[app][namespace] = new InstanceClass(app, app.options); } - return APP_MODULES[firebaseApp][namespace]; + return APP_MODULES[app][namespace]; }; }, @@ -79,7 +80,7 @@ export default { * @param name * @return {*} */ - initializeApp(options: FirebaseOptions, name: string): FirebaseApp { + initializeApp(options: FirebaseOptions, name: string): App { if (name && !isString(name)) { throw new Error(INTERNALS.STRINGS.ERROR_INIT_STRING_NAME); } @@ -124,7 +125,7 @@ export default { throw new Error(INTERNALS.STRINGS.ERROR_MISSING_OPT('storageBucket')); } - APPS[_name] = new FirebaseApp(_name, options); + APPS[_name] = new App(_name, options); return APPS[_name]; }, @@ -137,7 +138,7 @@ export default { const app = FirebaseCoreModule.apps[i]; const options = Object.assign({}, app); delete options.name; - APPS[app.name] = new FirebaseApp(app.name, options, true); + APPS[app.name] = new App(app.name, options, true); } }, @@ -145,22 +146,23 @@ export default { * * @param statics * @param InstanceClass - * @return {function(FirebaseApp=)} + * @return {function(App=)} */ moduleAndStatics(namespace: FirebaseNamespace, statics: S, moduleName: FirebaseModuleName): FirebaseModuleAndStatics { - const getModule = (app?: FirebaseApp): FirebaseModule => { - let firebaseApp = app; + const getModule = (app?: App): FirebaseModule => { + let _app = app; // throw an error if it's not a valid app instance - if (firebaseApp && !(firebaseApp instanceof FirebaseApp)) throw new Error(INTERNALS.STRINGS.ERROR_NOT_APP(namespace)); + if (_app && !(_app instanceof App)) throw new Error(INTERNALS.STRINGS.ERROR_NOT_APP(namespace)); // default to the 'DEFAULT' app if no arg provided - will throw an error // if default app not initialized - else if (!firebaseApp) firebaseApp = this.app(DEFAULT_APP_NAME); + else if (!_app) _app = this.app(DEFAULT_APP_NAME); if (namespace === 'crashlytics') { - return firebaseApp.fabric[namespace](); + return _app.fabric[namespace](); } - const module = firebaseApp[namespace]; + // $FlowBug: Flow doesn't support indexable signatures on classes: https://github.com/facebook/flow/issues/1323 + const module = _app[namespace]; return module(); }; diff --git a/lib/utils/events.js b/lib/utils/events.js index 659be82b..83152dba 100644 --- a/lib/utils/events.js +++ b/lib/utils/events.js @@ -13,7 +13,7 @@ const NATIVE_SUBSCRIPTIONS: { [string]: boolean } = {}; export const SharedEventEmitter = new EventEmitter(); export const getAppEventName = (module: ModuleBase, eventName: string): string => { - return `${module._firebaseApp._name}-${eventName}`; + return `${module.app.name}-${eventName}`; }; const getNativeEmitter = (moduleName: FirebaseModuleName, module: ModuleBase): NativeEventEmitter => { diff --git a/lib/utils/index.js b/lib/utils/index.js index cea0b5d2..994bab1d 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -371,21 +371,21 @@ export function objectToUniqueId(object: Object): string { * @param optionalCallback * @return {Promise} */ -export function promiseOrCallback(promise: Promise<*>, optionalCallback?: Function) { +export function promiseOrCallback(promise: Promise<*>, optionalCallback?: Function): Promise<*> { if (!isFunction(optionalCallback)) return promise; return promise.then((result) => { // some of firebase internal tests & methods only check/return one arg // see https://github.com/firebase/firebase-js-sdk/blob/master/src/utils/promise.ts#L62 - if (optionalCallback.length === 1) { + if (optionalCallback && optionalCallback.length === 1) { optionalCallback(null); - } else { + } else if (optionalCallback) { optionalCallback(null, result); } return Promise.resolve(result); }).catch((error) => { - optionalCallback(error); + if (optionalCallback) optionalCallback(error); return Promise.reject(error); }); } diff --git a/lib/utils/internals.js b/lib/utils/internals.js index 907c63da..13b7bedc 100644 --- a/lib/utils/internals.js +++ b/lib/utils/internals.js @@ -21,26 +21,32 @@ const GRADLE_DEPS = { }; const PLAY_SERVICES_CODES = { + // $FlowBug: Doesn't like numerical object keys: https://github.com/facebook/flow/issues/380 1: { code: 'SERVICE_MISSING', message: 'Google Play services is missing on this device.', }, + // $FlowBug: Doesn't like numerical object keys: https://github.com/facebook/flow/issues/380 2: { code: 'SERVICE_VERSION_UPDATE_REQUIRED', message: 'The installed version of Google Play services on this device is out of date.', }, + // $FlowBug: Doesn't like numerical object keys: https://github.com/facebook/flow/issues/380 3: { code: 'SERVICE_DISABLED', message: 'The installed version of Google Play services has been disabled on this device.', }, + // $FlowBug: Doesn't like numerical object keys: https://github.com/facebook/flow/issues/380 9: { code: 'SERVICE_INVALID', message: 'The version of the Google Play services installed on this device is not authentic.', }, + // $FlowBug: Doesn't like numerical object keys: https://github.com/facebook/flow/issues/380 18: { code: 'SERVICE_UPDATING', message: 'Google Play services is currently being updated on this device.', }, + // $FlowBug: Doesn't like numerical object keys: https://github.com/facebook/flow/issues/380 19: { code: 'SERVICE_MISSING_PERMISSION', message: 'Google Play service doesn\'t have one or more required permissions.', @@ -161,7 +167,7 @@ export default { * @return {string} */ ERROR_NOT_APP(namespace: string) { - return `Invalid FirebaseApp instance passed to firebase.${namespace}(app <--).`; + return `Invalid App instance passed to firebase.${namespace}(app <--).`; }, /** diff --git a/lib/utils/log.js b/lib/utils/log.js index e16eca99..75d21910 100644 --- a/lib/utils/log.js +++ b/lib/utils/log.js @@ -7,6 +7,7 @@ import type ModuleBase from './ModuleBase'; ((base) => { window = base || window; + // $FlowFixMe: Why are we using localStorage at all? if (!window.localStorage) window.localStorage = {}; })(windowOrGlobal); From d1f2b3fcfaeffed18be9591dd0561fea82890ae5 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Fri, 5 Jan 2018 18:23:38 +0000 Subject: [PATCH 52/56] [internals][types] Fix a couple of minor issues --- lib/modules/admob/index.js | 4 ---- lib/modules/auth/User.js | 2 +- lib/modules/auth/index.js | 4 ---- lib/modules/core/firebase.js | 4 ++-- lib/modules/database/disconnect.js | 11 ++++++----- lib/modules/database/index.js | 2 +- lib/utils/ModuleBase.js | 4 +++- lib/utils/log.js | 14 ++++++++++---- lib/utils/native.js | 14 +++++++++----- 9 files changed, 32 insertions(+), 27 deletions(-) diff --git a/lib/modules/admob/index.js b/lib/modules/admob/index.js index 84879f18..2e7fd4b7 100644 --- a/lib/modules/admob/index.js +++ b/lib/modules/admob/index.js @@ -101,10 +101,6 @@ export default class AdMob extends ModuleBase { rewarded(adUnit: string): RewardedVideo { return new RewardedVideo(this, adUnit); } - - get namespace(): string { - return 'firebase:admob'; - } } export const statics = { diff --git a/lib/modules/auth/User.js b/lib/modules/auth/User.js index b357915e..bcaa383f 100644 --- a/lib/modules/auth/User.js +++ b/lib/modules/auth/User.js @@ -1,4 +1,4 @@ -getNativeModule(this._auth)/** +/** * @flow * User representation wrapper */ diff --git a/lib/modules/auth/index.js b/lib/modules/auth/index.js index 224978a5..5568aeda 100644 --- a/lib/modules/auth/index.js +++ b/lib/modules/auth/index.js @@ -342,10 +342,6 @@ export default class Auth extends ModuleBase { return this._user; } - get namespace(): string { - return 'firebase:auth'; - } - /** * KNOWN UNSUPPORTED METHODS */ diff --git a/lib/modules/core/firebase.js b/lib/modules/core/firebase.js index 72ff3eef..abfdc52a 100644 --- a/lib/modules/core/firebase.js +++ b/lib/modules/core/firebase.js @@ -42,7 +42,7 @@ import type { const FirebaseCoreModule = NativeModules.RNFirebase; -class FirebaseCore { +class Firebase { admob: AdMobModule; analytics: AnalyticsModule; auth: AuthModule; @@ -114,4 +114,4 @@ class FirebaseCore { } } -export default new FirebaseCore(); +export default new Firebase(); diff --git a/lib/modules/database/disconnect.js b/lib/modules/database/disconnect.js index f1a37122..5266bc22 100644 --- a/lib/modules/database/disconnect.js +++ b/lib/modules/database/disconnect.js @@ -2,7 +2,8 @@ * @flow * Disconnect representation wrapper */ -import { typeOf } from './../../utils'; +import { typeOf } from '../../utils'; +import { getNativeModule } from '../../utils/native'; import type Database from './'; import type Reference from './reference'; @@ -32,7 +33,7 @@ export default class Disconnect { * @returns {*} */ set(value: string | Object): Promise { - return this._database._native.onDisconnectSet(this.path, { type: typeOf(value), value }); + return getNativeModule(this._database).onDisconnectSet(this.path, { type: typeOf(value), value }); } /** @@ -41,7 +42,7 @@ export default class Disconnect { * @returns {*} */ update(values: Object): Promise { - return this._database._native.onDisconnectUpdate(this.path, values); + return getNativeModule(this._database).onDisconnectUpdate(this.path, values); } /** @@ -49,7 +50,7 @@ export default class Disconnect { * @returns {*} */ remove(): Promise { - return this._database._native.onDisconnectRemove(this.path); + return getNativeModule(this._database).onDisconnectRemove(this.path); } /** @@ -57,6 +58,6 @@ export default class Disconnect { * @returns {*} */ cancel(): Promise { - return this._database._native.onDisconnectCancel(this.path); + return getNativeModule(this._database).onDisconnectCancel(this.path); } } diff --git a/lib/modules/database/index.js b/lib/modules/database/index.js index f40e7ac6..42b25cbc 100644 --- a/lib/modules/database/index.js +++ b/lib/modules/database/index.js @@ -1,4 +1,4 @@ -getNativeModule(this)/** +/** * @flow * Database representation wrapper */ diff --git a/lib/utils/ModuleBase.js b/lib/utils/ModuleBase.js index 35ed7eb3..6f1ac1a1 100644 --- a/lib/utils/ModuleBase.js +++ b/lib/utils/ModuleBase.js @@ -5,10 +5,11 @@ import { initialiseLogger } from './log'; import { initialiseNativeModule } from './native'; import type App from '../modules/core/firebase-app'; -import type { FirebaseModuleConfig } from '../types'; +import type { FirebaseModuleConfig, FirebaseNamespace } from '../types'; export default class ModuleBase { _app: App; + namespace: FirebaseNamespace; /** * @@ -24,6 +25,7 @@ export default class ModuleBase { } const { moduleName } = config; this._app = app; + this.namespace = config.namespace; // check if native module exists as all native initialiseNativeModule(this, config); diff --git a/lib/utils/log.js b/lib/utils/log.js index 75d21910..dd57df66 100644 --- a/lib/utils/log.js +++ b/lib/utils/log.js @@ -13,13 +13,19 @@ import type ModuleBase from './ModuleBase'; // clean up time -const NATIVE_LOGGERS: { [ModuleBase]: Object } = {}; +const NATIVE_LOGGERS: { [string]: Object } = {}; -export const getLogger = (module: ModuleBase) => NATIVE_LOGGERS[module]; +const getModuleKey = (module: ModuleBase): string => `${module.app.name}:${module.namespace}`; + +export const getLogger = (module: ModuleBase) => { + const key = getModuleKey(module); + return NATIVE_LOGGERS[key]; +}; export const initialiseLogger = (module: ModuleBase, logNamespace: string) => { - if (!NATIVE_LOGGERS[module]) { - NATIVE_LOGGERS[module] = require('bows')(`🔥 ${logNamespace.toUpperCase()}`); + const key = getModuleKey(module); + if (!NATIVE_LOGGERS[key]) { + NATIVE_LOGGERS[key] = require('bows')(`🔥 ${logNamespace.toUpperCase()}`); } }; diff --git a/lib/utils/native.js b/lib/utils/native.js index d6404a47..ed728eb1 100644 --- a/lib/utils/native.js +++ b/lib/utils/native.js @@ -16,7 +16,7 @@ const MULTI_APP_MODULES = [ 'RNFirebaseStorage', ]; -const NATIVE_MODULES: { [ModuleBase]: Object } = {}; +const NATIVE_MODULES: { [string]: Object } = {}; /** * Prepends appName arg to all native method calls @@ -37,13 +37,17 @@ const nativeWithApp = (appName: string, NativeModule: Object): Object => { return native; }; +const getModuleKey = (module: ModuleBase): string => `${module.app.name}:${module.namespace}`; + export const getNativeModule = (module: ModuleBase): Object => { - return NATIVE_MODULES[module]; + const key = getModuleKey(module); + return NATIVE_MODULES[key]; }; export const initialiseNativeModule = (module: ModuleBase, config: FirebaseModuleConfig): Object => { const { moduleName, namespace } = config; const nativeModule = NativeModules[moduleName]; + const key = getModuleKey(module); if (!nativeModule && namespace !== 'utils') { throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(namespace, moduleName)); @@ -52,12 +56,12 @@ export const initialiseNativeModule = (module: ModuleBase, config: FirebaseModul // used by the modules that extend ModuleBase // to access their native module counterpart if (!MULTI_APP_MODULES.includes(moduleName)) { - NATIVE_MODULES[module] = nativeModule; + NATIVE_MODULES[key] = nativeModule; } else { - NATIVE_MODULES[module] = nativeWithApp(module.app.name, nativeModule); + NATIVE_MODULES[key] = nativeWithApp(module.app.name, nativeModule); } initialiseNativeModuleEventEmitter(module, config); - return NATIVE_MODULES[module]; + return NATIVE_MODULES[key]; }; From 6d313206861953e36efab0687afbdb4f13f786d2 Mon Sep 17 00:00:00 2001 From: "Jose Pablo Rocha, Jr" Date: Sun, 7 Jan 2018 15:09:40 -0600 Subject: [PATCH 53/56] Set NSNumber to nonnull for storage config calls Made change requested by Chris Bianca via Discord chat. New versions of react-native requires that all NSNumber arguments are explicitly marked as `nonnull` to ensure compatibility with Android. Only changed for a few storage methods. The other method exports with NSNumber will probably need to be updated as well, but I did not have a project setup to test them. --- ios/RNFirebase/storage/RNFirebaseStorage.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ios/RNFirebase/storage/RNFirebaseStorage.m b/ios/RNFirebase/storage/RNFirebaseStorage.m index ce6ea1ed..2116c7b6 100644 --- a/ios/RNFirebase/storage/RNFirebaseStorage.m +++ b/ios/RNFirebase/storage/RNFirebaseStorage.m @@ -162,7 +162,7 @@ RCT_EXPORT_METHOD(downloadFile:(NSString *) appDisplayName @param NSNumber milliseconds */ RCT_EXPORT_METHOD(setMaxDownloadRetryTime:(NSString *) appDisplayName - milliseconds:(NSNumber *) milliseconds) { + milliseconds:(nonnull NSNumber *) milliseconds) { FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; [[FIRStorage storageForApp:firApp] setMaxDownloadRetryTime:[milliseconds doubleValue]]; } @@ -174,7 +174,7 @@ RCT_EXPORT_METHOD(setMaxDownloadRetryTime:(NSString *) appDisplayName @param NSNumber milliseconds */ RCT_EXPORT_METHOD(setMaxOperationRetryTime:(NSString *) appDisplayName - milliseconds:(NSNumber *) milliseconds) { + milliseconds:(nonnull NSNumber *) milliseconds) { FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; [[FIRStorage storageForApp:firApp] setMaxOperationRetryTime:[milliseconds doubleValue]]; } @@ -185,7 +185,7 @@ RCT_EXPORT_METHOD(setMaxOperationRetryTime:(NSString *) appDisplayName @url https://firebase.google.com/docs/reference/js/firebase.storage.Storage#setMaxUploadRetryTime */ RCT_EXPORT_METHOD(setMaxUploadRetryTime:(NSString *) appDisplayName - milliseconds:(NSNumber *) milliseconds) { + milliseconds:(nonnull NSNumber *) milliseconds) { FIRApp *firApp = [RNFirebaseUtil getApp:appDisplayName]; [[FIRStorage storageForApp:firApp] setMaxUploadRetryTime:[milliseconds doubleValue]]; } From fe19942e183ce71e6499179506ad8e5c87289580 Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Mon, 8 Jan 2018 09:20:32 +0000 Subject: [PATCH 54/56] [android][utils] Fix a couple of minor Android issues with internals refactor --- lib/modules/utils/index.js | 8 ++++++++ lib/utils/apps.js | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/modules/utils/index.js b/lib/modules/utils/index.js index 6b9ade59..d6629bb0 100644 --- a/lib/modules/utils/index.js +++ b/lib/modules/utils/index.js @@ -6,6 +6,7 @@ import INTERNALS from '../../utils/internals'; import { isIOS } from '../../utils'; import ModuleBase from '../../utils/ModuleBase'; import PACKAGE from '../../../package.json'; +import type App from '../core/firebase-app'; const FirebaseCoreModule = NativeModules.RNFirebase; @@ -21,6 +22,13 @@ export const MODULE_NAME = 'RNFirebaseUtils'; export const NAMESPACE = 'utils'; export default class RNFirebaseUtils extends ModuleBase { + constructor(app: App) { + super(app, { + moduleName: MODULE_NAME, + namespace: NAMESPACE, + }); + } + /** * */ diff --git a/lib/utils/apps.js b/lib/utils/apps.js index 3be466e7..5e3a9c7f 100644 --- a/lib/utils/apps.js +++ b/lib/utils/apps.js @@ -51,7 +51,7 @@ export default { if (isAndroid && namespace !== 'utils' && !INTERNALS.FLAGS.checkedPlayServices) { INTERNALS.FLAGS.checkedPlayServices = true; - this.utils().checkPlayServicesAvailability(); + app.utils().checkPlayServicesAvailability(); } if (!APP_MODULES[app][namespace]) { From 301f2749c0c2f68dcc2c39c9961782a87208027a Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Tue, 9 Jan 2018 17:31:00 +0000 Subject: [PATCH 55/56] [internals] Migrate multi app flag to module configuration --- lib/modules/admob/index.js | 1 + lib/modules/analytics/index.js | 1 + lib/modules/auth/index.js | 1 + lib/modules/config/index.js | 1 + lib/modules/crash/index.js | 1 + lib/modules/database/index.js | 1 + lib/modules/fabric/crashlytics/index.js | 1 + lib/modules/firestore/index.js | 1 + lib/modules/links/index.js | 1 + lib/modules/messaging/index.js | 1 + lib/modules/perf/index.js | 1 + lib/modules/storage/index.js | 1 + lib/modules/utils/index.js | 1 + lib/types/index.js | 1 + lib/utils/native.js | 16 ++++------------ 15 files changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/modules/admob/index.js b/lib/modules/admob/index.js index 2e7fd4b7..6c6e357d 100644 --- a/lib/modules/admob/index.js +++ b/lib/modules/admob/index.js @@ -43,6 +43,7 @@ export default class AdMob extends ModuleBase { super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, + multiApp: false, namespace: NAMESPACE, }); diff --git a/lib/modules/analytics/index.js b/lib/modules/analytics/index.js index 44d8464f..e45678ae 100644 --- a/lib/modules/analytics/index.js +++ b/lib/modules/analytics/index.js @@ -32,6 +32,7 @@ export default class Analytics extends ModuleBase { constructor(app: App) { super(app, { moduleName: MODULE_NAME, + multiApp: false, namespace: NAMESPACE, }); } diff --git a/lib/modules/auth/index.js b/lib/modules/auth/index.js index 5568aeda..3151aac4 100644 --- a/lib/modules/auth/index.js +++ b/lib/modules/auth/index.js @@ -44,6 +44,7 @@ export default class Auth extends ModuleBase { super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, + multiApp: true, namespace: NAMESPACE, }); this._user = null; diff --git a/lib/modules/config/index.js b/lib/modules/config/index.js index ab34b94b..bede5a48 100644 --- a/lib/modules/config/index.js +++ b/lib/modules/config/index.js @@ -28,6 +28,7 @@ export default class RemoteConfig extends ModuleBase { constructor(app: App) { super(app, { moduleName: MODULE_NAME, + multiApp: false, namespace: NAMESPACE, }); this._developerModeEnabled = false; diff --git a/lib/modules/crash/index.js b/lib/modules/crash/index.js index 48fbbea4..314d910a 100644 --- a/lib/modules/crash/index.js +++ b/lib/modules/crash/index.js @@ -15,6 +15,7 @@ export default class Crash extends ModuleBase { constructor(app: App) { super(app, { moduleName: MODULE_NAME, + multiApp: false, namespace: NAMESPACE, }); } diff --git a/lib/modules/database/index.js b/lib/modules/database/index.js index 42b25cbc..d2fa1da0 100644 --- a/lib/modules/database/index.js +++ b/lib/modules/database/index.js @@ -31,6 +31,7 @@ export default class Database extends ModuleBase { super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, + multiApp: true, namespace: NAMESPACE, }); this._transactionHandler = new TransactionHandler(this); diff --git a/lib/modules/fabric/crashlytics/index.js b/lib/modules/fabric/crashlytics/index.js index 789c9af8..b95b9d2d 100644 --- a/lib/modules/fabric/crashlytics/index.js +++ b/lib/modules/fabric/crashlytics/index.js @@ -14,6 +14,7 @@ export default class Crashlytics extends ModuleBase { constructor(app: App) { super(app, { moduleName: MODULE_NAME, + multiApp: false, namespace: NAMESPACE, }); } diff --git a/lib/modules/firestore/index.js b/lib/modules/firestore/index.js index 7061ed4b..029b002e 100644 --- a/lib/modules/firestore/index.js +++ b/lib/modules/firestore/index.js @@ -52,6 +52,7 @@ export default class Firestore extends ModuleBase { super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, + multiApp: true, namespace: NAMESPACE, }); this._referencePath = new Path([]); diff --git a/lib/modules/links/index.js b/lib/modules/links/index.js index 1ca4f3ca..a4c36211 100644 --- a/lib/modules/links/index.js +++ b/lib/modules/links/index.js @@ -75,6 +75,7 @@ export default class Links extends ModuleBase { super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, + multiApp: false, namespace: NAMESPACE, }); } diff --git a/lib/modules/messaging/index.js b/lib/modules/messaging/index.js index 0686f860..5136cf98 100644 --- a/lib/modules/messaging/index.js +++ b/lib/modules/messaging/index.js @@ -91,6 +91,7 @@ export default class Messaging extends ModuleBase { super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, + multiApp: false, namespace: NAMESPACE, }); } diff --git a/lib/modules/perf/index.js b/lib/modules/perf/index.js index 165919ad..8b0eac38 100644 --- a/lib/modules/perf/index.js +++ b/lib/modules/perf/index.js @@ -15,6 +15,7 @@ export default class PerformanceMonitoring extends ModuleBase { constructor(app: App) { super(app, { moduleName: MODULE_NAME, + multiApp: false, namespace: NAMESPACE, }); } diff --git a/lib/modules/storage/index.js b/lib/modules/storage/index.js index f0f86282..8e372619 100644 --- a/lib/modules/storage/index.js +++ b/lib/modules/storage/index.js @@ -32,6 +32,7 @@ export default class Storage extends ModuleBase { super(app, { events: NATIVE_EVENTS, moduleName: MODULE_NAME, + multiApp: true, namespace: NAMESPACE, }); diff --git a/lib/modules/utils/index.js b/lib/modules/utils/index.js index d6629bb0..6991e37f 100644 --- a/lib/modules/utils/index.js +++ b/lib/modules/utils/index.js @@ -25,6 +25,7 @@ export default class RNFirebaseUtils extends ModuleBase { constructor(app: App) { super(app, { moduleName: MODULE_NAME, + multiApp: false, namespace: NAMESPACE, }); } diff --git a/lib/types/index.js b/lib/types/index.js index 31588854..32299af1 100644 --- a/lib/types/index.js +++ b/lib/types/index.js @@ -43,6 +43,7 @@ export type FirebaseModule = $Subtype; export type FirebaseModuleConfig = { events?: string[], moduleName: FirebaseModuleName, + multiApp: boolean, namespace: FirebaseNamespace, } diff --git a/lib/utils/native.js b/lib/utils/native.js index ed728eb1..274862c6 100644 --- a/lib/utils/native.js +++ b/lib/utils/native.js @@ -8,14 +8,6 @@ import INTERNALS from './internals'; import type ModuleBase from './ModuleBase'; import type { FirebaseModuleConfig } from '../types'; -// Firebase Native SDKs that support multiple app instances -const MULTI_APP_MODULES = [ - 'RNFirebaseAuth', - 'RNFirebaseDatabase', - 'RNFirebaseFirestore', - 'RNFirebaseStorage', -]; - const NATIVE_MODULES: { [string]: Object } = {}; /** @@ -45,7 +37,7 @@ export const getNativeModule = (module: ModuleBase): Object => { }; export const initialiseNativeModule = (module: ModuleBase, config: FirebaseModuleConfig): Object => { - const { moduleName, namespace } = config; + const { moduleName, multiApp, namespace } = config; const nativeModule = NativeModules[moduleName]; const key = getModuleKey(module); @@ -55,10 +47,10 @@ export const initialiseNativeModule = (module: ModuleBase, config: FirebaseModul // used by the modules that extend ModuleBase // to access their native module counterpart - if (!MULTI_APP_MODULES.includes(moduleName)) { - NATIVE_MODULES[key] = nativeModule; - } else { + if (multiApp) { NATIVE_MODULES[key] = nativeWithApp(module.app.name, nativeModule); + } else { + NATIVE_MODULES[key] = nativeModule; } initialiseNativeModuleEventEmitter(module, config); From d700bf9d6dcc277450238f52b0be65f691df379d Mon Sep 17 00:00:00 2001 From: Chris Bianca Date: Tue, 9 Jan 2018 17:31:54 +0000 Subject: [PATCH 56/56] [core] Add SDK_VERSION --- .gitignore | 1 + lib/modules/core/firebase.js | 9 ++++++++ lib/modules/utils/index.js | 11 +--------- package-lock.json | 42 ++++++++++++++++++++++++++++++++++++ package.json | 3 ++- 5 files changed, 55 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 7a868226..68b162ad 100644 --- a/.gitignore +++ b/.gitignore @@ -77,3 +77,4 @@ local.properties **/ios/Pods/** **/ios/ReactNativeFirebaseDemo.xcworkspace/ dist +version.js diff --git a/lib/modules/core/firebase.js b/lib/modules/core/firebase.js index abfdc52a..78317e82 100644 --- a/lib/modules/core/firebase.js +++ b/lib/modules/core/firebase.js @@ -7,6 +7,7 @@ import { NativeModules } from 'react-native'; import APPS from '../../utils/apps'; import INTERNALS from '../../utils/internals'; import App from './firebase-app'; +import VERSION from '../../version'; // module imports import { statics as AdMobStatics, MODULE_NAME as AdmobModuleName } from '../admob'; @@ -112,6 +113,14 @@ class Firebase { get apps(): Array { return APPS.apps(); } + + /** + * The current SDK version. + * @return {string} + */ + get SDK_VERSION(): string { + return VERSION; + } } export default new Firebase(); diff --git a/lib/modules/utils/index.js b/lib/modules/utils/index.js index 6991e37f..0cfb2ed0 100644 --- a/lib/modules/utils/index.js +++ b/lib/modules/utils/index.js @@ -1,11 +1,8 @@ // @flow import { NativeModules } from 'react-native'; -// import { version as ReactVersion } from 'react'; -// import ReactNativeVersion from 'react-native/Libraries/Core/ReactNativeVersion'; import INTERNALS from '../../utils/internals'; import { isIOS } from '../../utils'; import ModuleBase from '../../utils/ModuleBase'; -import PACKAGE from '../../../package.json'; import type App from '../core/firebase-app'; const FirebaseCoreModule = NativeModules.RNFirebase; @@ -106,10 +103,4 @@ export default class RNFirebaseUtils extends ModuleBase { } -export const statics = { - // VERSIONS: { - // react: ReactVersion, - // 'react-native': Object.values(ReactNativeVersion.version).slice(0, 3).join('.'), - // 'react-native-firebase': PACKAGE.version, - // }, -}; +export const statics = {}; diff --git a/package-lock.json b/package-lock.json index eaedc9aa..c5cb8750 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2680,6 +2680,15 @@ } } }, + "find-package": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-package/-/find-package-1.0.0.tgz", + "integrity": "sha1-13ONpn48XwVcJNPhmqGu7QY8PoM=", + "dev": true, + "requires": { + "parents": "1.0.1" + } + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -2690,6 +2699,12 @@ "pinkie-promise": "2.0.1" } }, + "firstline": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/firstline/-/firstline-1.2.1.tgz", + "integrity": "sha1-uIZzxCAJ+IIfrCkm6ZcgrO6ST64=", + "dev": true + }, "flat-cache": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", @@ -3819,6 +3834,18 @@ "lodash.padstart": "4.6.1" } }, + "genversion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/genversion/-/genversion-2.0.1.tgz", + "integrity": "sha1-cCAQ5VD3d6VtsWbrFzL4BA8mGao=", + "dev": true, + "requires": { + "commander": "2.11.0", + "find-package": "1.0.0", + "firstline": "1.2.1", + "mkdirp": "0.5.1" + } + }, "get-caller-file": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", @@ -5829,6 +5856,15 @@ "p-limit": "1.1.0" } }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "0.11.15" + } + }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", @@ -5889,6 +5925,12 @@ "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", "dev": true }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", diff --git a/package.json b/package.json index adad4656..9dd8d177 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { - "build": "npm run build-lib && npm run build-flow", + "build": "genversion lib/version.js && npm run build-lib && npm run build-flow", "build-flow": "flow-copy-source -i */__tests__* lib dist", "build-lib": "BABEL_ENV=publish babel lib -d dist --ignore __tests__ --copy-files", "clean": "rimraf dist/", @@ -88,6 +88,7 @@ "eslint-plugin-react": "^7.4.0", "flow-bin": "^0.56.0", "flow-copy-source": "^1.2.1", + "genversion": "^2.0.1", "react": "^16.0.0", "react-dom": "^16.0.0", "react-native": "^0.50.3",