Merge branch 'master' into typescript-definitions-static-module-fix
This commit is contained in:
commit
157f0109cd
54
.eslintrc
54
.eslintrc
@ -1,46 +1,36 @@
|
||||
{
|
||||
"extends": "airbnb",
|
||||
"extends": [
|
||||
"airbnb",
|
||||
"prettier",
|
||||
"prettier/flowtype",
|
||||
"prettier/react"
|
||||
],
|
||||
"parser": "babel-eslint",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
},
|
||||
"plugins": [
|
||||
"flowtype"
|
||||
"flowtype",
|
||||
"prettier"
|
||||
],
|
||||
"env": {
|
||||
"es6": true,
|
||||
"jasmine": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"prettier/prettier": ["error", {
|
||||
"trailingComma": "es5",
|
||||
"singleQuote": true
|
||||
}],
|
||||
|
||||
"react/forbid-prop-types": "warn",
|
||||
"react/jsx-filename-extension": [
|
||||
"off", { "extensions": [".js", ".jsx"] }
|
||||
],
|
||||
|
||||
"class-methods-use-this": 0,
|
||||
"no-plusplus": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-return-assign": 0,
|
||||
"no-undef": 0,
|
||||
"no-use-before-define": 0,
|
||||
"arrow-body-style": 0,
|
||||
"import/prefer-default-export": 0,
|
||||
"radix": 0,
|
||||
"new-cap": 0,
|
||||
"max-len": 0,
|
||||
"no-continue": 0,
|
||||
"no-console": 0,
|
||||
"global-require": 0,
|
||||
"import/extensions": 0,
|
||||
"import/no-unresolved": 0,
|
||||
"import/no-extraneous-dependencies": 0,
|
||||
"react/jsx-filename-extension": 0,
|
||||
"no-unused-expressions": 0,
|
||||
"flowtype/no-unused-expressions": ['error', {
|
||||
allowShortCircuit: false,
|
||||
allowTernary: false,
|
||||
allowTaggedTemplates: false,
|
||||
}]
|
||||
"no-plusplus": 0,
|
||||
"no-undef": 0,
|
||||
"no-underscore-dangle": "off",
|
||||
"no-use-before-define": 0
|
||||
},
|
||||
"globals": {
|
||||
"__DEV__": true,
|
||||
|
@ -453,31 +453,15 @@
|
||||
ENABLE_BITCODE = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"${BUILT_PRODUCTS_DIR}",
|
||||
"${SRCROOT}/../../../ios/Pods/Crashlytics/iOS",
|
||||
"${SRCROOT}/../../../ios/Pods/Fabric/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseAnalytics/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseAuth/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseCore/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseCrash/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseDatabase/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseDynamicLinks/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseFirestore/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseInstanceID/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseMessaging/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebasePerformance/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseRemoteConfig/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseStorage/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/Google-Mobile-Ads-SDK/Frameworks/frameworks",
|
||||
"${BUILT_PRODUCTS_DIR}/**",
|
||||
"${SRCROOT}/../../../ios/Pods/**",
|
||||
"${SRCROOT}/../../../ios/Firebase/**",
|
||||
);
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(SRCROOT)/../../react-native/React/**",
|
||||
"${SRCROOT}/../../../ios/Firebase/**",
|
||||
"${SRCROOT}/../../../ios/Pods/Headers/Public/Crashlytics",
|
||||
"${SRCROOT}/../../../ios/Pods/Headers/Public/Fabric",
|
||||
"${SRCROOT}/../../../ios/Pods/Firebase/**",
|
||||
"${SRCROOT}/../../../ios/Pods/Headers/Public/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
@ -498,31 +482,15 @@
|
||||
ENABLE_BITCODE = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"${BUILT_PRODUCTS_DIR}",
|
||||
"${SRCROOT}/../../../ios/Pods/Crashlytics/iOS",
|
||||
"${SRCROOT}/../../../ios/Pods/Fabric/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseAnalytics/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseAuth/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseCore/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseCrash/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseDatabase/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseDynamicLinks/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseFirestore/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseInstanceID/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseMessaging/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebasePerformance/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseRemoteConfig/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/FirebaseStorage/Frameworks",
|
||||
"${SRCROOT}/../../../ios/Pods/Google-Mobile-Ads-SDK/Frameworks/frameworks",
|
||||
"${BUILT_PRODUCTS_DIR}/**",
|
||||
"${SRCROOT}/../../../ios/Pods/**",
|
||||
"${SRCROOT}/../../../ios/Firebase/**",
|
||||
);
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(SRCROOT)/../../react-native/React/**",
|
||||
"${SRCROOT}/../../../ios/Firebase/**",
|
||||
"${SRCROOT}/../../../ios/Pods/Headers/Public/Crashlytics",
|
||||
"${SRCROOT}/../../../ios/Pods/Headers/Public/Fabric",
|
||||
"${SRCROOT}/../../../ios/Pods/Firebase/**",
|
||||
"${SRCROOT}/../../../ios/Pods/Headers/Public/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
|
262
lib/index.d.ts
vendored
262
lib/index.d.ts
vendored
@ -21,8 +21,8 @@ declare module "react-native-firebase" {
|
||||
database: FirebaseModuleAndStatics<RNFirebase.database.Database, RNFirebase.database.DatabaseStatics>;
|
||||
fabric: {
|
||||
crashlytics: FirebaseModuleAndStatics<RNFirebase.crashlytics.Crashlytics>;
|
||||
};
|
||||
// firestore: FirebaseModuleAndStatics<RNFirebase.firestore.Firestore>;
|
||||
};
|
||||
firestore: FirebaseModuleAndStatics<RNFirebase.firestore.Firestore, RNFirebase.firestore.FirestoreStatics>;
|
||||
links: FirebaseModuleAndStatics<RNFirebase.links.Links>;
|
||||
messaging: FirebaseModuleAndStatics<RNFirebase.messaging.Messaging>;
|
||||
// perf: FirebaseModuleAndStatics<RNFirebase.perf.Perf>;
|
||||
@ -58,7 +58,7 @@ declare module "react-native-firebase" {
|
||||
fabric: {
|
||||
crashlytics(): RNFirebase.crashlytics.Crashlytics,
|
||||
};
|
||||
// firestore(): RNFirebase.firestore.Firestore;
|
||||
firestore(): RNFirebase.firestore.Firestore;
|
||||
links(): RNFirebase.links.Links;
|
||||
messaging(): RNFirebase.messaging.Messaging;
|
||||
// perf(): RNFirebase.perf.Performance;
|
||||
@ -1043,7 +1043,7 @@ declare module "react-native-firebase" {
|
||||
*/
|
||||
onLink(listener: (url) => void): () => void;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configuration when creating a Dynamic Link (standard or short). For
|
||||
* more information about each parameter, see the official Firebase docs:
|
||||
@ -1076,5 +1076,259 @@ declare module "react-native-firebase" {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
namespace firestore {
|
||||
interface Firestore {
|
||||
batch(): WriteBatch;
|
||||
collection(collectionPath: string): CollectionReference;
|
||||
doc(documentPath: string): DocumentReference;
|
||||
|
||||
/** NOT SUPPORTED YET */
|
||||
// enablePersistence(): Promise<void>;
|
||||
/** NOT SUPPORTED YET */
|
||||
// runTransaction(): Promise<any>;
|
||||
/** NOT SUPPORTED YET */
|
||||
// settings(): void;
|
||||
}
|
||||
|
||||
interface FirestoreStatics {
|
||||
FieldPath: typeof FieldPath;
|
||||
FieldValue: typeof FieldValue;
|
||||
GeoPoint: typeof GeoPoint;
|
||||
enableLogging(enabled: boolean): void;
|
||||
}
|
||||
|
||||
interface CollectionReference {
|
||||
readonly firestore: Firestore;
|
||||
readonly id: string;
|
||||
readonly parent: DocumentReference;
|
||||
add(data: object): Promise<DocumentReference>;
|
||||
doc(documentPath?: string): DocumentReference;
|
||||
endAt(snapshot: DocumentSnapshot): Query;
|
||||
endAt(...varargs: any[]): Query;
|
||||
endBefore(snapshot: DocumentSnapshot): Query;
|
||||
endBefore(...varargs: any[]): Query;
|
||||
get(): Promise<QuerySnapshot>;
|
||||
limit(limit: number): Query;
|
||||
onSnapshot(onNext: Query.ObserverOnNext, onError?: Query.ObserverOnError): () => void;
|
||||
onSnapshot(observer: Query.Observer): () => void;
|
||||
onSnapshot(queryListenOptions: Query.QueryListenOptions, onNext: Query.ObserverOnNext, onError?: Query.ObserverOnError): () => void;
|
||||
onSnapshot(queryListenOptions: Query.QueryListenOptions, observer: Query.Observer): () => void;
|
||||
orderBy(fieldPath: string | FieldPath, directionStr?: Types.QueryDirection): Query;
|
||||
startAfter(snapshot: DocumentSnapshot): Query;
|
||||
startAfter(...varargs: any[]): Query;
|
||||
startAt(snapshot: DocumentSnapshot): Query;
|
||||
startAt(...varargs: any[]): Query;
|
||||
where(fieldPath: string, op: Types.QueryOperator, value: any): Query;
|
||||
}
|
||||
|
||||
interface DocumentChange {
|
||||
readonly doc: DocumentSnapshot;
|
||||
readonly newIndex: number;
|
||||
readonly oldIndex: number;
|
||||
readonly type: string;
|
||||
}
|
||||
|
||||
interface DocumentReference {
|
||||
readonly firestore: Firestore;
|
||||
readonly id: string | null;
|
||||
readonly parent: CollectionReference;
|
||||
readonly path: string;
|
||||
collection(collectionPath: string): CollectionReference;
|
||||
delete(): Promise<void>;
|
||||
get(): Promise<DocumentSnapshot>;
|
||||
onSnapshot(onNext: DocumentReference.ObserverOnNext, onError?: DocumentReference.ObserverOnError): () => void;
|
||||
onSnapshot(observer: DocumentReference.Observer): () => void;
|
||||
onSnapshot(documentListenOptions: DocumentReference.DocumentListenOptions, onNext: DocumentReference.ObserverOnNext, onError?: DocumentReference.ObserverOnError): () => void;
|
||||
onSnapshot(documentListenOptions: DocumentReference.DocumentListenOptions, observer: DocumentReference.Observer): () => void;
|
||||
set(data: object, writeOptions?: Types.WriteOptions): Promise<void>;
|
||||
update(obj: object): Promise<void>;
|
||||
update(key1: Types.UpdateKey, val1: any): Promise<void>;
|
||||
update(key1: Types.UpdateKey, val1: any, key2: Types.UpdateKey, val2: any): Promise<void>;
|
||||
update(key1: Types.UpdateKey, val1: any, key2: Types.UpdateKey, val2: any, key3: Types.UpdateKey, val3: any): Promise<void>;
|
||||
update(key1: Types.UpdateKey, val1: any, key2: Types.UpdateKey, val2: any, key3: Types.UpdateKey, val3: any, key4: Types.UpdateKey, val4: any): Promise<void>;
|
||||
update(key1: Types.UpdateKey, val1: any, key2: Types.UpdateKey, val2: any, key3: Types.UpdateKey, val3: any, key4: Types.UpdateKey, val4: any, key5: Types.UpdateKey, val5: any): Promise<void>;
|
||||
}
|
||||
namespace DocumentReference {
|
||||
interface DocumentListenOptions {
|
||||
includeMetadataChanges: boolean;
|
||||
}
|
||||
|
||||
type ObserverOnNext = (documentSnapshot: DocumentSnapshot) => void;
|
||||
type ObserverOnError = (err: object) => void;
|
||||
interface Observer {
|
||||
next: ObserverOnNext;
|
||||
error?: ObserverOnError;
|
||||
}
|
||||
}
|
||||
|
||||
interface DocumentSnapshot {
|
||||
readonly exists: boolean;
|
||||
readonly id: string | null;
|
||||
readonly metadata: Types.SnapshotMetadata;
|
||||
readonly ref: DocumentReference;
|
||||
data(): object | void;
|
||||
get(fieldPath: string | FieldPath): any | undefined;
|
||||
}
|
||||
|
||||
class FieldPath {
|
||||
static documentId(): FieldPath;
|
||||
constructor(...segments: string[]);
|
||||
}
|
||||
|
||||
class FieldValue {
|
||||
static delete(): FieldValue;
|
||||
static serverTimestamp(): FieldValue;
|
||||
}
|
||||
|
||||
class GeoPoint {
|
||||
constructor(latitude: number, longitude: number);
|
||||
readonly latitude: number;
|
||||
readonly longitude: number;
|
||||
}
|
||||
|
||||
class Path {
|
||||
static fromName(name: string): Path;
|
||||
constructor(pathComponents: string[]);
|
||||
readonly id: string | null;
|
||||
readonly isDocument: boolean;
|
||||
readonly isCollection: boolean;
|
||||
readonly relativeName: string;
|
||||
child(relativePath: string): Path;
|
||||
parent(): Path | null;
|
||||
}
|
||||
|
||||
interface Query {
|
||||
readonly firestore: Firestore;
|
||||
endAt(snapshot: DocumentSnapshot): Query;
|
||||
endAt(...varargs: any[]): Query;
|
||||
endBefore(snapshot: DocumentSnapshot): Query;
|
||||
endBefore(...varargs: any[]): Query;
|
||||
get(): Promise<QuerySnapshot>;
|
||||
limit(limit: number): Query;
|
||||
onSnapshot(onNext: Query.ObserverOnNext, onError?: Query.ObserverOnError): () => void;
|
||||
onSnapshot(observer: Query.Observer): () => void;
|
||||
onSnapshot(queryListenOptions: Query.QueryListenOptions, onNext: Query.ObserverOnNext, onError?: Query.ObserverOnError): () => void;
|
||||
onSnapshot(queryListenOptions: Query.QueryListenOptions, observer: Query.Observer): () => void;
|
||||
orderBy(fieldPath: string | FieldPath, directionStr?: Types.QueryDirection): Query;
|
||||
startAfter(snapshot: DocumentSnapshot): Query;
|
||||
startAfter(...varargs: any[]): Query;
|
||||
startAt(snapshot: DocumentSnapshot): Query;
|
||||
startAt(...varargs: any[]): Query;
|
||||
where(fieldPath: string, op: Types.QueryOperator, value: any): Query;
|
||||
}
|
||||
namespace Query {
|
||||
interface NativeFieldPath {
|
||||
elements?: string[];
|
||||
string?: string;
|
||||
type: 'fieldpath' | 'string';
|
||||
}
|
||||
|
||||
interface FieldFilter {
|
||||
fieldPath: NativeFieldPath;
|
||||
operator: string;
|
||||
value: any;
|
||||
}
|
||||
|
||||
interface FieldOrder {
|
||||
direction: string;
|
||||
fieldPath: NativeFieldPath;
|
||||
}
|
||||
|
||||
interface QueryOptions {
|
||||
endAt?: any[];
|
||||
endBefore?: any[];
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
selectFields?: string[];
|
||||
startAfter?: any[];
|
||||
startAt?: any[];
|
||||
}
|
||||
|
||||
// The JS code expects at least one of 'includeDocumentMetadataChanges'
|
||||
// or 'includeQueryMetadataChanges' to be defined.
|
||||
interface _IncludeDocumentMetadataChanges {
|
||||
includeDocumentMetadataChanges: boolean;
|
||||
}
|
||||
interface _IncludeQueryMetadataChanges {
|
||||
includeQueryMetadataChanges: boolean;
|
||||
}
|
||||
type QueryListenOptions = _IncludeDocumentMetadataChanges | _IncludeQueryMetadataChanges | (_IncludeDocumentMetadataChanges & _IncludeQueryMetadataChanges);
|
||||
|
||||
type ObserverOnNext = (querySnapshot: QuerySnapshot) => void;
|
||||
type ObserverOnError = (err: object) => void;
|
||||
interface Observer {
|
||||
next: ObserverOnNext;
|
||||
error?: ObserverOnError;
|
||||
}
|
||||
}
|
||||
|
||||
interface QuerySnapshot {
|
||||
readonly docChanges: DocumentChange[];
|
||||
readonly docs: DocumentSnapshot[];
|
||||
readonly empty: boolean;
|
||||
readonly metadata: Types.SnapshotMetadata;
|
||||
readonly query: Query;
|
||||
readonly size: number;
|
||||
forEach(callback: (snapshot: DocumentSnapshot) => any);
|
||||
}
|
||||
namespace QuerySnapshot {
|
||||
interface NativeData {
|
||||
changes: Types.NativeDocumentChange[];
|
||||
documents: Types.NativeDocumentSnapshot[];
|
||||
metadata: Types.SnapshotMetadata;
|
||||
}
|
||||
}
|
||||
|
||||
interface WriteBatch {
|
||||
commit(): Promise<void>;
|
||||
delete(docRef: DocumentReference): WriteBatch;
|
||||
set(docRef: DocumentReference, data: object, options?: Types.WriteOptions): WriteBatch;
|
||||
// multiple overrides for update() to allow strong-typed var_args
|
||||
update(docRef: DocumentReference, obj: object): WriteBatch;
|
||||
update(docRef: DocumentReference, key1: Types.UpdateKey, val1: any): WriteBatch;
|
||||
update(docRef: DocumentReference, key1: Types.UpdateKey, val1: any, key2: Types.UpdateKey, val2: any): WriteBatch;
|
||||
update(docRef: DocumentReference, key1: Types.UpdateKey, val1: any, key2: Types.UpdateKey, val2: any, key3: Types.UpdateKey, val3: any): WriteBatch;
|
||||
update(docRef: DocumentReference, key1: Types.UpdateKey, val1: any, key2: Types.UpdateKey, val2: any, key3: Types.UpdateKey, val3: any, key4: Types.UpdateKey, val4: any): WriteBatch;
|
||||
update(docRef: DocumentReference, key1: Types.UpdateKey, val1: any, key2: Types.UpdateKey, val2: any, key3: Types.UpdateKey, val3: any, key4: Types.UpdateKey, val4: any, key5: Types.UpdateKey, val5: any): WriteBatch;
|
||||
}
|
||||
|
||||
namespace Types {
|
||||
interface NativeDocumentChange {
|
||||
document: NativeDocumentSnapshot;
|
||||
newIndex: number;
|
||||
oldIndex: number;
|
||||
type: string;
|
||||
}
|
||||
|
||||
interface NativeDocumentSnapshot {
|
||||
data: {
|
||||
[key: string]: TypeMap;
|
||||
};
|
||||
metadata: SnapshotMetadata;
|
||||
path: string;
|
||||
}
|
||||
|
||||
interface SnapshotMetadata {
|
||||
fromCache: boolean;
|
||||
hasPendingWrites: boolean;
|
||||
}
|
||||
|
||||
type QueryDirection = 'asc' | 'ASC' | 'desc' | 'DESC';
|
||||
type QueryOperator = '=' | '==' | '>' | '>=' | '<' | '<=';
|
||||
|
||||
interface TypeMap {
|
||||
type: 'array' | 'boolean' | 'date' | 'documentid' | 'fieldvalue' | 'geopoint' | 'null' | 'number' | 'object' | 'reference' | 'string';
|
||||
value: any;
|
||||
}
|
||||
|
||||
/** The key in update() function for DocumentReference and WriteBatch. */
|
||||
type UpdateKey = string | FieldPath
|
||||
|
||||
interface WriteOptions {
|
||||
merge?: boolean;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,13 +11,15 @@ const adMobPropTypes = {
|
||||
...ViewPropTypes,
|
||||
size: PropTypes.string.isRequired,
|
||||
unitId: PropTypes.string.isRequired,
|
||||
/* eslint-disable react/forbid-prop-types */
|
||||
request: PropTypes.object,
|
||||
video: PropTypes.object,
|
||||
/* eslint-enable react/forbid-prop-types */
|
||||
};
|
||||
Object.keys(EventTypes).forEach((eventType) => {
|
||||
Object.keys(EventTypes).forEach(eventType => {
|
||||
adMobPropTypes[eventType] = PropTypes.func;
|
||||
});
|
||||
Object.keys(NativeExpressEventTypes).forEach((eventType) => {
|
||||
Object.keys(NativeExpressEventTypes).forEach(eventType => {
|
||||
adMobPropTypes[eventType] = PropTypes.func;
|
||||
});
|
||||
|
||||
@ -67,7 +69,8 @@ class AdMobComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
if (nativeEvent.type === 'onSizeChange') this.updateSize(nativeEvent.payload);
|
||||
if (nativeEvent.type === 'onSizeChange')
|
||||
this.updateSize(nativeEvent.payload);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,4 @@
|
||||
export default class AdRequest {
|
||||
|
||||
constructor() {
|
||||
this._props = {
|
||||
keywords: [],
|
||||
@ -12,7 +11,7 @@ export default class AdRequest {
|
||||
}
|
||||
|
||||
addTestDevice(deviceId?: string) {
|
||||
this._props.testDevices.push(deviceId ? deviceId : 'DEVICE_ID_EMULATOR');
|
||||
this._props.testDevices.push(deviceId || 'DEVICE_ID_EMULATOR');
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,7 @@ import React from 'react';
|
||||
import AdMobComponent from './AdMobComponent';
|
||||
|
||||
function Banner({ ...props }) {
|
||||
return (
|
||||
<AdMobComponent
|
||||
{...props}
|
||||
class={'RNFirebaseAdMobBanner'}
|
||||
/>
|
||||
);
|
||||
return <AdMobComponent {...props} class="RNFirebaseAdMobBanner" />;
|
||||
}
|
||||
|
||||
Banner.propTypes = AdMobComponent.propTypes;
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
export default {
|
||||
onAdLoaded: 'onAdLoaded',
|
||||
onAdOpened: 'onAdOpened',
|
||||
@ -18,4 +17,4 @@ export const NativeExpressEventTypes = {
|
||||
export const RewardedVideoEventTypes = {
|
||||
onRewarded: 'onRewarded',
|
||||
onRewardedVideoStarted: 'onRewardedVideoStarted',
|
||||
};
|
||||
};
|
||||
|
@ -9,7 +9,6 @@ const FirebaseAdMob = NativeModules.RNFirebaseAdMob;
|
||||
let subscriptions = [];
|
||||
|
||||
export default class Interstitial {
|
||||
|
||||
constructor(admob: Object, adUnit: string) {
|
||||
// Interstitials on iOS require a new instance each time
|
||||
if (Platform.OS === 'ios') {
|
||||
@ -25,7 +24,10 @@ export default class Interstitial {
|
||||
this.adUnit = adUnit;
|
||||
this.loaded = false;
|
||||
SharedEventEmitter.removeAllListeners(`interstitial_${adUnit}`);
|
||||
SharedEventEmitter.addListener(`interstitial_${adUnit}`, this._onInterstitialEvent);
|
||||
SharedEventEmitter.addListener(
|
||||
`interstitial_${adUnit}`,
|
||||
this._onInterstitialEvent
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -33,7 +35,7 @@ export default class Interstitial {
|
||||
* @param event
|
||||
* @private
|
||||
*/
|
||||
_onInterstitialEvent = (event) => {
|
||||
_onInterstitialEvent = event => {
|
||||
const eventType = `interstitial:${this.adUnit}:${event.type}`;
|
||||
|
||||
let emitData = Object.assign({}, event);
|
||||
@ -94,11 +96,18 @@ export default class Interstitial {
|
||||
*/
|
||||
on(eventType, listenerCb) {
|
||||
if (!statics.EventTypes[eventType]) {
|
||||
console.warn(`Invalid event type provided, must be one of: ${Object.keys(statics.EventTypes).join(', ')}`);
|
||||
console.warn(
|
||||
`Invalid event type provided, must be one of: ${Object.keys(
|
||||
statics.EventTypes
|
||||
).join(', ')}`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const sub = SharedEventEmitter.addListener(`interstitial:${this.adUnit}:${eventType}`, listenerCb);
|
||||
const sub = SharedEventEmitter.addListener(
|
||||
`interstitial:${this.adUnit}:${eventType}`,
|
||||
listenerCb
|
||||
);
|
||||
subscriptions.push(sub);
|
||||
return sub;
|
||||
}
|
||||
|
@ -2,12 +2,7 @@ import React from 'react';
|
||||
import AdMobComponent from './AdMobComponent';
|
||||
|
||||
function NativeExpress({ ...props }) {
|
||||
return (
|
||||
<AdMobComponent
|
||||
{...props}
|
||||
class={'RNFirebaseAdMobNativeExpress'}
|
||||
/>
|
||||
);
|
||||
return <AdMobComponent {...props} class="RNFirebaseAdMobNativeExpress" />;
|
||||
}
|
||||
|
||||
NativeExpress.propTypes = AdMobComponent.propTypes;
|
||||
|
@ -9,7 +9,6 @@ const FirebaseAdMob = NativeModules.RNFirebaseAdMob;
|
||||
let subscriptions = [];
|
||||
|
||||
export default class RewardedVideo {
|
||||
|
||||
constructor(admob: Object, adUnit: string) {
|
||||
for (let i = 0, len = subscriptions.length; i < len; i++) {
|
||||
subscriptions[i].remove();
|
||||
@ -20,7 +19,10 @@ export default class RewardedVideo {
|
||||
this.adUnit = adUnit;
|
||||
this.loaded = false;
|
||||
SharedEventEmitter.removeAllListeners(`rewarded_video_${adUnit}`);
|
||||
SharedEventEmitter.addListener(`rewarded_video_${adUnit}`, this._onRewardedVideoEvent);
|
||||
SharedEventEmitter.addListener(
|
||||
`rewarded_video_${adUnit}`,
|
||||
this._onRewardedVideoEvent
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -28,7 +30,7 @@ export default class RewardedVideo {
|
||||
* @param event
|
||||
* @private
|
||||
*/
|
||||
_onRewardedVideoEvent = (event) => {
|
||||
_onRewardedVideoEvent = event => {
|
||||
const eventType = `rewarded_video:${this.adUnit}:${event.type}`;
|
||||
|
||||
let emitData = Object.assign({}, event);
|
||||
@ -94,11 +96,18 @@ export default class RewardedVideo {
|
||||
};
|
||||
|
||||
if (!types[eventType]) {
|
||||
console.warn(`Invalid event type provided, must be one of: ${Object.keys(types).join(', ')}`);
|
||||
console.warn(
|
||||
`Invalid event type provided, must be one of: ${Object.keys(types).join(
|
||||
', '
|
||||
)}`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const sub = SharedEventEmitter.addListener(`rewarded_video:${this.adUnit}:${eventType}`, listenerCb);
|
||||
const sub = SharedEventEmitter.addListener(
|
||||
`rewarded_video:${this.adUnit}:${eventType}`,
|
||||
listenerCb
|
||||
);
|
||||
subscriptions.push(sub);
|
||||
return sub;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
export default class VideoOptions {
|
||||
|
||||
constructor() {
|
||||
this._props = {
|
||||
startMuted: true,
|
||||
|
@ -25,12 +25,9 @@ type NativeEvent = {
|
||||
adUnit: string,
|
||||
payload: Object,
|
||||
type: string,
|
||||
}
|
||||
};
|
||||
|
||||
const NATIVE_EVENTS = [
|
||||
'interstitial_event',
|
||||
'rewarded_video_event',
|
||||
];
|
||||
const NATIVE_EVENTS = ['interstitial_event', 'rewarded_video_event'];
|
||||
|
||||
export const MODULE_NAME = 'RNFirebaseAdmob';
|
||||
export const NAMESPACE = 'admob';
|
||||
@ -50,8 +47,14 @@ export default class AdMob extends ModuleBase {
|
||||
this._initialized = false;
|
||||
this._appId = null;
|
||||
|
||||
SharedEventEmitter.addListener('interstitial_event', this._onInterstitialEvent.bind(this));
|
||||
SharedEventEmitter.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 {
|
||||
@ -88,7 +91,9 @@ export default class AdMob extends ModuleBase {
|
||||
|
||||
openDebugMenu(): void {
|
||||
if (!this._initialized) {
|
||||
getLogger(this).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 {
|
||||
getLogger(this).info('Opening debug menu');
|
||||
getNativeModule(this).openDebugMenu(this._appId);
|
||||
|
@ -46,16 +46,21 @@ export default class Analytics extends ModuleBase {
|
||||
logEvent(name: string, params: Object = {}): void {
|
||||
// check name is not a reserved event name
|
||||
if (ReservedEventNames.includes(name)) {
|
||||
throw new Error(`event name '${name}' is a reserved event name and can not be used.`);
|
||||
throw new Error(
|
||||
`event name '${name}' is a reserved event name and can not be used.`
|
||||
);
|
||||
}
|
||||
|
||||
// name format validation
|
||||
if (!AlphaNumericUnderscore.test(name)) {
|
||||
throw new Error(`Event name '${name}' is invalid. Names should contain 1 to 32 alphanumeric characters or underscores.`);
|
||||
throw new Error(
|
||||
`Event name '${name}' is invalid. Names should contain 1 to 32 alphanumeric characters or underscores.`
|
||||
);
|
||||
}
|
||||
|
||||
// maximum number of allowed params check
|
||||
if (params && Object.keys(params).length > 25) throw new Error('Maximum number of parameters exceeded (25).');
|
||||
if (params && Object.keys(params).length > 25)
|
||||
throw new Error('Maximum number of parameters exceeded (25).');
|
||||
|
||||
// Parameter names can be up to 24 characters long and must start with an alphabetic character
|
||||
// and contain only alphanumeric characters and underscores. Only String, long and double param
|
||||
@ -121,9 +126,9 @@ export default class Analytics extends ModuleBase {
|
||||
* @param object
|
||||
*/
|
||||
setUserProperties(object: Object): void {
|
||||
for (const property of Object.keys(object)) {
|
||||
Object.keys(object).forEach(property => {
|
||||
getNativeModule(this).setUserProperty(property, object[property]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,14 @@
|
||||
// @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 './';
|
||||
@ -50,9 +57,15 @@ export default class PhoneAuthListener {
|
||||
// internal events
|
||||
this._internalEvents = {
|
||||
codeSent: `phone:auth:${this._phoneAuthRequestKey}:onCodeSent`,
|
||||
verificationFailed: `phone:auth:${this._phoneAuthRequestKey}:onVerificationFailed`,
|
||||
verificationComplete: `phone:auth:${this._phoneAuthRequestKey}:onVerificationComplete`,
|
||||
codeAutoRetrievalTimeout: `phone:auth:${this._phoneAuthRequestKey}:onCodeAutoRetrievalTimeout`,
|
||||
verificationFailed: `phone:auth:${
|
||||
this._phoneAuthRequestKey
|
||||
}:onVerificationFailed`,
|
||||
verificationComplete: `phone:auth:${
|
||||
this._phoneAuthRequestKey
|
||||
}:onVerificationComplete`,
|
||||
codeAutoRetrievalTimeout: `phone:auth:${
|
||||
this._phoneAuthRequestKey
|
||||
}:onCodeAutoRetrievalTimeout`,
|
||||
};
|
||||
|
||||
// user observer events
|
||||
@ -73,14 +86,14 @@ export default class PhoneAuthListener {
|
||||
getNativeModule(this._auth).verifyPhoneNumber(
|
||||
phoneNumber,
|
||||
this._phoneAuthRequestKey,
|
||||
this._timeout,
|
||||
this._timeout
|
||||
);
|
||||
}
|
||||
|
||||
if (isIOS) {
|
||||
getNativeModule(this._auth).verifyPhoneNumber(
|
||||
phoneNumber,
|
||||
this._phoneAuthRequestKey,
|
||||
this._phoneAuthRequestKey
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -94,8 +107,11 @@ 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));
|
||||
SharedEventEmitter.once(
|
||||
this._internalEvents[type],
|
||||
// $FlowBug: Flow doesn't support indexable signatures on classes: https://github.com/facebook/flow/issues/1323
|
||||
this[`_${type}Handler`].bind(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,14 +159,15 @@ export default class PhoneAuthListener {
|
||||
* @private
|
||||
*/
|
||||
_removeAllListeners() {
|
||||
setTimeout(() => { // move to next event loop - not sure if needed
|
||||
setTimeout(() => {
|
||||
// move to next event loop - not sure if needed
|
||||
// internal listeners
|
||||
Object.values(this._internalEvents).forEach((event) => {
|
||||
Object.values(this._internalEvents).forEach(event => {
|
||||
SharedEventEmitter.removeAllListeners(event);
|
||||
});
|
||||
|
||||
// user observer listeners
|
||||
Object.values(this._publicEvents).forEach((publicEvent) => {
|
||||
Object.values(this._publicEvents).forEach(publicEvent => {
|
||||
SharedEventEmitter.removeAllListeners(publicEvent);
|
||||
});
|
||||
}, 0);
|
||||
@ -163,12 +180,12 @@ export default class PhoneAuthListener {
|
||||
_promiseDeferred() {
|
||||
if (!this._promise) {
|
||||
this._promise = new Promise((resolve, reject) => {
|
||||
this._resolve = (result) => {
|
||||
this._resolve = result => {
|
||||
this._resolve = null;
|
||||
return resolve(result);
|
||||
};
|
||||
|
||||
this._reject = (possibleError) => {
|
||||
this._reject = possibleError => {
|
||||
this._reject = null;
|
||||
return reject(possibleError);
|
||||
};
|
||||
@ -261,22 +278,36 @@ export default class PhoneAuthListener {
|
||||
this._removeAllListeners();
|
||||
}
|
||||
|
||||
|
||||
/* -------------
|
||||
-- PUBLIC API
|
||||
--------------*/
|
||||
|
||||
on(event: string, observer: () => PhoneAuthSnapshot, errorCb?: () => PhoneAuthError, successCb?: () => PhoneAuthSnapshot): this {
|
||||
on(
|
||||
event: string,
|
||||
observer: () => PhoneAuthSnapshot,
|
||||
errorCb?: () => PhoneAuthError,
|
||||
successCb?: () => PhoneAuthSnapshot
|
||||
): this {
|
||||
if (!isString(event)) {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_ARG_NAMED('event', 'string', 'on'));
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_MISSING_ARG_NAMED('event', 'string', 'on')
|
||||
);
|
||||
}
|
||||
|
||||
if (event !== 'state_changed') {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_ARG_INVALID_VALUE('event', 'state_changed', event));
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_ARG_INVALID_VALUE(
|
||||
'event',
|
||||
'state_changed',
|
||||
event
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!isFunction(observer)) {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_ARG_NAMED('observer', 'function', 'on'));
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_MISSING_ARG_NAMED('observer', 'function', 'on')
|
||||
);
|
||||
}
|
||||
|
||||
this._addUserObserver(observer);
|
||||
|
@ -6,7 +6,13 @@ import INTERNALS from '../../utils/internals';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type Auth from './';
|
||||
import type { ActionCodeSettings, AuthCredential, NativeUser, UserCredential, UserMetadata } from './types';
|
||||
import type {
|
||||
ActionCodeSettings,
|
||||
AuthCredential,
|
||||
NativeUser,
|
||||
UserCredential,
|
||||
UserMetadata,
|
||||
} from './types';
|
||||
|
||||
type UserInfo = {
|
||||
displayName?: string,
|
||||
@ -15,12 +21,12 @@ type UserInfo = {
|
||||
photoURL?: string,
|
||||
providerId: string,
|
||||
uid: string,
|
||||
}
|
||||
};
|
||||
|
||||
type UpdateProfile = {
|
||||
displayName?: string,
|
||||
photoURL?: string,
|
||||
}
|
||||
};
|
||||
|
||||
export default class User {
|
||||
_auth: Auth;
|
||||
@ -110,7 +116,9 @@ export default class User {
|
||||
* @return {Promise}
|
||||
*/
|
||||
getToken(forceRefresh: boolean = false): Promise<Object> {
|
||||
console.warn('Deprecated firebase.User.prototype.getToken in favor of firebase.User.prototype.getIdToken.');
|
||||
console.warn(
|
||||
'Deprecated firebase.User.prototype.getToken in favor of firebase.User.prototype.getIdToken.'
|
||||
);
|
||||
return getNativeModule(this._auth).getToken(forceRefresh);
|
||||
}
|
||||
|
||||
@ -119,9 +127,15 @@ export default class User {
|
||||
* @param credential
|
||||
*/
|
||||
linkWithCredential(credential: AuthCredential): Promise<User> {
|
||||
console.warn('Deprecated firebase.User.prototype.linkWithCredential in favor of firebase.User.prototype.linkAndRetrieveDataWithCredential.');
|
||||
console.warn(
|
||||
'Deprecated firebase.User.prototype.linkWithCredential in favor of firebase.User.prototype.linkAndRetrieveDataWithCredential.'
|
||||
);
|
||||
return getNativeModule(this._auth)
|
||||
.linkWithCredential(credential.providerId, credential.token, credential.secret)
|
||||
.linkWithCredential(
|
||||
credential.providerId,
|
||||
credential.token,
|
||||
credential.secret
|
||||
)
|
||||
.then(user => this._auth._setUser(user));
|
||||
}
|
||||
|
||||
@ -129,9 +143,15 @@ export default class User {
|
||||
*
|
||||
* @param credential
|
||||
*/
|
||||
linkAndRetrieveDataWithCredential(credential: AuthCredential): Promise<UserCredential> {
|
||||
linkAndRetrieveDataWithCredential(
|
||||
credential: AuthCredential
|
||||
): Promise<UserCredential> {
|
||||
return getNativeModule(this._auth)
|
||||
.linkAndRetrieveDataWithCredential(credential.providerId, credential.token, credential.secret)
|
||||
.linkAndRetrieveDataWithCredential(
|
||||
credential.providerId,
|
||||
credential.token,
|
||||
credential.secret
|
||||
)
|
||||
.then(userCredential => this._auth._setUserCredential(userCredential));
|
||||
}
|
||||
|
||||
@ -140,10 +160,16 @@ export default class User {
|
||||
* @return {Promise} A promise resolved upon completion
|
||||
*/
|
||||
reauthenticateWithCredential(credential: AuthCredential): Promise<void> {
|
||||
console.warn('Deprecated firebase.User.prototype.reauthenticateWithCredential in favor of firebase.User.prototype.reauthenticateAndRetrieveDataWithCredential.');
|
||||
console.warn(
|
||||
'Deprecated firebase.User.prototype.reauthenticateWithCredential in favor of firebase.User.prototype.reauthenticateAndRetrieveDataWithCredential.'
|
||||
);
|
||||
return getNativeModule(this._auth)
|
||||
.reauthenticateWithCredential(credential.providerId, credential.token, credential.secret)
|
||||
.then((user) => {
|
||||
.reauthenticateWithCredential(
|
||||
credential.providerId,
|
||||
credential.token,
|
||||
credential.secret
|
||||
)
|
||||
.then(user => {
|
||||
this._auth._setUser(user);
|
||||
});
|
||||
}
|
||||
@ -152,9 +178,15 @@ export default class User {
|
||||
* Re-authenticate a user with a third-party authentication provider
|
||||
* @return {Promise} A promise resolved upon completion
|
||||
*/
|
||||
reauthenticateAndRetrieveDataWithCredential(credential: AuthCredential): Promise<UserCredential> {
|
||||
reauthenticateAndRetrieveDataWithCredential(
|
||||
credential: AuthCredential
|
||||
): Promise<UserCredential> {
|
||||
return getNativeModule(this._auth)
|
||||
.reauthenticateAndRetrieveDataWithCredential(credential.providerId, credential.token, credential.secret)
|
||||
.reauthenticateAndRetrieveDataWithCredential(
|
||||
credential.providerId,
|
||||
credential.token,
|
||||
credential.secret
|
||||
)
|
||||
.then(userCredential => this._auth._setUserCredential(userCredential));
|
||||
}
|
||||
|
||||
@ -165,7 +197,7 @@ export default class User {
|
||||
reload(): Promise<void> {
|
||||
return getNativeModule(this._auth)
|
||||
.reload()
|
||||
.then((user) => {
|
||||
.then(user => {
|
||||
this._auth._setUser(user);
|
||||
});
|
||||
}
|
||||
@ -173,10 +205,12 @@ export default class User {
|
||||
/**
|
||||
* Send verification email to current user.
|
||||
*/
|
||||
sendEmailVerification(actionCodeSettings?: ActionCodeSettings): Promise<void> {
|
||||
sendEmailVerification(
|
||||
actionCodeSettings?: ActionCodeSettings
|
||||
): Promise<void> {
|
||||
return getNativeModule(this._auth)
|
||||
.sendEmailVerification(actionCodeSettings)
|
||||
.then((user) => {
|
||||
.then(user => {
|
||||
this._auth._setUser(user);
|
||||
});
|
||||
}
|
||||
@ -205,7 +239,7 @@ export default class User {
|
||||
updateEmail(email: string): Promise<void> {
|
||||
return getNativeModule(this._auth)
|
||||
.updateEmail(email)
|
||||
.then((user) => {
|
||||
.then(user => {
|
||||
this._auth._setUser(user);
|
||||
});
|
||||
}
|
||||
@ -218,7 +252,7 @@ export default class User {
|
||||
updatePassword(password: string): Promise<void> {
|
||||
return getNativeModule(this._auth)
|
||||
.updatePassword(password)
|
||||
.then((user) => {
|
||||
.then(user => {
|
||||
this._auth._setUser(user);
|
||||
});
|
||||
}
|
||||
@ -231,7 +265,7 @@ export default class User {
|
||||
updateProfile(updates: UpdateProfile = {}): Promise<void> {
|
||||
return getNativeModule(this._auth)
|
||||
.updateProfile(updates)
|
||||
.then((user) => {
|
||||
.then(user => {
|
||||
this._auth._setUser(user);
|
||||
});
|
||||
}
|
||||
@ -241,34 +275,68 @@ export default class User {
|
||||
*/
|
||||
|
||||
linkWithPhoneNumber() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('User', 'linkWithPhoneNumber'));
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD(
|
||||
'User',
|
||||
'linkWithPhoneNumber'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
linkWithPopup() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('User', 'linkWithPopup'));
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('User', 'linkWithPopup')
|
||||
);
|
||||
}
|
||||
|
||||
linkWithRedirect() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('User', 'linkWithRedirect'));
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD(
|
||||
'User',
|
||||
'linkWithRedirect'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
reauthenticateWithPhoneNumber() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('User', 'reauthenticateWithPhoneNumber'));
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD(
|
||||
'User',
|
||||
'reauthenticateWithPhoneNumber'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
reauthenticateWithPopup() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('User', 'reauthenticateWithPopup'));
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD(
|
||||
'User',
|
||||
'reauthenticateWithPopup'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
reauthenticateWithRedirect() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('User', 'reauthenticateWithRedirect'));
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD(
|
||||
'User',
|
||||
'reauthenticateWithRedirect'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
updatePhoneNumber() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('User', 'updatePhoneNumber'));
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD(
|
||||
'User',
|
||||
'updatePhoneNumber'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
get refreshToken(): string {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_PROPERTY('User', 'refreshToken'));
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_PROPERTY('User', 'refreshToken')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,13 @@ import FacebookAuthProvider from './providers/FacebookAuthProvider';
|
||||
|
||||
import PhoneAuthListener from './PhoneAuthListener';
|
||||
|
||||
import type { ActionCodeSettings, AuthCredential, NativeUser, NativeUserCredential, UserCredential } from './types';
|
||||
import type {
|
||||
ActionCodeSettings,
|
||||
AuthCredential,
|
||||
NativeUser,
|
||||
NativeUserCredential,
|
||||
UserCredential,
|
||||
} from './types';
|
||||
import type App from '../core/firebase-app';
|
||||
|
||||
type AuthState = {
|
||||
@ -34,7 +40,7 @@ type ActionCodeInfo = {
|
||||
fromEmail?: string,
|
||||
},
|
||||
operation: 'PASSWORD_RESET' | 'VERIFY_EMAIL' | 'RECOVER_EMAIL',
|
||||
}
|
||||
};
|
||||
|
||||
const NATIVE_EVENTS = [
|
||||
'auth_state_changed',
|
||||
@ -59,7 +65,9 @@ export default class Auth extends ModuleBase {
|
||||
});
|
||||
this._user = null;
|
||||
this._authResult = false;
|
||||
this._languageCode = getNativeModule(this).APP_LANGUAGE[app._name] || getNativeModule(this).APP_LANGUAGE['[DEFAULT]'];
|
||||
this._languageCode =
|
||||
getNativeModule(this).APP_LANGUAGE[app._name] ||
|
||||
getNativeModule(this).APP_LANGUAGE['[DEFAULT]'];
|
||||
|
||||
SharedEventEmitter.addListener(
|
||||
// sub to internal native event - this fans out to
|
||||
@ -67,8 +75,11 @@ export default class Auth extends ModuleBase {
|
||||
getAppEventName(this, 'auth_state_changed'),
|
||||
(state: AuthState) => {
|
||||
this._setUser(state.user);
|
||||
SharedEventEmitter.emit(getAppEventName(this, 'onAuthStateChanged'), this._user);
|
||||
},
|
||||
SharedEventEmitter.emit(
|
||||
getAppEventName(this, 'onAuthStateChanged'),
|
||||
this._user
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
SharedEventEmitter.addListener(
|
||||
@ -78,7 +89,7 @@ export default class Auth extends ModuleBase {
|
||||
(event: Object) => {
|
||||
const eventKey = `phone:auth:${event.requestKey}:${event.type}`;
|
||||
SharedEventEmitter.emit(eventKey, event.state);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
SharedEventEmitter.addListener(
|
||||
@ -87,8 +98,11 @@ export default class Auth extends ModuleBase {
|
||||
getAppEventName(this, 'auth_id_token_changed'),
|
||||
(auth: AuthState) => {
|
||||
this._setUser(auth.user);
|
||||
SharedEventEmitter.emit(getAppEventName(this, 'onIdTokenChanged'), this._user);
|
||||
},
|
||||
SharedEventEmitter.emit(
|
||||
getAppEventName(this, 'onIdTokenChanged'),
|
||||
this._user
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
getNativeModule(this).addAuthStateListener();
|
||||
@ -123,12 +137,18 @@ export default class Auth extends ModuleBase {
|
||||
*/
|
||||
onAuthStateChanged(listener: Function) {
|
||||
getLogger(this).info('Creating onAuthStateChanged listener');
|
||||
SharedEventEmitter.addListener(getAppEventName(this, 'onAuthStateChanged'), listener);
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this, 'onAuthStateChanged'),
|
||||
listener
|
||||
);
|
||||
if (this._authResult) listener(this._user || null);
|
||||
|
||||
return () => {
|
||||
getLogger(this).info('Removing onAuthStateChanged listener');
|
||||
SharedEventEmitter.removeListener(getAppEventName(this, 'onAuthStateChanged'), listener);
|
||||
SharedEventEmitter.removeListener(
|
||||
getAppEventName(this, 'onAuthStateChanged'),
|
||||
listener
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@ -138,12 +158,18 @@ export default class Auth extends ModuleBase {
|
||||
*/
|
||||
onIdTokenChanged(listener: Function) {
|
||||
getLogger(this).info('Creating onIdTokenChanged listener');
|
||||
SharedEventEmitter.addListener(getAppEventName(this, 'onIdTokenChanged'), listener);
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this, 'onIdTokenChanged'),
|
||||
listener
|
||||
);
|
||||
if (this._authResult) listener(this._user || null);
|
||||
|
||||
return () => {
|
||||
getLogger(this).info('Removing onIdTokenChanged listener');
|
||||
SharedEventEmitter.removeListener(getAppEventName(this, 'onIdTokenChanged'), listener);
|
||||
SharedEventEmitter.removeListener(
|
||||
getAppEventName(this, 'onIdTokenChanged'),
|
||||
listener
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@ -153,12 +179,18 @@ export default class Auth extends ModuleBase {
|
||||
*/
|
||||
onUserChanged(listener: Function) {
|
||||
getLogger(this).info('Creating onUserChanged listener');
|
||||
SharedEventEmitter.addListener(getAppEventName(this, 'onUserChanged'), listener);
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this, 'onUserChanged'),
|
||||
listener
|
||||
);
|
||||
if (this._authResult) listener(this._user || null);
|
||||
|
||||
return () => {
|
||||
getLogger(this).info('Removing onUserChanged listener');
|
||||
SharedEventEmitter.removeListener(getAppEventName(this, 'onUserChanged'), listener);
|
||||
SharedEventEmitter.removeListener(
|
||||
getAppEventName(this, 'onUserChanged'),
|
||||
listener
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@ -180,7 +212,9 @@ export default class Auth extends ModuleBase {
|
||||
* @return {Promise} A promise resolved upon completion
|
||||
*/
|
||||
signInAnonymously(): Promise<User> {
|
||||
console.warn('Deprecated firebase.User.prototype.signInAnonymously in favor of firebase.User.prototype.signInAnonymouslyAndRetrieveData.');
|
||||
console.warn(
|
||||
'Deprecated firebase.User.prototype.signInAnonymously in favor of firebase.User.prototype.signInAnonymouslyAndRetrieveData.'
|
||||
);
|
||||
return getNativeModule(this)
|
||||
.signInAnonymously()
|
||||
.then(user => this._setUser(user));
|
||||
@ -203,8 +237,13 @@ 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<User> {
|
||||
console.warn('Deprecated firebase.User.prototype.createUserWithEmailAndPassword in favor of firebase.User.prototype.createUserAndRetrieveDataWithEmailAndPassword.');
|
||||
createUserWithEmailAndPassword(
|
||||
email: string,
|
||||
password: string
|
||||
): Promise<User> {
|
||||
console.warn(
|
||||
'Deprecated firebase.User.prototype.createUserWithEmailAndPassword in favor of firebase.User.prototype.createUserAndRetrieveDataWithEmailAndPassword.'
|
||||
);
|
||||
return getNativeModule(this)
|
||||
.createUserWithEmailAndPassword(email, password)
|
||||
.then(user => this._setUser(user));
|
||||
@ -216,7 +255,10 @@ export default class Auth extends ModuleBase {
|
||||
* @param {string} password The user's password
|
||||
* @return {Promise} A promise indicating the completion
|
||||
*/
|
||||
createUserAndRetrieveDataWithEmailAndPassword(email: string, password: string): Promise<User> {
|
||||
createUserAndRetrieveDataWithEmailAndPassword(
|
||||
email: string,
|
||||
password: string
|
||||
): Promise<User> {
|
||||
return getNativeModule(this)
|
||||
.createUserAndRetrieveDataWithEmailAndPassword(email, password)
|
||||
.then(userCredential => this._setUserCredential(userCredential));
|
||||
@ -230,7 +272,9 @@ export default class Auth extends ModuleBase {
|
||||
* @return {Promise} A promise that is resolved upon completion
|
||||
*/
|
||||
signInWithEmailAndPassword(email: string, password: string): Promise<User> {
|
||||
console.warn('Deprecated firebase.User.prototype.signInWithEmailAndPassword in favor of firebase.User.prototype.signInAndRetrieveDataWithEmailAndPassword.');
|
||||
console.warn(
|
||||
'Deprecated firebase.User.prototype.signInWithEmailAndPassword in favor of firebase.User.prototype.signInAndRetrieveDataWithEmailAndPassword.'
|
||||
);
|
||||
return getNativeModule(this)
|
||||
.signInWithEmailAndPassword(email, password)
|
||||
.then(user => this._setUser(user));
|
||||
@ -242,7 +286,10 @@ export default class Auth extends ModuleBase {
|
||||
* @param {string} password The user's password
|
||||
* @return {Promise} A promise that is resolved upon completion
|
||||
*/
|
||||
signInAndRetrieveDataWithEmailAndPassword(email: string, password: string): Promise<UserCredential> {
|
||||
signInAndRetrieveDataWithEmailAndPassword(
|
||||
email: string,
|
||||
password: string
|
||||
): Promise<UserCredential> {
|
||||
return getNativeModule(this)
|
||||
.signInAndRetrieveDataWithEmailAndPassword(email, password)
|
||||
.then(userCredential => this._setUserCredential(userCredential));
|
||||
@ -255,7 +302,9 @@ export default class Auth extends ModuleBase {
|
||||
* @return {Promise} A promise resolved upon completion
|
||||
*/
|
||||
signInWithCustomToken(customToken: string): Promise<User> {
|
||||
console.warn('Deprecated firebase.User.prototype.signInWithCustomToken in favor of firebase.User.prototype.signInAndRetrieveDataWithCustomToken.');
|
||||
console.warn(
|
||||
'Deprecated firebase.User.prototype.signInWithCustomToken in favor of firebase.User.prototype.signInAndRetrieveDataWithCustomToken.'
|
||||
);
|
||||
return getNativeModule(this)
|
||||
.signInWithCustomToken(customToken)
|
||||
.then(user => this._setUser(user));
|
||||
@ -266,7 +315,9 @@ export default class Auth extends ModuleBase {
|
||||
* @param {string} customToken A self-signed custom auth token.
|
||||
* @return {Promise} A promise resolved upon completion
|
||||
*/
|
||||
signInAndRetrieveDataWithCustomToken(customToken: string): Promise<UserCredential> {
|
||||
signInAndRetrieveDataWithCustomToken(
|
||||
customToken: string
|
||||
): Promise<UserCredential> {
|
||||
return getNativeModule(this)
|
||||
.signInAndRetrieveDataWithCustomToken(customToken)
|
||||
.then(userCredential => this._setUserCredential(userCredential));
|
||||
@ -278,9 +329,15 @@ export default class Auth extends ModuleBase {
|
||||
* @return {Promise} A promise resolved upon completion
|
||||
*/
|
||||
signInWithCredential(credential: AuthCredential): Promise<User> {
|
||||
console.warn('Deprecated firebase.User.prototype.signInWithCredential in favor of firebase.User.prototype.signInAndRetrieveDataWithCredential.');
|
||||
console.warn(
|
||||
'Deprecated firebase.User.prototype.signInWithCredential in favor of firebase.User.prototype.signInAndRetrieveDataWithCredential.'
|
||||
);
|
||||
return getNativeModule(this)
|
||||
.signInWithCredential(credential.providerId, credential.token, credential.secret)
|
||||
.signInWithCredential(
|
||||
credential.providerId,
|
||||
credential.token,
|
||||
credential.secret
|
||||
)
|
||||
.then(user => this._setUser(user));
|
||||
}
|
||||
|
||||
@ -288,9 +345,15 @@ export default class Auth extends ModuleBase {
|
||||
* Sign the user in with a third-party authentication provider
|
||||
* @return {Promise} A promise resolved upon completion
|
||||
*/
|
||||
signInAndRetrieveDataWithCredential(credential: AuthCredential): Promise<UserCredential> {
|
||||
signInAndRetrieveDataWithCredential(
|
||||
credential: AuthCredential
|
||||
): Promise<UserCredential> {
|
||||
return getNativeModule(this)
|
||||
.signInAndRetrieveDataWithCredential(credential.providerId, credential.token, credential.secret)
|
||||
.signInAndRetrieveDataWithCredential(
|
||||
credential.providerId,
|
||||
credential.token,
|
||||
credential.secret
|
||||
)
|
||||
.then(userCredential => this._setUserCredential(userCredential));
|
||||
}
|
||||
|
||||
@ -301,9 +364,7 @@ export default class Auth extends ModuleBase {
|
||||
signInWithPhoneNumber(phoneNumber: string): Promise<ConfirmationResult> {
|
||||
return getNativeModule(this)
|
||||
.signInWithPhoneNumber(phoneNumber)
|
||||
.then((result) => {
|
||||
return new ConfirmationResult(this, result.verificationId);
|
||||
});
|
||||
.then(result => new ConfirmationResult(this, result.verificationId));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -315,7 +376,10 @@ export default class Auth extends ModuleBase {
|
||||
* @param autoVerifyTimeout Android Only
|
||||
* @returns {PhoneAuthListener}
|
||||
*/
|
||||
verifyPhoneNumber(phoneNumber: string, autoVerifyTimeout?: number): PhoneAuthListener {
|
||||
verifyPhoneNumber(
|
||||
phoneNumber: string,
|
||||
autoVerifyTimeout?: number
|
||||
): PhoneAuthListener {
|
||||
return new PhoneAuthListener(this, phoneNumber, autoVerifyTimeout);
|
||||
}
|
||||
|
||||
@ -323,8 +387,14 @@ 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, actionCodeSettings?: ActionCodeSettings): Promise<void> {
|
||||
return getNativeModule(this).sendPasswordResetEmail(email, actionCodeSettings);
|
||||
sendPasswordResetEmail(
|
||||
email: string,
|
||||
actionCodeSettings?: ActionCodeSettings
|
||||
): Promise<void> {
|
||||
return getNativeModule(this).sendPasswordResetEmail(
|
||||
email,
|
||||
actionCodeSettings
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -400,24 +470,49 @@ 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'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
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'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// firebase issue - https://github.com/invertase/react-native-firebase/pull/655#issuecomment-349904680
|
||||
useDeviceLanguage() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD('auth', 'useDeviceLanguage'));
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_UNSUPPORTED_MODULE_METHOD(
|
||||
'auth',
|
||||
'useDeviceLanguage'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,9 @@ const providerId = 'password';
|
||||
|
||||
export default class EmailAuthProvider {
|
||||
constructor() {
|
||||
throw new Error('`new EmailAuthProvider()` is not supported on the native Firebase SDKs.');
|
||||
throw new Error(
|
||||
'`new EmailAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
}
|
||||
|
||||
static get PROVIDER_ID(): string {
|
||||
|
@ -8,7 +8,9 @@ const providerId = 'facebook.com';
|
||||
|
||||
export default class FacebookAuthProvider {
|
||||
constructor() {
|
||||
throw new Error('`new FacebookAuthProvider()` is not supported on the native Firebase SDKs.');
|
||||
throw new Error(
|
||||
'`new FacebookAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
}
|
||||
|
||||
static get PROVIDER_ID(): string {
|
||||
|
@ -8,7 +8,9 @@ const providerId = 'github.com';
|
||||
|
||||
export default class GithubAuthProvider {
|
||||
constructor() {
|
||||
throw new Error('`new GithubAuthProvider()` is not supported on the native Firebase SDKs.');
|
||||
throw new Error(
|
||||
'`new GithubAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
}
|
||||
|
||||
static get PROVIDER_ID(): string {
|
||||
|
@ -8,7 +8,9 @@ const providerId = 'google.com';
|
||||
|
||||
export default class GoogleAuthProvider {
|
||||
constructor() {
|
||||
throw new Error('`new GoogleAuthProvider()` is not supported on the native Firebase SDKs.');
|
||||
throw new Error(
|
||||
'`new GoogleAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
}
|
||||
|
||||
static get PROVIDER_ID(): string {
|
||||
|
@ -8,7 +8,9 @@ const providerId = 'oauth';
|
||||
|
||||
export default class OAuthProvider {
|
||||
constructor() {
|
||||
throw new Error('`new OAuthProvider()` is not supported on the native Firebase SDKs.');
|
||||
throw new Error(
|
||||
'`new OAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
}
|
||||
|
||||
static get PROVIDER_ID(): string {
|
||||
|
@ -8,7 +8,9 @@ const providerId = 'phone';
|
||||
|
||||
export default class PhoneAuthProvider {
|
||||
constructor() {
|
||||
throw new Error('`new PhoneAuthProvider()` is not supported on the native Firebase SDKs.');
|
||||
throw new Error(
|
||||
'`new PhoneAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
}
|
||||
|
||||
static get PROVIDER_ID(): string {
|
||||
|
@ -8,7 +8,9 @@ const providerId = 'twitter.com';
|
||||
|
||||
export default class TwitterAuthProvider {
|
||||
constructor() {
|
||||
throw new Error('`new TwitterAuthProvider()` is not supported on the native Firebase SDKs.');
|
||||
throw new Error(
|
||||
'`new TwitterAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
}
|
||||
|
||||
static get PROVIDER_ID(): string {
|
||||
|
@ -14,25 +14,25 @@ export type ActionCodeSettings = {
|
||||
bundleId?: string,
|
||||
},
|
||||
url: string,
|
||||
}
|
||||
};
|
||||
|
||||
type AdditionalUserInfo = {
|
||||
isNewUser: boolean,
|
||||
profile?: Object,
|
||||
providerId: string,
|
||||
username?: string,
|
||||
}
|
||||
};
|
||||
|
||||
export type AuthCredential = {
|
||||
providerId: string,
|
||||
token: string,
|
||||
secret: string
|
||||
}
|
||||
secret: string,
|
||||
};
|
||||
|
||||
export type UserCredential = {|
|
||||
additionalUserInfo?: AdditionalUserInfo,
|
||||
user: User,
|
||||
|}
|
||||
|};
|
||||
|
||||
export type UserInfo = {
|
||||
displayName?: string,
|
||||
@ -41,12 +41,12 @@ export type UserInfo = {
|
||||
photoURL?: string,
|
||||
providerId: string,
|
||||
uid: string,
|
||||
}
|
||||
};
|
||||
|
||||
export type UserMetadata = {
|
||||
creationTime?: string,
|
||||
lastSignInTime?: string,
|
||||
}
|
||||
};
|
||||
|
||||
export type NativeUser = {
|
||||
displayName?: string,
|
||||
@ -59,9 +59,9 @@ export type NativeUser = {
|
||||
providerData: UserInfo[],
|
||||
providerId: string,
|
||||
uid: string,
|
||||
}
|
||||
};
|
||||
|
||||
export type NativeUserCredential = {|
|
||||
additionalUserInfo?: AdditionalUserInfo,
|
||||
user: NativeUser,
|
||||
|}
|
||||
|};
|
||||
|
@ -13,8 +13,11 @@ type NativeValue = {
|
||||
numberValue?: number,
|
||||
dataValue?: Object,
|
||||
boolValue?: boolean,
|
||||
source: 'remoteConfigSourceRemote' | 'remoteConfigSourceDefault' | ' remoteConfigSourceStatic',
|
||||
}
|
||||
source:
|
||||
| 'remoteConfigSourceRemote'
|
||||
| 'remoteConfigSourceDefault'
|
||||
| ' remoteConfigSourceStatic',
|
||||
};
|
||||
|
||||
export const MODULE_NAME = 'RNFirebaseRemoteConfig';
|
||||
export const NAMESPACE = 'config';
|
||||
@ -44,9 +47,26 @@ export default class RemoteConfig extends ModuleBase {
|
||||
return {
|
||||
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.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;
|
||||
if (
|
||||
nativeValue.boolValue !== null &&
|
||||
(nativeValue.stringValue === 'true' ||
|
||||
nativeValue.stringValue === 'false' ||
|
||||
nativeValue.stringValue === null)
|
||||
)
|
||||
return nativeValue.boolValue;
|
||||
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;
|
||||
},
|
||||
};
|
||||
@ -70,7 +90,9 @@ export default class RemoteConfig extends ModuleBase {
|
||||
*/
|
||||
fetch(expiration?: number) {
|
||||
if (expiration !== undefined) {
|
||||
getLogger(this).debug(`Fetching remote config data with expiration ${expiration.toString()}`);
|
||||
getLogger(this).debug(
|
||||
`Fetching remote config data with expiration ${expiration.toString()}`
|
||||
);
|
||||
return getNativeModule(this).fetchWithExpirationDuration(expiration);
|
||||
}
|
||||
getLogger(this).debug('Fetching remote config data');
|
||||
@ -124,7 +146,7 @@ export default class RemoteConfig extends ModuleBase {
|
||||
getValues(keys: Array<String>) {
|
||||
return getNativeModule(this)
|
||||
.getValues(keys || [])
|
||||
.then((nativeValues) => {
|
||||
.then(nativeValues => {
|
||||
const values: { [String]: Object } = {};
|
||||
for (let i = 0, len = keys.length; i < len; i++) {
|
||||
values[keys[i]] = this._nativeValueToJS(nativeValues[i]);
|
||||
|
@ -13,7 +13,9 @@ 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 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';
|
||||
@ -22,15 +24,12 @@ import Performance, { NAMESPACE as PerfNamespace } from '../perf';
|
||||
import Storage, { NAMESPACE as StorageNamespace } from '../storage';
|
||||
import Utils, { NAMESPACE as UtilsNamespace } from '../utils';
|
||||
|
||||
import type {
|
||||
FirebaseOptions,
|
||||
} from '../../types';
|
||||
import type { FirebaseOptions } from '../../types';
|
||||
|
||||
const FirebaseCoreModule = NativeModules.RNFirebase;
|
||||
|
||||
|
||||
export default class App {
|
||||
_extendedProps: { [string] : boolean };
|
||||
_extendedProps: { [string]: boolean };
|
||||
_initialized: boolean = false;
|
||||
_name: string;
|
||||
_nativeInitialized: boolean = false;
|
||||
@ -51,7 +50,11 @@ export default class App {
|
||||
storage: () => Storage;
|
||||
utils: () => Utils;
|
||||
|
||||
constructor(name: string, options: FirebaseOptions, fromNative: boolean = false) {
|
||||
constructor(
|
||||
name: string,
|
||||
options: FirebaseOptions,
|
||||
fromNative: boolean = false
|
||||
) {
|
||||
this._name = name;
|
||||
this._options = Object.assign({}, options);
|
||||
|
||||
@ -59,10 +62,14 @@ export default class App {
|
||||
this._initialized = true;
|
||||
this._nativeInitialized = true;
|
||||
} else if (options.databaseURL && options.apiKey) {
|
||||
FirebaseCoreModule.initializeApp(this._name, this._options, (error, result) => {
|
||||
this._initialized = true;
|
||||
SharedEventEmitter.emit(`AppReady:${this._name}`, { error, result });
|
||||
});
|
||||
FirebaseCoreModule.initializeApp(
|
||||
this._name,
|
||||
this._options,
|
||||
(error, result) => {
|
||||
this._initialized = true;
|
||||
SharedEventEmitter.emit(`AppReady:${this._name}`, { error, result });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// modules
|
||||
@ -109,7 +116,10 @@ export default class App {
|
||||
* @param props
|
||||
*/
|
||||
extendApp(props: Object) {
|
||||
if (!isObject(props)) throw new Error(INTERNALS.STRINGS.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++) {
|
||||
@ -130,7 +140,9 @@ export default class App {
|
||||
* @return {Promise}
|
||||
*/
|
||||
delete() {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_UNSUPPORTED_CLASS_METHOD('app', '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 === APPS.DEFAULT_APP_NAME && this._nativeInitialized) {
|
||||
// return Promise.reject(
|
||||
@ -141,7 +153,6 @@ export default class App {
|
||||
// return FirebaseCoreModule.deleteApp(this._name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {*}
|
||||
|
@ -10,19 +10,55 @@ import App from './firebase-app';
|
||||
import VERSION from '../../version';
|
||||
|
||||
// module imports
|
||||
import { statics as AdMobStatics, MODULE_NAME as AdmobModuleName } from '../admob';
|
||||
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 {
|
||||
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,
|
||||
@ -60,25 +96,57 @@ class Firebase {
|
||||
|
||||
constructor() {
|
||||
if (!FirebaseCoreModule) {
|
||||
throw (new Error(INTERNALS.STRINGS.ERROR_MISSING_CORE));
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_CORE);
|
||||
}
|
||||
APPS.initializeNativeApps();
|
||||
|
||||
// modules
|
||||
this.admob = APPS.moduleAndStatics('admob', AdMobStatics, AdmobModuleName);
|
||||
this.analytics = APPS.moduleAndStatics('analytics', AnalyticsStatics, AnalyticsModuleName);
|
||||
this.analytics = APPS.moduleAndStatics(
|
||||
'analytics',
|
||||
AnalyticsStatics,
|
||||
AnalyticsModuleName
|
||||
);
|
||||
this.auth = APPS.moduleAndStatics('auth', AuthStatics, AuthModuleName);
|
||||
this.config = APPS.moduleAndStatics('config', ConfigStatics, ConfigModuleName);
|
||||
this.config = APPS.moduleAndStatics(
|
||||
'config',
|
||||
ConfigStatics,
|
||||
ConfigModuleName
|
||||
);
|
||||
this.crash = APPS.moduleAndStatics('crash', CrashStatics, CrashModuleName);
|
||||
this.database = APPS.moduleAndStatics('database', DatabaseStatics, DatabaseModuleName);
|
||||
this.database = APPS.moduleAndStatics(
|
||||
'database',
|
||||
DatabaseStatics,
|
||||
DatabaseModuleName
|
||||
);
|
||||
this.fabric = {
|
||||
crashlytics: APPS.moduleAndStatics('crashlytics', CrashlyticsStatics, CrashlyticsModuleName),
|
||||
crashlytics: APPS.moduleAndStatics(
|
||||
'crashlytics',
|
||||
CrashlyticsStatics,
|
||||
CrashlyticsModuleName
|
||||
),
|
||||
};
|
||||
this.firestore = APPS.moduleAndStatics('firestore', FirestoreStatics, FirestoreModuleName);
|
||||
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.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);
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@ import { getNativeModule } from '../../utils/native';
|
||||
import type Database from './';
|
||||
import type Reference from './reference';
|
||||
|
||||
|
||||
/**
|
||||
* @url https://firebase.google.com/docs/reference/js/firebase.database.OnDisconnect
|
||||
* @class Disconnect
|
||||
@ -33,7 +32,10 @@ export default class Disconnect {
|
||||
* @returns {*}
|
||||
*/
|
||||
set(value: string | Object): Promise<void> {
|
||||
return getNativeModule(this._database).onDisconnectSet(this.path, { type: typeOf(value), value });
|
||||
return getNativeModule(this._database).onDisconnectSet(this.path, {
|
||||
type: typeOf(value),
|
||||
value,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -42,7 +44,10 @@ export default class Disconnect {
|
||||
* @returns {*}
|
||||
*/
|
||||
update(values: Object): Promise<void> {
|
||||
return getNativeModule(this._database).onDisconnectUpdate(this.path, values);
|
||||
return getNativeModule(this._database).onDisconnectUpdate(
|
||||
this.path,
|
||||
values
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,7 +47,7 @@ export default class Database extends ModuleBase {
|
||||
setTimeout(() => {
|
||||
this._serverTimeOffset = 0;
|
||||
this._offsetRef = this.ref('.info/serverTimeOffset');
|
||||
this._offsetRef.on('value', (snapshot) => {
|
||||
this._offsetRef.on('value', snapshot => {
|
||||
this._serverTimeOffset = snapshot.val() || this._serverTimeOffset;
|
||||
});
|
||||
}, 1);
|
||||
@ -86,9 +86,13 @@ export default class Database extends ModuleBase {
|
||||
}
|
||||
|
||||
export const statics = {
|
||||
ServerValue: NativeModules.RNFirebaseDatabase ? {
|
||||
TIMESTAMP: NativeModules.RNFirebaseDatabase.serverValueTimestamp || { '.sv': 'timestamp' },
|
||||
} : {},
|
||||
ServerValue: NativeModules.RNFirebaseDatabase
|
||||
? {
|
||||
TIMESTAMP: NativeModules.RNFirebaseDatabase.serverValueTimestamp || {
|
||||
'.sv': 'timestamp',
|
||||
},
|
||||
}
|
||||
: {},
|
||||
enableLogging(enabled: boolean) {
|
||||
if (NativeModules[MODULE_NAME]) {
|
||||
NativeModules[MODULE_NAME].enableLogging(enabled);
|
||||
|
@ -5,7 +5,7 @@
|
||||
import { objectToUniqueId } from '../../utils';
|
||||
|
||||
import type { DatabaseModifier } from '../../types';
|
||||
import type Reference from './reference.js';
|
||||
import type Reference from './reference';
|
||||
|
||||
// todo doc methods
|
||||
|
||||
@ -16,7 +16,7 @@ export default class Query {
|
||||
_reference: Reference;
|
||||
modifiers: Array<DatabaseModifier>;
|
||||
|
||||
constructor(ref: Reference, path: string, existingModifiers?: Array<DatabaseModifier>) {
|
||||
constructor(ref: Reference, existingModifiers?: Array<DatabaseModifier>) {
|
||||
this.modifiers = existingModifiers ? [...existingModifiers] : [];
|
||||
this._reference = ref;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @flow
|
||||
* Database Reference representation wrapper
|
||||
*/
|
||||
import Query from './query.js';
|
||||
import Query from './query';
|
||||
import Snapshot from './snapshot';
|
||||
import Disconnect from './disconnect';
|
||||
import { getLogger } from '../../utils/log';
|
||||
@ -41,11 +41,11 @@ const ReferenceEventTypes = {
|
||||
};
|
||||
|
||||
type DatabaseListener = {
|
||||
listenerId: number;
|
||||
eventName: string;
|
||||
successCallback: Function;
|
||||
failureCallback?: Function;
|
||||
}
|
||||
listenerId: number,
|
||||
eventName: string,
|
||||
successCallback: Function,
|
||||
failureCallback?: Function,
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {String} ReferenceLocation - Path to location in the database, relative
|
||||
@ -80,12 +80,16 @@ export default class Reference extends ReferenceBase {
|
||||
_query: Query;
|
||||
_refListeners: { [listenerId: number]: DatabaseListener };
|
||||
|
||||
constructor(database: Database, path: string, existingModifiers?: Array<DatabaseModifier>) {
|
||||
constructor(
|
||||
database: Database,
|
||||
path: string,
|
||||
existingModifiers?: Array<DatabaseModifier>
|
||||
) {
|
||||
super(path);
|
||||
this._promise = null;
|
||||
this._refListeners = {};
|
||||
this._database = database;
|
||||
this._query = new Query(this, path, existingModifiers);
|
||||
this._query = new Query(this, existingModifiers);
|
||||
getLogger(database).debug('Created new Reference', this._getRefKey());
|
||||
}
|
||||
|
||||
@ -100,7 +104,12 @@ export default class Reference extends ReferenceBase {
|
||||
* @returns {*}
|
||||
*/
|
||||
keepSynced(bool: boolean): Promise<void> {
|
||||
return getNativeModule(this._database).keepSynced(this._getRefKey(), this.path, this._query.getModifiers(), bool);
|
||||
return getNativeModule(this._database).keepSynced(
|
||||
this._getRefKey(),
|
||||
this.path,
|
||||
this._query.getModifiers(),
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -113,8 +122,11 @@ export default class Reference extends ReferenceBase {
|
||||
*/
|
||||
set(value: any, onComplete?: Function): Promise<void> {
|
||||
return promiseOrCallback(
|
||||
getNativeModule(this._database).set(this.path, this._serializeAnyType(value)),
|
||||
onComplete,
|
||||
getNativeModule(this._database).set(
|
||||
this.path,
|
||||
this._serializeAnyType(value)
|
||||
),
|
||||
onComplete
|
||||
);
|
||||
}
|
||||
|
||||
@ -126,12 +138,15 @@ export default class Reference extends ReferenceBase {
|
||||
* @param onComplete
|
||||
* @returns {Promise}
|
||||
*/
|
||||
setPriority(priority: string | number | null, onComplete?: Function): Promise<void> {
|
||||
setPriority(
|
||||
priority: string | number | null,
|
||||
onComplete?: Function
|
||||
): Promise<void> {
|
||||
const _priority = this._serializeAnyType(priority);
|
||||
|
||||
return promiseOrCallback(
|
||||
getNativeModule(this._database).setPriority(this.path, _priority),
|
||||
onComplete,
|
||||
onComplete
|
||||
);
|
||||
}
|
||||
|
||||
@ -144,13 +159,21 @@ export default class Reference extends ReferenceBase {
|
||||
* @param onComplete
|
||||
* @returns {Promise}
|
||||
*/
|
||||
setWithPriority(value: any, priority: string | number | null, onComplete?: Function): Promise<void> {
|
||||
setWithPriority(
|
||||
value: any,
|
||||
priority: string | number | null,
|
||||
onComplete?: Function
|
||||
): Promise<void> {
|
||||
const _value = this._serializeAnyType(value);
|
||||
const _priority = this._serializeAnyType(priority);
|
||||
|
||||
return promiseOrCallback(
|
||||
getNativeModule(this._database).setWithPriority(this.path, _value, _priority),
|
||||
onComplete,
|
||||
getNativeModule(this._database).setWithPriority(
|
||||
this.path,
|
||||
_value,
|
||||
_priority
|
||||
),
|
||||
onComplete
|
||||
);
|
||||
}
|
||||
|
||||
@ -167,7 +190,7 @@ export default class Reference extends ReferenceBase {
|
||||
|
||||
return promiseOrCallback(
|
||||
getNativeModule(this._database).update(this.path, value),
|
||||
onComplete,
|
||||
onComplete
|
||||
);
|
||||
}
|
||||
|
||||
@ -181,7 +204,7 @@ export default class Reference extends ReferenceBase {
|
||||
remove(onComplete?: Function): Promise<void> {
|
||||
return promiseOrCallback(
|
||||
getNativeModule(this._database).remove(this.path),
|
||||
onComplete,
|
||||
onComplete
|
||||
);
|
||||
}
|
||||
|
||||
@ -196,10 +219,12 @@ export default class Reference extends ReferenceBase {
|
||||
transaction(
|
||||
transactionUpdate: Function,
|
||||
onComplete: (error: ?Error, committed: boolean, snapshot: ?Snapshot) => *,
|
||||
applyLocally: boolean = false,
|
||||
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) => {
|
||||
@ -213,15 +238,22 @@ export default class Reference extends ReferenceBase {
|
||||
}
|
||||
|
||||
if (error) return reject(error);
|
||||
return resolve({ committed, snapshot: new Snapshot(this, snapshotData) });
|
||||
return resolve({
|
||||
committed,
|
||||
snapshot: new Snapshot(this, snapshotData),
|
||||
});
|
||||
};
|
||||
|
||||
// start the transaction natively
|
||||
this._database._transactionHandler.add(this, transactionUpdate, onCompleteWrapper, applyLocally);
|
||||
this._database._transactionHandler.add(
|
||||
this,
|
||||
transactionUpdate,
|
||||
onCompleteWrapper,
|
||||
applyLocally
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param eventName
|
||||
@ -234,21 +266,24 @@ export default class Reference extends ReferenceBase {
|
||||
eventName: string = 'value',
|
||||
successCallback: (snapshot: Object) => void,
|
||||
cancelOrContext: (error: FirebaseError) => void,
|
||||
context?: Object,
|
||||
context?: Object
|
||||
) {
|
||||
return getNativeModule(this._database).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);
|
||||
|
||||
if (isFunction(successCallback)) {
|
||||
if (isObject(cancelOrContext)) successCallback.bind(cancelOrContext)(_snapshot);
|
||||
if (context && isObject(context)) successCallback.bind(context)(_snapshot);
|
||||
if (isObject(cancelOrContext))
|
||||
successCallback.bind(cancelOrContext)(_snapshot);
|
||||
if (context && isObject(context))
|
||||
successCallback.bind(context)(_snapshot);
|
||||
successCallback(_snapshot);
|
||||
}
|
||||
|
||||
return _snapshot;
|
||||
})
|
||||
.catch((error) => {
|
||||
.catch(error => {
|
||||
if (isFunction(cancelOrContext)) return cancelOrContext(error);
|
||||
return error;
|
||||
});
|
||||
@ -262,19 +297,27 @@ export default class Reference extends ReferenceBase {
|
||||
*/
|
||||
push(value: any, onComplete?: Function): Reference | Promise<void> {
|
||||
if (value === null || value === undefined) {
|
||||
return new Reference(this._database, `${this.path}/${generatePushID(this._database._serverTimeOffset)}`);
|
||||
return new Reference(
|
||||
this._database,
|
||||
`${this.path}/${generatePushID(this._database._serverTimeOffset)}`
|
||||
);
|
||||
}
|
||||
|
||||
const newRef = new Reference(this._database, `${this.path}/${generatePushID(this._database._serverTimeOffset)}`);
|
||||
const newRef = new Reference(
|
||||
this._database,
|
||||
`${this.path}/${generatePushID(this._database._serverTimeOffset)}`
|
||||
);
|
||||
const promise = newRef.set(value);
|
||||
|
||||
// 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));
|
||||
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))
|
||||
);
|
||||
}
|
||||
|
||||
// otherwise attach promise to 'thenable' reference and return the
|
||||
@ -327,7 +370,11 @@ export default class Reference extends ReferenceBase {
|
||||
* @returns {Reference}
|
||||
*/
|
||||
orderBy(name: string, key?: string): Reference {
|
||||
const newRef = new Reference(this._database, this.path, this._query.getModifiers());
|
||||
const newRef = new Reference(
|
||||
this._database,
|
||||
this.path,
|
||||
this._query.getModifiers()
|
||||
);
|
||||
newRef._query.orderBy(name, key);
|
||||
return newRef;
|
||||
}
|
||||
@ -361,7 +408,11 @@ export default class Reference extends ReferenceBase {
|
||||
* @returns {Reference}
|
||||
*/
|
||||
limit(name: string, limit: number): Reference {
|
||||
const newRef = new Reference(this._database, this.path, this._query.getModifiers());
|
||||
const newRef = new Reference(
|
||||
this._database,
|
||||
this.path,
|
||||
this._query.getModifiers()
|
||||
);
|
||||
newRef._query.limit(name, limit);
|
||||
return newRef;
|
||||
}
|
||||
@ -408,7 +459,11 @@ export default class Reference extends ReferenceBase {
|
||||
* @returns {Reference}
|
||||
*/
|
||||
filter(name: string, value: any, key?: string): Reference {
|
||||
const newRef = new Reference(this._database, this.path, this._query.getModifiers());
|
||||
const newRef = new Reference(
|
||||
this._database,
|
||||
this.path,
|
||||
this._query.getModifiers()
|
||||
);
|
||||
newRef._query.filter(name, value, key);
|
||||
return newRef;
|
||||
}
|
||||
@ -438,7 +493,7 @@ export default class Reference extends ReferenceBase {
|
||||
* @returns {string}
|
||||
*/
|
||||
toString(): string {
|
||||
return this.path;
|
||||
return `${this._database.app.options.databaseURL}/${this.path}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -450,10 +505,12 @@ export default class Reference extends ReferenceBase {
|
||||
* {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#isEqual}
|
||||
*/
|
||||
isEqual(otherRef: Reference): boolean {
|
||||
return !!otherRef
|
||||
&& otherRef.constructor === Reference
|
||||
&& otherRef.key === this.key
|
||||
&& this._query.queryIdentifier() === otherRef._query.queryIdentifier();
|
||||
return (
|
||||
!!otherRef &&
|
||||
otherRef.constructor === Reference &&
|
||||
otherRef.key === this.key &&
|
||||
this._query.queryIdentifier() === otherRef._query.queryIdentifier()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -468,7 +525,10 @@ export default class Reference extends ReferenceBase {
|
||||
*/
|
||||
get parent(): Reference | null {
|
||||
if (this.path === '/') return null;
|
||||
return new Reference(this._database, this.path.substring(0, this.path.lastIndexOf('/')));
|
||||
return new Reference(
|
||||
this._database,
|
||||
this.path.substring(0, this.path.lastIndexOf('/'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -495,20 +555,23 @@ export default class Reference extends ReferenceBase {
|
||||
* Access then method of promise if set
|
||||
* @return {*}
|
||||
*/
|
||||
then(fnResolve: (any) => any, fnReject: (any) => any) {
|
||||
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;
|
||||
return fnResolve(result);
|
||||
}, (possibleErr) => {
|
||||
this._promise = null;
|
||||
return this._promise.then.bind(this._promise)(
|
||||
result => {
|
||||
this._promise = null;
|
||||
return fnResolve(result);
|
||||
},
|
||||
possibleErr => {
|
||||
this._promise = null;
|
||||
|
||||
if (isFunction(fnReject)) {
|
||||
return fnReject(possibleErr);
|
||||
if (isFunction(fnReject)) {
|
||||
return fnReject(possibleErr);
|
||||
}
|
||||
|
||||
throw possibleErr;
|
||||
}
|
||||
|
||||
throw possibleErr;
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error("Cannot read property 'then' of undefined.");
|
||||
@ -518,9 +581,9 @@ export default class Reference extends ReferenceBase {
|
||||
* Access catch method of promise if set
|
||||
* @return {*}
|
||||
*/
|
||||
catch(fnReject: (any) => any) {
|
||||
catch(fnReject: any => any) {
|
||||
if (isFunction(fnReject) && this._promise && this._promise.catch) {
|
||||
return this._promise.catch.bind(this._promise)((possibleErr) => {
|
||||
return this._promise.catch.bind(this._promise)(possibleErr => {
|
||||
this._promise = null;
|
||||
return fnReject(possibleErr);
|
||||
});
|
||||
@ -539,7 +602,9 @@ export default class Reference extends ReferenceBase {
|
||||
* @return {string}
|
||||
*/
|
||||
_getRegistrationKey(eventType: string): string {
|
||||
return `$${this._database.app.name}$/${this.path}$${this._query.queryIdentifier()}$${listeners}$${eventType}`;
|
||||
return `$${this._database.app.name}$/${
|
||||
this.path
|
||||
}$${this._query.queryIdentifier()}$${listeners}$${eventType}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -550,7 +615,9 @@ export default class Reference extends ReferenceBase {
|
||||
* @private
|
||||
*/
|
||||
_getRefKey(): string {
|
||||
return `$${this._database.app.name}$/${this.path}$${this._query.queryIdentifier()}`;
|
||||
return `$${this._database.app.name}$/${
|
||||
this.path
|
||||
}$${this._query.queryIdentifier()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -562,7 +629,6 @@ export default class Reference extends ReferenceBase {
|
||||
this._promise = promise;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param obj
|
||||
@ -623,34 +689,65 @@ export default class Reference extends ReferenceBase {
|
||||
*
|
||||
* {@link https://firebase.google.com/docs/reference/js/firebase.database.Reference#on}
|
||||
*/
|
||||
on(eventType: string, callback: (Snapshot) => any, cancelCallbackOrContext?: (Object) => any | Object, 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.');
|
||||
throw new Error(
|
||||
'Query.on failed: Function called with 0 arguments. Expects at least 2.'
|
||||
);
|
||||
}
|
||||
|
||||
if (!isString(eventType) || !ReferenceEventTypes[eventType]) {
|
||||
throw new Error(`Query.on failed: First argument must be a valid string event type: "${Object.keys(ReferenceEventTypes).join(', ')}"`);
|
||||
throw new Error(
|
||||
`Query.on failed: First argument must be a valid string event type: "${Object.keys(
|
||||
ReferenceEventTypes
|
||||
).join(', ')}"`
|
||||
);
|
||||
}
|
||||
|
||||
if (!callback) {
|
||||
throw new Error('Query.on failed: Function called with 1 argument. Expects at least 2.');
|
||||
throw new Error(
|
||||
'Query.on failed: Function called with 1 argument. Expects at least 2.'
|
||||
);
|
||||
}
|
||||
|
||||
if (!isFunction(callback)) {
|
||||
throw new Error('Query.on failed: Second argument must be a valid function.');
|
||||
throw new Error(
|
||||
'Query.on failed: Second argument must be a valid function.'
|
||||
);
|
||||
}
|
||||
|
||||
if (cancelCallbackOrContext && !isFunction(cancelCallbackOrContext) && !isObject(context) && !isObject(cancelCallbackOrContext)) {
|
||||
throw new Error('Query.on failed: Function called with 3 arguments, but third optional argument `cancelCallbackOrContext` was not a function.');
|
||||
if (
|
||||
cancelCallbackOrContext &&
|
||||
!isFunction(cancelCallbackOrContext) &&
|
||||
!isObject(context) &&
|
||||
!isObject(cancelCallbackOrContext)
|
||||
) {
|
||||
throw new Error(
|
||||
'Query.on failed: Function called with 3 arguments, but third optional argument `cancelCallbackOrContext` was not a function.'
|
||||
);
|
||||
}
|
||||
|
||||
if (cancelCallbackOrContext && !isFunction(cancelCallbackOrContext) && context) {
|
||||
throw new Error('Query.on failed: Function called with 4 arguments, but third optional argument `cancelCallbackOrContext` was not a function.');
|
||||
if (
|
||||
cancelCallbackOrContext &&
|
||||
!isFunction(cancelCallbackOrContext) &&
|
||||
context
|
||||
) {
|
||||
throw new Error(
|
||||
'Query.on failed: Function called with 4 arguments, but third optional argument `cancelCallbackOrContext` was not a function.'
|
||||
);
|
||||
}
|
||||
|
||||
const eventRegistrationKey = this._getRegistrationKey(eventType);
|
||||
const registrationCancellationKey = `${eventRegistrationKey}$cancelled`;
|
||||
const _context = (cancelCallbackOrContext && !isFunction(cancelCallbackOrContext)) ? cancelCallbackOrContext : context;
|
||||
const _context =
|
||||
cancelCallbackOrContext && !isFunction(cancelCallbackOrContext)
|
||||
? cancelCallbackOrContext
|
||||
: context;
|
||||
const registrationObj = {
|
||||
eventType,
|
||||
ref: this,
|
||||
@ -677,7 +774,9 @@ export default class Reference extends ReferenceBase {
|
||||
appName: this._database.app.name,
|
||||
eventType: `${eventType}$cancelled`,
|
||||
eventRegistrationKey: registrationCancellationKey,
|
||||
listener: _context ? cancelCallbackOrContext.bind(_context) : cancelCallbackOrContext,
|
||||
listener: _context
|
||||
? cancelCallbackOrContext.bind(_context)
|
||||
: cancelCallbackOrContext,
|
||||
});
|
||||
}
|
||||
|
||||
@ -724,18 +823,29 @@ 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 SyncTree.removeListenersForRegistrations(SyncTree.getRegistrationsByPath(this.path));
|
||||
return SyncTree.removeListenersForRegistrations(
|
||||
SyncTree.getRegistrationsByPath(this.path)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* VALIDATE ARGS
|
||||
*/
|
||||
if (eventType && (!isString(eventType) || !ReferenceEventTypes[eventType])) {
|
||||
throw new Error(`Query.off failed: First argument must be a valid string event type: "${Object.keys(ReferenceEventTypes).join(', ')}"`);
|
||||
if (
|
||||
eventType &&
|
||||
(!isString(eventType) || !ReferenceEventTypes[eventType])
|
||||
) {
|
||||
throw new Error(
|
||||
`Query.off failed: First argument must be a valid string event type: "${Object.keys(
|
||||
ReferenceEventTypes
|
||||
).join(', ')}"`
|
||||
);
|
||||
}
|
||||
|
||||
if (originalCallback && !isFunction(originalCallback)) {
|
||||
throw new Error('Query.off failed: Function called with 2 arguments, but second optional argument was not a function.');
|
||||
throw new Error(
|
||||
'Query.off failed: Function called with 2 arguments, but second optional argument was not a function.'
|
||||
);
|
||||
}
|
||||
|
||||
// Firebase Docs:
|
||||
@ -745,7 +855,11 @@ export default class Reference extends ReferenceBase {
|
||||
// remove the callback.
|
||||
// Remove only a single registration
|
||||
if (eventType && originalCallback) {
|
||||
const registration = 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
|
||||
@ -753,15 +867,20 @@ export default class Reference extends ReferenceBase {
|
||||
|
||||
// remove only the first registration to match firebase web sdk
|
||||
// call multiple times to remove multiple registrations
|
||||
return 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 = SyncTree.getRegistrationsByPathEvent(this.path, eventType);
|
||||
const registrations = SyncTree.getRegistrationsByPathEvent(
|
||||
this.path,
|
||||
eventType
|
||||
);
|
||||
|
||||
SyncTree.removeListenersForRegistrations(
|
||||
SyncTree.getRegistrationsByPathEvent(this.path, `${eventType}$cancelled`),
|
||||
SyncTree.getRegistrationsByPathEvent(this.path, `${eventType}$cancelled`)
|
||||
);
|
||||
|
||||
return SyncTree.removeListenersForRegistrations(registrations);
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Snapshot representation wrapper
|
||||
*/
|
||||
import { isObject, deepGet, deepExists } from './../../utils';
|
||||
import type Reference from './reference.js';
|
||||
import type Reference from './reference';
|
||||
|
||||
/**
|
||||
* @class DataSnapshot
|
||||
@ -39,7 +39,8 @@ export default class Snapshot {
|
||||
*/
|
||||
val(): any {
|
||||
// clone via JSON stringify/parse - prevent modification of this._value
|
||||
if (isObject(this._value) || Array.isArray(this._value)) return JSON.parse(JSON.stringify(this._value));
|
||||
if (isObject(this._value) || Array.isArray(this._value))
|
||||
return JSON.parse(JSON.stringify(this._value));
|
||||
return this._value;
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,7 @@ let transactionId = 0;
|
||||
* @returns {number}
|
||||
* @private
|
||||
*/
|
||||
const generateTransactionId = (): number => {
|
||||
return transactionId++;
|
||||
};
|
||||
const generateTransactionId = (): number => transactionId++;
|
||||
|
||||
/**
|
||||
* @class TransactionHandler
|
||||
@ -24,7 +22,7 @@ const generateTransactionId = (): number => {
|
||||
export default class TransactionHandler {
|
||||
_database: Database;
|
||||
_transactionListener: Function;
|
||||
_transactions: { [number]: Object }
|
||||
_transactions: { [number]: Object };
|
||||
|
||||
constructor(database: Database) {
|
||||
this._transactions = {};
|
||||
@ -32,7 +30,7 @@ export default class TransactionHandler {
|
||||
|
||||
this._transactionListener = SharedEventEmitter.addListener(
|
||||
getAppEventName(this._database, 'database_transaction_event'),
|
||||
this._handleTransactionEvent.bind(this),
|
||||
this._handleTransactionEvent.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
@ -43,7 +41,12 @@ export default class TransactionHandler {
|
||||
* @param onComplete
|
||||
* @param applyLocally
|
||||
*/
|
||||
add(reference: Object, transactionUpdater: Function, onComplete?: Function, applyLocally?: boolean = false) {
|
||||
add(
|
||||
reference: Object,
|
||||
transactionUpdater: Function,
|
||||
onComplete?: Function,
|
||||
applyLocally?: boolean = false
|
||||
) {
|
||||
const id = generateTransactionId();
|
||||
|
||||
this._transactions[id] = {
|
||||
@ -56,7 +59,11 @@ export default class TransactionHandler {
|
||||
started: true,
|
||||
};
|
||||
|
||||
getNativeModule(this._database).transactionStart(reference.path, id, applyLocally);
|
||||
getNativeModule(this._database).transactionStart(
|
||||
reference.path,
|
||||
id,
|
||||
applyLocally
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -78,7 +85,10 @@ export default class TransactionHandler {
|
||||
case 'complete':
|
||||
return this._handleComplete(event);
|
||||
default:
|
||||
getLogger(this._database).warn(`Unknown transaction event type: '${event.type}'`, event);
|
||||
getLogger(this._database).warn(
|
||||
`Unknown transaction event type: '${event.type}'`,
|
||||
event
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@ -104,7 +114,10 @@ export default class TransactionHandler {
|
||||
abort = true;
|
||||
}
|
||||
|
||||
getNativeModule(this._database).transactionTryCommit(id, { value: newValue, abort });
|
||||
getNativeModule(this._database).transactionTryCommit(id, {
|
||||
value: newValue,
|
||||
abort,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,7 +150,11 @@ export default class TransactionHandler {
|
||||
if (transaction && !transaction.completed) {
|
||||
transaction.completed = true;
|
||||
try {
|
||||
transaction.onComplete(null, event.committed, Object.assign({}, event.snapshot));
|
||||
transaction.onComplete(
|
||||
null,
|
||||
event.committed,
|
||||
Object.assign({}, event.snapshot)
|
||||
);
|
||||
} finally {
|
||||
setImmediate(() => {
|
||||
delete this._transactions[event.id];
|
||||
|
@ -7,10 +7,18 @@ import Query from './Query';
|
||||
import { firestoreAutoId } from '../../utils';
|
||||
|
||||
import type Firestore from './';
|
||||
import type { FirestoreQueryDirection, FirestoreQueryOperator } from '../../types';
|
||||
import type {
|
||||
FirestoreQueryDirection,
|
||||
FirestoreQueryOperator,
|
||||
} from '../../types';
|
||||
import type FieldPath from './FieldPath';
|
||||
import type Path from './Path';
|
||||
import type { Observer, ObserverOnError, ObserverOnNext, QueryListenOptions } from './Query';
|
||||
import type {
|
||||
Observer,
|
||||
ObserverOnError,
|
||||
ObserverOnNext,
|
||||
QueryListenOptions,
|
||||
} from './Query';
|
||||
import type QuerySnapshot from './QuerySnapshot';
|
||||
|
||||
/**
|
||||
@ -37,13 +45,14 @@ export default class CollectionReference {
|
||||
|
||||
get parent(): DocumentReference | null {
|
||||
const parentPath = this._collectionPath.parent();
|
||||
return parentPath ? new DocumentReference(this._firestore, parentPath) : null;
|
||||
return parentPath
|
||||
? new DocumentReference(this._firestore, parentPath)
|
||||
: null;
|
||||
}
|
||||
|
||||
add(data: Object): Promise<DocumentReference> {
|
||||
const documentRef = this.doc();
|
||||
return documentRef.set(data)
|
||||
.then(() => Promise.resolve(documentRef));
|
||||
return documentRef.set(data).then(() => Promise.resolve(documentRef));
|
||||
}
|
||||
|
||||
doc(documentPath?: string): DocumentReference {
|
||||
@ -77,12 +86,19 @@ export default class CollectionReference {
|
||||
onSnapshot(
|
||||
optionsOrObserverOrOnNext: QueryListenOptions | Observer | ObserverOnNext,
|
||||
observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError,
|
||||
onError?: ObserverOnError,
|
||||
onError?: ObserverOnError
|
||||
): () => void {
|
||||
return this._query.onSnapshot(optionsOrObserverOrOnNext, observerOrOnNextOrOnError, onError);
|
||||
return this._query.onSnapshot(
|
||||
optionsOrObserverOrOnNext,
|
||||
observerOrOnNextOrOnError,
|
||||
onError
|
||||
);
|
||||
}
|
||||
|
||||
orderBy(fieldPath: string | FieldPath, directionStr?: FirestoreQueryDirection): Query {
|
||||
orderBy(
|
||||
fieldPath: string | FieldPath,
|
||||
directionStr?: FirestoreQueryDirection
|
||||
): Query {
|
||||
return this._query.orderBy(fieldPath, directionStr);
|
||||
}
|
||||
|
||||
|
@ -13,20 +13,23 @@ import { firestoreAutoId, isFunction, isObject, isString } from '../../utils';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type Firestore from './';
|
||||
import type { FirestoreNativeDocumentSnapshot, FirestoreWriteOptions } from '../../types';
|
||||
import type {
|
||||
FirestoreNativeDocumentSnapshot,
|
||||
FirestoreWriteOptions,
|
||||
} from '../../types';
|
||||
import type Path from './Path';
|
||||
|
||||
type DocumentListenOptions = {
|
||||
includeMetadataChanges: boolean,
|
||||
}
|
||||
};
|
||||
|
||||
type ObserverOnError = (Object) => void;
|
||||
type ObserverOnNext = (DocumentSnapshot) => void;
|
||||
type ObserverOnError = Object => void;
|
||||
type ObserverOnNext = DocumentSnapshot => void;
|
||||
|
||||
type Observer = {
|
||||
error?: ObserverOnError,
|
||||
next: ObserverOnNext,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class DocumentReference
|
||||
@ -70,8 +73,7 @@ export default class DocumentReference {
|
||||
}
|
||||
|
||||
delete(): Promise<void> {
|
||||
return getNativeModule(this._firestore)
|
||||
.documentDelete(this.path);
|
||||
return getNativeModule(this._firestore).documentDelete(this.path);
|
||||
}
|
||||
|
||||
get(): Promise<DocumentSnapshot> {
|
||||
@ -81,28 +83,41 @@ export default class DocumentReference {
|
||||
}
|
||||
|
||||
onSnapshot(
|
||||
optionsOrObserverOrOnNext: DocumentListenOptions | Observer | ObserverOnNext,
|
||||
optionsOrObserverOrOnNext:
|
||||
| DocumentListenOptions
|
||||
| Observer
|
||||
| ObserverOnNext,
|
||||
observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError,
|
||||
onError?: ObserverOnError,
|
||||
onError?: ObserverOnError
|
||||
) {
|
||||
let observer: Observer;
|
||||
let docListenOptions = {};
|
||||
// Called with: onNext, ?onError
|
||||
if (isFunction(optionsOrObserverOrOnNext)) {
|
||||
if (observerOrOnNextOrOnError && !isFunction(observerOrOnNextOrOnError)) {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Second argument must be a valid function.');
|
||||
throw new Error(
|
||||
'DocumentReference.onSnapshot failed: Second argument must be a valid function.'
|
||||
);
|
||||
}
|
||||
// $FlowBug: Not coping with the overloaded method signature
|
||||
observer = {
|
||||
next: optionsOrObserverOrOnNext,
|
||||
error: observerOrOnNextOrOnError,
|
||||
};
|
||||
} else if (optionsOrObserverOrOnNext && isObject(optionsOrObserverOrOnNext)) {
|
||||
} else if (
|
||||
optionsOrObserverOrOnNext &&
|
||||
isObject(optionsOrObserverOrOnNext)
|
||||
) {
|
||||
// Called with: Observer
|
||||
if (optionsOrObserverOrOnNext.next) {
|
||||
if (isFunction(optionsOrObserverOrOnNext.next)) {
|
||||
if (optionsOrObserverOrOnNext.error && !isFunction(optionsOrObserverOrOnNext.error)) {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Observer.error must be a valid function.');
|
||||
if (
|
||||
optionsOrObserverOrOnNext.error &&
|
||||
!isFunction(optionsOrObserverOrOnNext.error)
|
||||
) {
|
||||
throw new Error(
|
||||
'DocumentReference.onSnapshot failed: Observer.error must be a valid function.'
|
||||
);
|
||||
}
|
||||
// $FlowBug: Not coping with the overloaded method signature
|
||||
observer = {
|
||||
@ -110,66 +125,103 @@ export default class DocumentReference {
|
||||
error: optionsOrObserverOrOnNext.error,
|
||||
};
|
||||
} else {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Observer.next must be a valid function.');
|
||||
throw new Error(
|
||||
'DocumentReference.onSnapshot failed: Observer.next must be a valid function.'
|
||||
);
|
||||
}
|
||||
} else if (Object.prototype.hasOwnProperty.call(optionsOrObserverOrOnNext, 'includeMetadataChanges')) {
|
||||
} else if (
|
||||
Object.prototype.hasOwnProperty.call(
|
||||
optionsOrObserverOrOnNext,
|
||||
'includeMetadataChanges'
|
||||
)
|
||||
) {
|
||||
docListenOptions = optionsOrObserverOrOnNext;
|
||||
// Called with: Options, onNext, ?onError
|
||||
if (isFunction(observerOrOnNextOrOnError)) {
|
||||
if (onError && !isFunction(onError)) {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Third argument must be a valid function.');
|
||||
throw new Error(
|
||||
'DocumentReference.onSnapshot failed: Third argument must be a valid function.'
|
||||
);
|
||||
}
|
||||
// $FlowBug: Not coping with the overloaded method signature
|
||||
observer = {
|
||||
next: observerOrOnNextOrOnError,
|
||||
error: onError,
|
||||
};
|
||||
// Called with Options, Observer
|
||||
} else if (observerOrOnNextOrOnError && isObject(observerOrOnNextOrOnError) && observerOrOnNextOrOnError.next) {
|
||||
// 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.');
|
||||
if (
|
||||
observerOrOnNextOrOnError.error &&
|
||||
!isFunction(observerOrOnNextOrOnError.error)
|
||||
) {
|
||||
throw new Error(
|
||||
'DocumentReference.onSnapshot failed: Observer.error must be a valid function.'
|
||||
);
|
||||
}
|
||||
observer = {
|
||||
next: observerOrOnNextOrOnError.next,
|
||||
error: observerOrOnNextOrOnError.error,
|
||||
};
|
||||
} else {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Observer.next must be a valid function.');
|
||||
throw new Error(
|
||||
'DocumentReference.onSnapshot failed: Observer.next must be a valid function.'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Second argument must be a function or observer.');
|
||||
throw new Error(
|
||||
'DocumentReference.onSnapshot failed: Second argument must be a function or observer.'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new Error('DocumentReference.onSnapshot failed: First argument must be a function, observer or options.');
|
||||
throw new Error(
|
||||
'DocumentReference.onSnapshot failed: First argument must be a function, observer or options.'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new Error('DocumentReference.onSnapshot failed: Called with invalid arguments.');
|
||||
throw new Error(
|
||||
'DocumentReference.onSnapshot failed: Called with invalid arguments.'
|
||||
);
|
||||
}
|
||||
const listenerId = firestoreAutoId();
|
||||
|
||||
const listener = (nativeDocumentSnapshot: FirestoreNativeDocumentSnapshot) => {
|
||||
const documentSnapshot = new DocumentSnapshot(this.firestore, nativeDocumentSnapshot);
|
||||
const listener = (
|
||||
nativeDocumentSnapshot: FirestoreNativeDocumentSnapshot
|
||||
) => {
|
||||
const documentSnapshot = new DocumentSnapshot(
|
||||
this.firestore,
|
||||
nativeDocumentSnapshot
|
||||
);
|
||||
observer.next(documentSnapshot);
|
||||
};
|
||||
|
||||
// Listen to snapshot events
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`),
|
||||
listener,
|
||||
listener
|
||||
);
|
||||
|
||||
// Listen for snapshot error events
|
||||
if (observer.error) {
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`),
|
||||
observer.error,
|
||||
getAppEventName(
|
||||
this._firestore,
|
||||
`onDocumentSnapshotError:${listenerId}`
|
||||
),
|
||||
observer.error
|
||||
);
|
||||
}
|
||||
|
||||
// Add the native listener
|
||||
getNativeModule(this._firestore)
|
||||
.documentOnSnapshot(this.path, listenerId, docListenOptions);
|
||||
getNativeModule(this._firestore).documentOnSnapshot(
|
||||
this.path,
|
||||
listenerId,
|
||||
docListenOptions
|
||||
);
|
||||
|
||||
// Return an unsubscribe method
|
||||
return this._offDocumentSnapshot.bind(this, listenerId, listener);
|
||||
@ -177,19 +229,27 @@ export default class DocumentReference {
|
||||
|
||||
set(data: Object, writeOptions?: FirestoreWriteOptions): Promise<void> {
|
||||
const nativeData = buildNativeMap(data);
|
||||
return getNativeModule(this._firestore)
|
||||
.documentSet(this.path, nativeData, writeOptions);
|
||||
return getNativeModule(this._firestore).documentSet(
|
||||
this.path,
|
||||
nativeData,
|
||||
writeOptions
|
||||
);
|
||||
}
|
||||
|
||||
update(...args: any[]): Promise<void> {
|
||||
let data = {};
|
||||
if (args.length === 1) {
|
||||
if (!isObject(args[0])) {
|
||||
throw new Error('DocumentReference.update failed: If using a single argument, it must be an object.');
|
||||
throw new Error(
|
||||
'DocumentReference.update failed: If using a single argument, it must be an object.'
|
||||
);
|
||||
}
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
data = args[0];
|
||||
} else if (args.length % 2 === 1) {
|
||||
throw new Error('DocumentReference.update failed: Must have either a single object argument, or equal numbers of key/value pairs.');
|
||||
throw new Error(
|
||||
'DocumentReference.update failed: Must have either a single object argument, or equal numbers of key/value pairs.'
|
||||
);
|
||||
} else {
|
||||
for (let i = 0; i < args.length; i += 2) {
|
||||
const key = args[i];
|
||||
@ -199,13 +259,17 @@ export default class DocumentReference {
|
||||
} else if (key instanceof FieldPath) {
|
||||
data = mergeFieldPathData(data, key._segments, value);
|
||||
} else {
|
||||
throw new Error(`DocumentReference.update failed: Argument at index ${i} must be a string or FieldPath`);
|
||||
throw new Error(
|
||||
`DocumentReference.update failed: Argument at index ${i} must be a string or FieldPath`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
const nativeData = buildNativeMap(data);
|
||||
return getNativeModule(this._firestore)
|
||||
.documentUpdate(this.path, nativeData);
|
||||
return getNativeModule(this._firestore).documentUpdate(
|
||||
this.path,
|
||||
nativeData
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -218,9 +282,14 @@ export default class DocumentReference {
|
||||
*/
|
||||
_offDocumentSnapshot(listenerId: string, listener: Function) {
|
||||
getLogger(this._firestore).info('Removing onDocumentSnapshot listener');
|
||||
SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`), listener);
|
||||
SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`), listener);
|
||||
getNativeModule(this._firestore)
|
||||
.documentOffSnapshot(this.path, listenerId);
|
||||
SharedEventEmitter.removeListener(
|
||||
getAppEventName(this._firestore, `onDocumentSnapshot:${listenerId}`),
|
||||
listener
|
||||
);
|
||||
SharedEventEmitter.removeListener(
|
||||
getAppEventName(this._firestore, `onDocumentSnapshotError:${listenerId}`),
|
||||
listener
|
||||
);
|
||||
getNativeModule(this._firestore).documentOffSnapshot(this.path, listenerId);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,10 @@ import { isObject } from '../../utils';
|
||||
import { parseNativeMap } from './utils/serialize';
|
||||
|
||||
import type Firestore from './';
|
||||
import type { FirestoreNativeDocumentSnapshot, FirestoreSnapshotMetadata } from '../../types';
|
||||
import type {
|
||||
FirestoreNativeDocumentSnapshot,
|
||||
FirestoreSnapshotMetadata,
|
||||
} from '../../types';
|
||||
|
||||
const extractFieldPathData = (data: Object | void, segments: string[]): any => {
|
||||
if (!data || !isObject(data)) {
|
||||
@ -30,10 +33,16 @@ export default class DocumentSnapshot {
|
||||
_metadata: FirestoreSnapshotMetadata;
|
||||
_ref: DocumentReference;
|
||||
|
||||
constructor(firestore: Firestore, nativeData: FirestoreNativeDocumentSnapshot) {
|
||||
constructor(
|
||||
firestore: Firestore,
|
||||
nativeData: FirestoreNativeDocumentSnapshot
|
||||
) {
|
||||
this._data = parseNativeMap(firestore, nativeData.data);
|
||||
this._metadata = nativeData.metadata;
|
||||
this._ref = new DocumentReference(firestore, Path.fromName(nativeData.path));
|
||||
this._ref = new DocumentReference(
|
||||
firestore,
|
||||
Path.fromName(nativeData.path)
|
||||
);
|
||||
}
|
||||
|
||||
get exists(): boolean {
|
||||
|
@ -12,7 +12,10 @@ import { firestoreAutoId, isFunction, isObject } from '../../utils';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type Firestore from './';
|
||||
import type { FirestoreQueryDirection, FirestoreQueryOperator } from '../../types';
|
||||
import type {
|
||||
FirestoreQueryDirection,
|
||||
FirestoreQueryOperator,
|
||||
} from '../../types';
|
||||
import type Path from './Path';
|
||||
|
||||
const DIRECTIONS: { [FirestoreQueryDirection]: string } = {
|
||||
@ -35,16 +38,16 @@ type NativeFieldPath = {|
|
||||
elements?: string[],
|
||||
string?: string,
|
||||
type: 'fieldpath' | 'string',
|
||||
|}
|
||||
|};
|
||||
type FieldFilter = {|
|
||||
fieldPath: NativeFieldPath,
|
||||
operator: string,
|
||||
value: any,
|
||||
|}
|
||||
|};
|
||||
type FieldOrder = {|
|
||||
direction: string,
|
||||
fieldPath: NativeFieldPath,
|
||||
|}
|
||||
|};
|
||||
type QueryOptions = {
|
||||
endAt?: any[],
|
||||
endBefore?: any[],
|
||||
@ -53,22 +56,24 @@ type QueryOptions = {
|
||||
selectFields?: string[],
|
||||
startAfter?: any[],
|
||||
startAt?: any[],
|
||||
}
|
||||
};
|
||||
|
||||
export type QueryListenOptions = {|
|
||||
includeDocumentMetadataChanges: boolean,
|
||||
includeQueryMetadataChanges: boolean,
|
||||
|}
|
||||
|};
|
||||
|
||||
export type ObserverOnError = (Object) => void;
|
||||
export type ObserverOnNext = (QuerySnapshot) => void;
|
||||
export type ObserverOnError = Object => void;
|
||||
export type ObserverOnNext = QuerySnapshot => void;
|
||||
|
||||
export type Observer = {
|
||||
error?: ObserverOnError,
|
||||
next: ObserverOnNext,
|
||||
}
|
||||
};
|
||||
|
||||
const buildNativeFieldPath = (fieldPath: string | FieldPath): NativeFieldPath => {
|
||||
const buildNativeFieldPath = (
|
||||
fieldPath: string | FieldPath
|
||||
): NativeFieldPath => {
|
||||
if (fieldPath instanceof FieldPath) {
|
||||
return {
|
||||
elements: fieldPath._segments,
|
||||
@ -95,10 +100,9 @@ export default class Query {
|
||||
constructor(
|
||||
firestore: Firestore,
|
||||
path: Path,
|
||||
fieldFilters?:
|
||||
FieldFilter[],
|
||||
fieldFilters?: FieldFilter[],
|
||||
fieldOrders?: FieldOrder[],
|
||||
queryOptions?: QueryOptions,
|
||||
queryOptions?: QueryOptions
|
||||
) {
|
||||
this._fieldFilters = fieldFilters || [];
|
||||
this._fieldOrders = fieldOrders || [];
|
||||
@ -122,7 +126,7 @@ export default class Query {
|
||||
this._referencePath,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
options,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
@ -137,7 +141,7 @@ export default class Query {
|
||||
this._referencePath,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
options,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
@ -147,7 +151,7 @@ export default class Query {
|
||||
this._referencePath.relativeName,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
this._queryOptions,
|
||||
this._queryOptions
|
||||
)
|
||||
.then(nativeData => new QuerySnapshot(this._firestore, this, nativeData));
|
||||
}
|
||||
@ -165,33 +169,43 @@ export default class Query {
|
||||
this._referencePath,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
options,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
onSnapshot(
|
||||
optionsOrObserverOrOnNext: QueryListenOptions | Observer | ObserverOnNext,
|
||||
observerOrOnNextOrOnError?: Observer | ObserverOnNext | ObserverOnError,
|
||||
onError?: ObserverOnError,
|
||||
onError?: ObserverOnError
|
||||
) {
|
||||
let observer: Observer;
|
||||
let queryListenOptions = {};
|
||||
// Called with: onNext, ?onError
|
||||
if (isFunction(optionsOrObserverOrOnNext)) {
|
||||
if (observerOrOnNextOrOnError && !isFunction(observerOrOnNextOrOnError)) {
|
||||
throw new Error('Query.onSnapshot failed: Second argument must be a valid function.');
|
||||
throw new Error(
|
||||
'Query.onSnapshot failed: Second argument must be a valid function.'
|
||||
);
|
||||
}
|
||||
// $FlowBug: Not coping with the overloaded method signature
|
||||
observer = {
|
||||
next: optionsOrObserverOrOnNext,
|
||||
error: observerOrOnNextOrOnError,
|
||||
};
|
||||
} else if (optionsOrObserverOrOnNext && isObject(optionsOrObserverOrOnNext)) {
|
||||
} else if (
|
||||
optionsOrObserverOrOnNext &&
|
||||
isObject(optionsOrObserverOrOnNext)
|
||||
) {
|
||||
// Called with: Observer
|
||||
if (optionsOrObserverOrOnNext.next) {
|
||||
if (isFunction(optionsOrObserverOrOnNext.next)) {
|
||||
if (optionsOrObserverOrOnNext.error && !isFunction(optionsOrObserverOrOnNext.error)) {
|
||||
throw new Error('Query.onSnapshot failed: Observer.error must be a valid function.');
|
||||
if (
|
||||
optionsOrObserverOrOnNext.error &&
|
||||
!isFunction(optionsOrObserverOrOnNext.error)
|
||||
) {
|
||||
throw new Error(
|
||||
'Query.onSnapshot failed: Observer.error must be a valid function.'
|
||||
);
|
||||
}
|
||||
// $FlowBug: Not coping with the overloaded method signature
|
||||
observer = {
|
||||
@ -199,87 +213,124 @@ export default class Query {
|
||||
error: optionsOrObserverOrOnNext.error,
|
||||
};
|
||||
} else {
|
||||
throw new Error('Query.onSnapshot failed: Observer.next must be a valid function.');
|
||||
throw new Error(
|
||||
'Query.onSnapshot failed: Observer.next must be a valid function.'
|
||||
);
|
||||
}
|
||||
} else if (Object.prototype.hasOwnProperty.call(optionsOrObserverOrOnNext, 'includeDocumentMetadataChanges')
|
||||
|| Object.prototype.hasOwnProperty.call(optionsOrObserverOrOnNext, 'includeQueryMetadataChanges')) {
|
||||
} else if (
|
||||
Object.prototype.hasOwnProperty.call(
|
||||
optionsOrObserverOrOnNext,
|
||||
'includeDocumentMetadataChanges'
|
||||
) ||
|
||||
Object.prototype.hasOwnProperty.call(
|
||||
optionsOrObserverOrOnNext,
|
||||
'includeQueryMetadataChanges'
|
||||
)
|
||||
) {
|
||||
queryListenOptions = optionsOrObserverOrOnNext;
|
||||
// Called with: Options, onNext, ?onError
|
||||
if (isFunction(observerOrOnNextOrOnError)) {
|
||||
if (onError && !isFunction(onError)) {
|
||||
throw new Error('Query.onSnapshot failed: Third argument must be a valid function.');
|
||||
throw new Error(
|
||||
'Query.onSnapshot failed: Third argument must be a valid function.'
|
||||
);
|
||||
}
|
||||
// $FlowBug: Not coping with the overloaded method signature
|
||||
observer = {
|
||||
next: observerOrOnNextOrOnError,
|
||||
error: onError,
|
||||
};
|
||||
// Called with Options, Observer
|
||||
} else if (observerOrOnNextOrOnError && isObject(observerOrOnNextOrOnError) && observerOrOnNextOrOnError.next) {
|
||||
// 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.');
|
||||
if (
|
||||
observerOrOnNextOrOnError.error &&
|
||||
!isFunction(observerOrOnNextOrOnError.error)
|
||||
) {
|
||||
throw new Error(
|
||||
'Query.onSnapshot failed: Observer.error must be a valid function.'
|
||||
);
|
||||
}
|
||||
observer = {
|
||||
next: observerOrOnNextOrOnError.next,
|
||||
error: observerOrOnNextOrOnError.error,
|
||||
};
|
||||
} else {
|
||||
throw new Error('Query.onSnapshot failed: Observer.next must be a valid function.');
|
||||
throw new Error(
|
||||
'Query.onSnapshot failed: Observer.next must be a valid function.'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new Error('Query.onSnapshot failed: Second argument must be a function or observer.');
|
||||
throw new Error(
|
||||
'Query.onSnapshot failed: Second argument must be a function or observer.'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new Error('Query.onSnapshot failed: First argument must be a function, observer or options.');
|
||||
throw new Error(
|
||||
'Query.onSnapshot failed: First argument must be a function, observer or options.'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new Error('Query.onSnapshot failed: Called with invalid arguments.');
|
||||
throw new Error(
|
||||
'Query.onSnapshot failed: Called with invalid arguments.'
|
||||
);
|
||||
}
|
||||
const listenerId = firestoreAutoId();
|
||||
|
||||
const listener = (nativeQuerySnapshot) => {
|
||||
const querySnapshot = new QuerySnapshot(this._firestore, this, nativeQuerySnapshot);
|
||||
const listener = nativeQuerySnapshot => {
|
||||
const querySnapshot = new QuerySnapshot(
|
||||
this._firestore,
|
||||
this,
|
||||
nativeQuerySnapshot
|
||||
);
|
||||
observer.next(querySnapshot);
|
||||
};
|
||||
|
||||
// Listen to snapshot events
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this._firestore, `onQuerySnapshot:${listenerId}`),
|
||||
listener,
|
||||
listener
|
||||
);
|
||||
|
||||
// Listen for snapshot error events
|
||||
if (observer.error) {
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this._firestore, `onQuerySnapshotError:${listenerId}`),
|
||||
observer.error,
|
||||
observer.error
|
||||
);
|
||||
}
|
||||
|
||||
// Add the native listener
|
||||
getNativeModule(this._firestore)
|
||||
.collectionOnSnapshot(
|
||||
this._referencePath.relativeName,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
this._queryOptions,
|
||||
listenerId,
|
||||
queryListenOptions,
|
||||
);
|
||||
getNativeModule(this._firestore).collectionOnSnapshot(
|
||||
this._referencePath.relativeName,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
this._queryOptions,
|
||||
listenerId,
|
||||
queryListenOptions
|
||||
);
|
||||
|
||||
// Return an unsubscribe method
|
||||
return this._offCollectionSnapshot.bind(this, listenerId, listener);
|
||||
}
|
||||
|
||||
orderBy(fieldPath: string | FieldPath, directionStr?: FirestoreQueryDirection = 'asc'): Query {
|
||||
orderBy(
|
||||
fieldPath: string | FieldPath,
|
||||
directionStr?: FirestoreQueryDirection = 'asc'
|
||||
): Query {
|
||||
// TODO: Validation
|
||||
// validate.isFieldPath('fieldPath', fieldPath);
|
||||
// validate.isOptionalFieldOrder('directionStr', directionStr);
|
||||
|
||||
if (this._queryOptions.startAt || this._queryOptions.endAt) {
|
||||
throw new Error('Cannot specify an orderBy() constraint after calling ' +
|
||||
'startAt(), startAfter(), endBefore() or endAt().');
|
||||
throw new Error(
|
||||
'Cannot specify an orderBy() constraint after calling ' +
|
||||
'startAt(), startAfter(), endBefore() or endAt().'
|
||||
);
|
||||
}
|
||||
|
||||
const newOrder: FieldOrder = {
|
||||
@ -292,7 +343,7 @@ export default class Query {
|
||||
this._referencePath,
|
||||
this._fieldFilters,
|
||||
combinedOrders,
|
||||
this._queryOptions,
|
||||
this._queryOptions
|
||||
);
|
||||
}
|
||||
|
||||
@ -307,7 +358,7 @@ export default class Query {
|
||||
this._referencePath,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
options,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
@ -322,11 +373,15 @@ export default class Query {
|
||||
this._referencePath,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
options,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
where(fieldPath: string | FieldPath, opStr: FirestoreQueryOperator, value: any): Query {
|
||||
where(
|
||||
fieldPath: string | FieldPath,
|
||||
opStr: FirestoreQueryOperator,
|
||||
value: any
|
||||
): Query {
|
||||
// TODO: Validation
|
||||
// validate.isFieldPath('fieldPath', fieldPath);
|
||||
// validate.isFieldFilter('fieldFilter', opStr, value);
|
||||
@ -342,7 +397,7 @@ export default class Query {
|
||||
this._referencePath,
|
||||
combinedFilters,
|
||||
this._fieldOrders,
|
||||
this._queryOptions,
|
||||
this._queryOptions
|
||||
);
|
||||
}
|
||||
|
||||
@ -353,12 +408,18 @@ export default class Query {
|
||||
_buildOrderByOption(snapshotOrVarArgs: any[]) {
|
||||
// TODO: Validation
|
||||
let values;
|
||||
if (snapshotOrVarArgs.length === 1 && snapshotOrVarArgs[0] instanceof DocumentSnapshot) {
|
||||
if (
|
||||
snapshotOrVarArgs.length === 1 &&
|
||||
snapshotOrVarArgs[0] instanceof DocumentSnapshot
|
||||
) {
|
||||
const docSnapshot: DocumentSnapshot = snapshotOrVarArgs[0];
|
||||
values = [];
|
||||
for (let i = 0; i < this._fieldOrders.length; i++) {
|
||||
const fieldOrder = this._fieldOrders[i];
|
||||
if (fieldOrder.fieldPath.type === 'string' && fieldOrder.fieldPath.string) {
|
||||
if (
|
||||
fieldOrder.fieldPath.type === 'string' &&
|
||||
fieldOrder.fieldPath.string
|
||||
) {
|
||||
values.push(docSnapshot.get(fieldOrder.fieldPath.string));
|
||||
} else if (fieldOrder.fieldPath.fieldpath) {
|
||||
const fieldPath = new FieldPath(...fieldOrder.fieldPath.fieldpath);
|
||||
@ -378,15 +439,20 @@ export default class Query {
|
||||
*/
|
||||
_offCollectionSnapshot(listenerId: string, listener: Function) {
|
||||
getLogger(this._firestore).info('Removing onQuerySnapshot listener');
|
||||
SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onQuerySnapshot:${listenerId}`), listener);
|
||||
SharedEventEmitter.removeListener(getAppEventName(this._firestore, `onQuerySnapshotError:${listenerId}`), listener);
|
||||
getNativeModule(this._firestore)
|
||||
.collectionOffSnapshot(
|
||||
this._referencePath.relativeName,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
this._queryOptions,
|
||||
listenerId,
|
||||
);
|
||||
SharedEventEmitter.removeListener(
|
||||
getAppEventName(this._firestore, `onQuerySnapshot:${listenerId}`),
|
||||
listener
|
||||
);
|
||||
SharedEventEmitter.removeListener(
|
||||
getAppEventName(this._firestore, `onQuerySnapshotError:${listenerId}`),
|
||||
listener
|
||||
);
|
||||
getNativeModule(this._firestore).collectionOffSnapshot(
|
||||
this._referencePath.relativeName,
|
||||
this._fieldFilters,
|
||||
this._fieldOrders,
|
||||
this._queryOptions,
|
||||
listenerId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,14 +6,18 @@ import DocumentChange from './DocumentChange';
|
||||
import DocumentSnapshot from './DocumentSnapshot';
|
||||
|
||||
import type Firestore from './';
|
||||
import type { FirestoreNativeDocumentChange, FirestoreNativeDocumentSnapshot, FirestoreSnapshotMetadata } from '../../types';
|
||||
import type {
|
||||
FirestoreNativeDocumentChange,
|
||||
FirestoreNativeDocumentSnapshot,
|
||||
FirestoreSnapshotMetadata,
|
||||
} from '../../types';
|
||||
import type Query from './Query';
|
||||
|
||||
type QuerySnapshotNativeData = {
|
||||
changes: FirestoreNativeDocumentChange[],
|
||||
documents: FirestoreNativeDocumentSnapshot[],
|
||||
metadata: FirestoreSnapshotMetadata,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class QuerySnapshot
|
||||
@ -24,9 +28,17 @@ export default class QuerySnapshot {
|
||||
_metadata: FirestoreSnapshotMetadata;
|
||||
_query: Query;
|
||||
|
||||
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));
|
||||
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;
|
||||
this._query = query;
|
||||
}
|
||||
@ -59,7 +71,7 @@ export default class QuerySnapshot {
|
||||
// TODO: Validation
|
||||
// validate.isFunction('callback', callback);
|
||||
|
||||
this._docs.forEach((doc) => {
|
||||
this._docs.forEach(doc => {
|
||||
callback(doc);
|
||||
});
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ type DocumentWrite = {
|
||||
options?: Object,
|
||||
path: string,
|
||||
type: 'DELETE' | 'SET' | 'UPDATE',
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class WriteBatch
|
||||
@ -47,7 +47,11 @@ export default class WriteBatch {
|
||||
return this;
|
||||
}
|
||||
|
||||
set(docRef: DocumentReference, data: Object, writeOptions?: FirestoreWriteOptions) {
|
||||
set(
|
||||
docRef: DocumentReference,
|
||||
data: Object,
|
||||
writeOptions?: FirestoreWriteOptions
|
||||
) {
|
||||
// TODO: Validation
|
||||
// validate.isDocumentReference('docRef', docRef);
|
||||
// validate.isDocument('data', data);
|
||||
@ -69,11 +73,16 @@ export default class WriteBatch {
|
||||
let data = {};
|
||||
if (args.length === 1) {
|
||||
if (!isObject(args[0])) {
|
||||
throw new Error('WriteBatch.update failed: If using two arguments, the second must be an object.');
|
||||
throw new Error(
|
||||
'WriteBatch.update failed: If using two arguments, the second must be an object.'
|
||||
);
|
||||
}
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
data = args[0];
|
||||
} else if (args.length % 2 === 1) {
|
||||
throw new Error('WriteBatch.update failed: Must have a document reference, followed by either a single object argument, or equal numbers of key/value pairs.');
|
||||
throw new Error(
|
||||
'WriteBatch.update failed: Must have a document reference, followed by either a single object argument, or equal numbers of key/value pairs.'
|
||||
);
|
||||
} else {
|
||||
for (let i = 0; i < args.length; i += 2) {
|
||||
const key = args[i];
|
||||
@ -83,7 +92,9 @@ export default class WriteBatch {
|
||||
} else if (key instanceof FieldPath) {
|
||||
data = mergeFieldPathData(data, key._segments, value);
|
||||
} else {
|
||||
throw new Error(`WriteBatch.update failed: Argument at index ${i} must be a string or FieldPath`);
|
||||
throw new Error(
|
||||
`WriteBatch.update failed: Argument at index ${i} must be a string or FieldPath`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ type CollectionSyncEvent = {
|
||||
error?: Object,
|
||||
listenerId: string,
|
||||
path: string,
|
||||
}
|
||||
};
|
||||
|
||||
type DocumentSyncEvent = {
|
||||
appName: string,
|
||||
@ -33,7 +33,7 @@ type DocumentSyncEvent = {
|
||||
error?: Object,
|
||||
listenerId: string,
|
||||
path: string,
|
||||
}
|
||||
};
|
||||
|
||||
const NATIVE_EVENTS = [
|
||||
'firestore_collection_sync_event',
|
||||
@ -62,14 +62,14 @@ export default class Firestore extends ModuleBase {
|
||||
// sub to internal native event - this fans out to
|
||||
// public event name: onCollectionSnapshot
|
||||
getAppEventName(this, 'firestore_collection_sync_event'),
|
||||
this._onCollectionSyncEvent.bind(this),
|
||||
this._onCollectionSyncEvent.bind(this)
|
||||
);
|
||||
|
||||
SharedEventEmitter.addListener(
|
||||
// sub to internal native event - this fans out to
|
||||
// public event name: onDocumentSnapshot
|
||||
getAppEventName(this, 'firestore_document_sync_event'),
|
||||
this._onDocumentSyncEvent.bind(this),
|
||||
this._onDocumentSyncEvent.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
@ -114,7 +114,12 @@ 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 {
|
||||
@ -128,9 +133,15 @@ export default class Firestore extends ModuleBase {
|
||||
*/
|
||||
_onCollectionSyncEvent(event: CollectionSyncEvent) {
|
||||
if (event.error) {
|
||||
SharedEventEmitter.emit(getAppEventName(this, `onQuerySnapshotError:${event.listenerId}`), event.error);
|
||||
SharedEventEmitter.emit(
|
||||
getAppEventName(this, `onQuerySnapshotError:${event.listenerId}`),
|
||||
event.error
|
||||
);
|
||||
} else {
|
||||
SharedEventEmitter.emit(getAppEventName(this, `onQuerySnapshot:${event.listenerId}`), event.querySnapshot);
|
||||
SharedEventEmitter.emit(
|
||||
getAppEventName(this, `onQuerySnapshot:${event.listenerId}`),
|
||||
event.querySnapshot
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,9 +152,15 @@ export default class Firestore extends ModuleBase {
|
||||
*/
|
||||
_onDocumentSyncEvent(event: DocumentSyncEvent) {
|
||||
if (event.error) {
|
||||
SharedEventEmitter.emit(getAppEventName(this, `onDocumentSnapshotError:${event.listenerId}`), event.error);
|
||||
SharedEventEmitter.emit(
|
||||
getAppEventName(this, `onDocumentSnapshotError:${event.listenerId}`),
|
||||
event.error
|
||||
);
|
||||
} else {
|
||||
SharedEventEmitter.emit(getAppEventName(this, `onDocumentSnapshot:${event.listenerId}`), event.documentSnapshot);
|
||||
SharedEventEmitter.emit(
|
||||
getAppEventName(this, `onDocumentSnapshot:${event.listenerId}`),
|
||||
event.documentSnapshot
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,12 @@ const buildFieldPathData = (segments: string[], value: any): Object => {
|
||||
};
|
||||
};
|
||||
|
||||
export const mergeFieldPathData = (data: Object, segments: string[], value: any): Object => {
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export const mergeFieldPathData = (
|
||||
data: Object,
|
||||
segments: string[],
|
||||
value: any
|
||||
): Object => {
|
||||
if (segments.length === 1) {
|
||||
return {
|
||||
...data,
|
||||
@ -22,7 +27,11 @@ export const mergeFieldPathData = (data: Object, segments: string[], value: any)
|
||||
} else if (data[segments[0]]) {
|
||||
return {
|
||||
...data,
|
||||
[segments[0]]: mergeFieldPathData(data[segments[0]], segments.slice(1), value),
|
||||
[segments[0]]: mergeFieldPathData(
|
||||
data[segments[0]],
|
||||
segments.slice(1),
|
||||
value
|
||||
),
|
||||
};
|
||||
}
|
||||
return {
|
||||
|
@ -4,7 +4,10 @@
|
||||
|
||||
import DocumentReference from '../DocumentReference';
|
||||
import { DOCUMENT_ID } from '../FieldPath';
|
||||
import { DELETE_FIELD_VALUE, SERVER_TIMESTAMP_FIELD_VALUE } from '../FieldValue';
|
||||
import {
|
||||
DELETE_FIELD_VALUE,
|
||||
SERVER_TIMESTAMP_FIELD_VALUE,
|
||||
} from '../FieldValue';
|
||||
import GeoPoint from '../GeoPoint';
|
||||
import Path from '../Path';
|
||||
import { typeOf } from '../../../utils';
|
||||
@ -18,10 +21,12 @@ import type { FirestoreTypeMap } from '../../../types';
|
||||
* for transmission to the native side
|
||||
*/
|
||||
|
||||
export const buildNativeMap = (data: Object): { [string]: FirestoreTypeMap } => {
|
||||
export const buildNativeMap = (
|
||||
data: Object
|
||||
): { [string]: FirestoreTypeMap } => {
|
||||
const nativeData = {};
|
||||
if (data) {
|
||||
Object.keys(data).forEach((key) => {
|
||||
Object.keys(data).forEach(key => {
|
||||
const typeMap = buildTypeMap(data[key]);
|
||||
if (typeMap) {
|
||||
nativeData[key] = typeMap;
|
||||
@ -34,7 +39,7 @@ export const buildNativeMap = (data: Object): { [string]: FirestoreTypeMap } =>
|
||||
export const buildNativeArray = (array: Object[]): FirestoreTypeMap[] => {
|
||||
const nativeArray = [];
|
||||
if (array) {
|
||||
array.forEach((value) => {
|
||||
array.forEach(value => {
|
||||
const typeMap = buildTypeMap(value);
|
||||
if (typeMap) {
|
||||
nativeArray.push(typeMap);
|
||||
@ -110,21 +115,27 @@ export const buildTypeMap = (value: any): FirestoreTypeMap | null => {
|
||||
* side and converts to the correct Firestore JS types
|
||||
*/
|
||||
|
||||
export const parseNativeMap = (firestore: Firestore, nativeData: { [string]: FirestoreTypeMap }): Object | void => {
|
||||
export const parseNativeMap = (
|
||||
firestore: Firestore,
|
||||
nativeData: { [string]: FirestoreTypeMap }
|
||||
): Object | void => {
|
||||
let data;
|
||||
if (nativeData) {
|
||||
data = {};
|
||||
Object.keys(nativeData).forEach((key) => {
|
||||
Object.keys(nativeData).forEach(key => {
|
||||
data[key] = parseTypeMap(firestore, nativeData[key]);
|
||||
});
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
const parseNativeArray = (firestore: Firestore, nativeArray: FirestoreTypeMap[]): any[] => {
|
||||
const parseNativeArray = (
|
||||
firestore: Firestore,
|
||||
nativeArray: FirestoreTypeMap[]
|
||||
): any[] => {
|
||||
const array = [];
|
||||
if (nativeArray) {
|
||||
nativeArray.forEach((typeMap) => {
|
||||
nativeArray.forEach(typeMap => {
|
||||
array.push(parseTypeMap(firestore, typeMap));
|
||||
});
|
||||
}
|
||||
|
@ -13,9 +13,7 @@ const EVENT_TYPE = {
|
||||
Link: 'dynamic_link_received',
|
||||
};
|
||||
|
||||
const NATIVE_EVENTS = [
|
||||
EVENT_TYPE.Link,
|
||||
];
|
||||
const NATIVE_EVENTS = [EVENT_TYPE.Link];
|
||||
|
||||
export const MODULE_NAME = 'RNFirebaseLinks';
|
||||
export const NAMESPACE = 'links';
|
||||
@ -59,10 +57,16 @@ function checkForMandatoryParameters(parameters: Object): void {
|
||||
if (!isString(parameters.link)) {
|
||||
throw new Error('No link was specified.');
|
||||
}
|
||||
if (isObject(parameters.androidInfo) && !isString(parameters.androidInfo.androidPackageName)) {
|
||||
if (
|
||||
isObject(parameters.androidInfo) &&
|
||||
!isString(parameters.androidInfo.androidPackageName)
|
||||
) {
|
||||
throw new Error('No androidPackageName was specified.');
|
||||
}
|
||||
if (isObject(parameters.iosInfo) && !isString(parameters.iosInfo.iosBundleId)) {
|
||||
if (
|
||||
isObject(parameters.iosInfo) &&
|
||||
!isString(parameters.iosInfo.iosBundleId)
|
||||
) {
|
||||
throw new Error('No iosBundleId was specified.');
|
||||
}
|
||||
}
|
||||
@ -98,7 +102,10 @@ export default class Links extends ModuleBase {
|
||||
* @returns {Function}
|
||||
*/
|
||||
onLink(listener: Function): () => any {
|
||||
const rnListener = SharedEventEmitter.addListener(EVENT_TYPE.Link, listener);
|
||||
const rnListener = SharedEventEmitter.addListener(
|
||||
EVENT_TYPE.Link,
|
||||
listener
|
||||
);
|
||||
return () => rnListener.remove();
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,9 @@ export default class RemoteMessage {
|
||||
id: generatePushID(),
|
||||
ttl: 3600,
|
||||
// add the googleapis sender id part if not already added.
|
||||
sender: `${sender}`.includes('@') ? sender : `${sender}@gcm.googleapis.com`,
|
||||
sender: `${sender}`.includes('@')
|
||||
? sender
|
||||
: `${sender}@gcm.googleapis.com`,
|
||||
type: 'remote',
|
||||
data: {},
|
||||
};
|
||||
@ -57,7 +59,6 @@ export default class RemoteMessage {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param data
|
||||
@ -65,7 +66,9 @@ export default class RemoteMessage {
|
||||
*/
|
||||
setData(data: Object = {}) {
|
||||
if (!isObject(data)) {
|
||||
throw new Error(`RemoteMessage:setData expects an object as the first parameter but got type '${typeof data}'.`);
|
||||
throw new Error(
|
||||
`RemoteMessage:setData expects an object as the first parameter but got type '${typeof data}'.`
|
||||
);
|
||||
}
|
||||
|
||||
const props = Object.keys(data);
|
||||
|
@ -33,10 +33,7 @@ const WILL_PRESENT_RESULT = {
|
||||
None: 'UNNotificationPresentationOptionNone',
|
||||
};
|
||||
|
||||
const NATIVE_EVENTS = [
|
||||
EVENT_TYPE.RefreshToken,
|
||||
EVENT_TYPE.Notification,
|
||||
];
|
||||
const NATIVE_EVENTS = [EVENT_TYPE.RefreshToken, EVENT_TYPE.Notification];
|
||||
|
||||
const FirebaseMessaging = NativeModules.RNFirebaseMessaging;
|
||||
|
||||
@ -49,7 +46,6 @@ function finish(data) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!this._finishCalled && this._completionHandlerId) {
|
||||
let result = data;
|
||||
|
||||
@ -59,21 +55,35 @@ function finish(data) {
|
||||
case NOTIFICATION_TYPE.Remote:
|
||||
result = result || REMOTE_NOTIFICATION_RESULT.NoData;
|
||||
if (!Object.values(REMOTE_NOTIFICATION_RESULT).includes(result)) {
|
||||
throw new Error('Invalid REMOTE_NOTIFICATION_RESULT value, use messaging().REMOTE_NOTIFICATION_RESULT');
|
||||
throw new Error(
|
||||
'Invalid REMOTE_NOTIFICATION_RESULT value, use messaging().REMOTE_NOTIFICATION_RESULT'
|
||||
);
|
||||
}
|
||||
|
||||
FirebaseMessaging.finishRemoteNotification(this._completionHandlerId, result);
|
||||
FirebaseMessaging.finishRemoteNotification(
|
||||
this._completionHandlerId,
|
||||
result
|
||||
);
|
||||
return;
|
||||
case NOTIFICATION_TYPE.NotificationResponse:
|
||||
FirebaseMessaging.finishNotificationResponse(this._completionHandlerId);
|
||||
return;
|
||||
case NOTIFICATION_TYPE.WillPresent:
|
||||
result = result || (this.show_in_foreground ? WILL_PRESENT_RESULT.All : WILL_PRESENT_RESULT.None);
|
||||
result =
|
||||
result ||
|
||||
(this.show_in_foreground
|
||||
? WILL_PRESENT_RESULT.All
|
||||
: WILL_PRESENT_RESULT.None);
|
||||
if (!Object.values(WILL_PRESENT_RESULT).includes(result)) {
|
||||
throw new Error('Invalid WILL_PRESENT_RESULT value, use messaging().WILL_PRESENT_RESULT');
|
||||
throw new Error(
|
||||
'Invalid WILL_PRESENT_RESULT value, use messaging().WILL_PRESENT_RESULT'
|
||||
);
|
||||
}
|
||||
|
||||
FirebaseMessaging.finishWillPresentNotification(this._completionHandlerId, result);
|
||||
FirebaseMessaging.finishWillPresentNotification(
|
||||
this._completionHandlerId,
|
||||
result
|
||||
);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
@ -155,7 +165,10 @@ export default class Messaging extends ModuleBase {
|
||||
*/
|
||||
scheduleLocalNotification(notification: Object): Promise<void> {
|
||||
const _notification = Object.assign({}, notification);
|
||||
if (!notification.id) return Promise.reject(new Error('An id is required to schedule a local notification.'));
|
||||
if (!notification.id)
|
||||
return Promise.reject(
|
||||
new Error('An id is required to schedule a local notification.')
|
||||
);
|
||||
_notification.local_notification = true;
|
||||
return getNativeModule(this).scheduleLocalNotification(_notification);
|
||||
}
|
||||
@ -188,7 +201,8 @@ export default class Messaging extends ModuleBase {
|
||||
*/
|
||||
removeDeliveredNotification(id: string): Promise<void> {
|
||||
if (!id) return Promise.reject(new Error('Missing notification id'));
|
||||
if (id === '*') return getNativeModule(this).removeAllDeliveredNotifications();
|
||||
if (id === '*')
|
||||
return getNativeModule(this).removeAllDeliveredNotifications();
|
||||
return getNativeModule(this).removeDeliveredNotification(id);
|
||||
}
|
||||
|
||||
@ -201,7 +215,6 @@ export default class Messaging extends ModuleBase {
|
||||
return getNativeModule(this).requestPermissions();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set notification count badge number
|
||||
* @param n
|
||||
@ -223,10 +236,10 @@ export default class Messaging extends ModuleBase {
|
||||
* @param listener
|
||||
* @returns {*}
|
||||
*/
|
||||
onMessage(listener: (Object) => any): () => any {
|
||||
onMessage(listener: Object => any): () => any {
|
||||
const rnListener = SharedEventEmitter.addListener(
|
||||
EVENT_TYPE.Notification,
|
||||
async (event) => {
|
||||
async event => {
|
||||
const data = {
|
||||
...event,
|
||||
finish,
|
||||
@ -236,7 +249,7 @@ export default class Messaging extends ModuleBase {
|
||||
if (!data._finishCalled) {
|
||||
data.finish();
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
return () => rnListener.remove();
|
||||
}
|
||||
@ -246,8 +259,11 @@ export default class Messaging extends ModuleBase {
|
||||
* @param listener
|
||||
* @returns {*}
|
||||
*/
|
||||
onTokenRefresh(listener: (string) => any): () => any {
|
||||
const rnListener = SharedEventEmitter.addListener(EVENT_TYPE.RefreshToken, listener);
|
||||
onTokenRefresh(listener: string => any): () => any {
|
||||
const rnListener = SharedEventEmitter.addListener(
|
||||
EVENT_TYPE.RefreshToken,
|
||||
listener
|
||||
);
|
||||
return () => rnListener.remove();
|
||||
}
|
||||
|
||||
@ -273,7 +289,9 @@ export default class Messaging extends ModuleBase {
|
||||
*/
|
||||
send(remoteMessage: RemoteMessage): Promise<void> {
|
||||
if (!(remoteMessage instanceof RemoteMessage)) {
|
||||
throw new Error('messaging().send requires an instance of RemoteMessage as the first argument.');
|
||||
throw new Error(
|
||||
'messaging().send requires an instance of RemoteMessage as the first argument.'
|
||||
);
|
||||
}
|
||||
|
||||
return getNativeModule(this).send(remoteMessage.toJSON());
|
||||
|
@ -14,10 +14,7 @@ import type App from '../core/firebase-app';
|
||||
|
||||
const FirebaseStorage = NativeModules.RNFirebaseStorage;
|
||||
|
||||
const NATIVE_EVENTS = [
|
||||
'storage_event',
|
||||
'storage_error',
|
||||
];
|
||||
const NATIVE_EVENTS = ['storage_event', 'storage_error'];
|
||||
|
||||
export const MODULE_NAME = 'RNFirebaseStorage';
|
||||
export const NAMESPACE = 'storage';
|
||||
@ -38,12 +35,12 @@ export default class Storage extends ModuleBase {
|
||||
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this, 'storage_event'),
|
||||
this._handleStorageEvent.bind(this),
|
||||
this._handleStorageEvent.bind(this)
|
||||
);
|
||||
|
||||
SharedEventEmitter.addListener(
|
||||
getAppEventName(this, 'storage_error'),
|
||||
this._handleStorageEvent.bind(this),
|
||||
this._handleStorageEvent.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
@ -118,12 +115,23 @@ export default class Storage extends ModuleBase {
|
||||
SharedEventEmitter.emit(this._getSubEventName(path, eventName), body);
|
||||
}
|
||||
|
||||
_addListener(path: string, eventName: string, cb: (evt: Object) => Object): void {
|
||||
_addListener(
|
||||
path: string,
|
||||
eventName: string,
|
||||
cb: (evt: Object) => Object
|
||||
): void {
|
||||
SharedEventEmitter.addListener(this._getSubEventName(path, eventName), cb);
|
||||
}
|
||||
|
||||
_removeListener(path: string, eventName: string, origCB: (evt: Object) => Object): void {
|
||||
SharedEventEmitter.removeListener(this._getSubEventName(path, eventName), origCB);
|
||||
_removeListener(
|
||||
path: string,
|
||||
eventName: string,
|
||||
origCB: (evt: Object) => Object
|
||||
): void {
|
||||
SharedEventEmitter.removeListener(
|
||||
this._getSubEventName(path, eventName),
|
||||
origCB
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,15 +146,18 @@ export const statics = {
|
||||
CANCELLED: 'cancelled',
|
||||
ERROR: 'error',
|
||||
},
|
||||
Native: FirebaseStorage ? {
|
||||
MAIN_BUNDLE_PATH: FirebaseStorage.MAIN_BUNDLE_PATH,
|
||||
CACHES_DIRECTORY_PATH: FirebaseStorage.CACHES_DIRECTORY_PATH,
|
||||
DOCUMENT_DIRECTORY_PATH: FirebaseStorage.DOCUMENT_DIRECTORY_PATH,
|
||||
EXTERNAL_DIRECTORY_PATH: FirebaseStorage.EXTERNAL_DIRECTORY_PATH,
|
||||
EXTERNAL_STORAGE_DIRECTORY_PATH: FirebaseStorage.EXTERNAL_STORAGE_DIRECTORY_PATH,
|
||||
TEMP_DIRECTORY_PATH: FirebaseStorage.TEMP_DIRECTORY_PATH,
|
||||
LIBRARY_DIRECTORY_PATH: FirebaseStorage.LIBRARY_DIRECTORY_PATH,
|
||||
FILETYPE_REGULAR: FirebaseStorage.FILETYPE_REGULAR,
|
||||
FILETYPE_DIRECTORY: FirebaseStorage.FILETYPE_DIRECTORY,
|
||||
} : {},
|
||||
Native: FirebaseStorage
|
||||
? {
|
||||
MAIN_BUNDLE_PATH: FirebaseStorage.MAIN_BUNDLE_PATH,
|
||||
CACHES_DIRECTORY_PATH: FirebaseStorage.CACHES_DIRECTORY_PATH,
|
||||
DOCUMENT_DIRECTORY_PATH: FirebaseStorage.DOCUMENT_DIRECTORY_PATH,
|
||||
EXTERNAL_DIRECTORY_PATH: FirebaseStorage.EXTERNAL_DIRECTORY_PATH,
|
||||
EXTERNAL_STORAGE_DIRECTORY_PATH:
|
||||
FirebaseStorage.EXTERNAL_STORAGE_DIRECTORY_PATH,
|
||||
TEMP_DIRECTORY_PATH: FirebaseStorage.TEMP_DIRECTORY_PATH,
|
||||
LIBRARY_DIRECTORY_PATH: FirebaseStorage.LIBRARY_DIRECTORY_PATH,
|
||||
FILETYPE_REGULAR: FirebaseStorage.FILETYPE_REGULAR,
|
||||
FILETYPE_DIRECTORY: FirebaseStorage.FILETYPE_DIRECTORY,
|
||||
}
|
||||
: {},
|
||||
};
|
||||
|
@ -7,7 +7,6 @@ import StorageTask, { UPLOAD_TASK, DOWNLOAD_TASK } from './task';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
import type Storage from './';
|
||||
|
||||
|
||||
/**
|
||||
* @url https://firebase.google.com/docs/reference/js/firebase.storage.Reference
|
||||
*/
|
||||
@ -75,7 +74,11 @@ export default class StorageReference extends ReferenceBase {
|
||||
* @return {Promise}
|
||||
*/
|
||||
downloadFile(filePath: string): Promise<Object> {
|
||||
return new StorageTask(DOWNLOAD_TASK, getNativeModule(this._storage).downloadFile(this.path, filePath), this);
|
||||
return new StorageTask(
|
||||
DOWNLOAD_TASK,
|
||||
getNativeModule(this._storage).downloadFile(this.path, filePath),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,6 +97,10 @@ export default class StorageReference extends ReferenceBase {
|
||||
*/
|
||||
putFile(filePath: Object, metadata: Object = {}): Promise<Object> {
|
||||
const _filePath = filePath.replace('file://', '');
|
||||
return new StorageTask(UPLOAD_TASK, getNativeModule(this._storage).putFile(this.path, _filePath, metadata), this);
|
||||
return new StorageTask(
|
||||
UPLOAD_TASK,
|
||||
getNativeModule(this._storage).putFile(this.path, _filePath, metadata),
|
||||
this
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -12,31 +12,33 @@ export const DOWNLOAD_TASK = 'download';
|
||||
|
||||
declare type UploadTaskSnapshotType = {
|
||||
bytesTransferred: number,
|
||||
downloadURL: string|null,
|
||||
downloadURL: string | null,
|
||||
metadata: Object, // TODO flow type def for https://firebase.google.com/docs/reference/js/firebase.storage.FullMetadata.html
|
||||
ref: StorageReference,
|
||||
state: (
|
||||
typeof StorageStatics.TaskState.RUNNING
|
||||
state:
|
||||
| typeof StorageStatics.TaskState.RUNNING
|
||||
| typeof StorageStatics.TaskState.PAUSED
|
||||
| typeof StorageStatics.TaskState.SUCCESS
|
||||
| typeof StorageStatics.TaskState.CANCELLED
|
||||
| typeof StorageStatics.TaskState.ERROR
|
||||
),
|
||||
| typeof StorageStatics.TaskState.ERROR,
|
||||
task: StorageTask,
|
||||
totalBytes: number,
|
||||
};
|
||||
|
||||
declare type FuncSnapshotType = null|(snapshot: UploadTaskSnapshotType) => any;
|
||||
declare type FuncSnapshotType =
|
||||
| null
|
||||
| ((snapshot: UploadTaskSnapshotType) => any);
|
||||
|
||||
declare type FuncErrorType = null|(error: Error) => any;
|
||||
declare type FuncErrorType = null | ((error: Error) => any);
|
||||
|
||||
declare type NextOrObserverType = null |
|
||||
{
|
||||
next?: FuncSnapshotType,
|
||||
error?: FuncErrorType,
|
||||
complete?:FuncSnapshotType
|
||||
} |
|
||||
FuncSnapshotType;
|
||||
declare type NextOrObserverType =
|
||||
| null
|
||||
| {
|
||||
next?: FuncSnapshotType,
|
||||
error?: FuncErrorType,
|
||||
complete?: FuncSnapshotType,
|
||||
}
|
||||
| FuncSnapshotType;
|
||||
|
||||
/**
|
||||
* @url https://firebase.google.com/docs/reference/js/firebase.storage.UploadTask
|
||||
@ -49,7 +51,11 @@ export default class StorageTask {
|
||||
then: () => Promise<*>;
|
||||
catch: () => Promise<*>;
|
||||
|
||||
constructor(type: typeof UPLOAD_TASK | typeof DOWNLOAD_TASK, promise: Promise<*>, storageRef: StorageReference) {
|
||||
constructor(
|
||||
type: typeof UPLOAD_TASK | typeof DOWNLOAD_TASK,
|
||||
promise: Promise<*>,
|
||||
storageRef: StorageReference
|
||||
) {
|
||||
this.type = type;
|
||||
this.ref = storageRef;
|
||||
this.storage = storageRef._storage;
|
||||
@ -66,9 +72,9 @@ export default class StorageTask {
|
||||
* @returns {Promise.<T>}
|
||||
* @private
|
||||
*/
|
||||
_interceptSnapshotEvent(f: ?Function): null | () => * {
|
||||
_interceptSnapshotEvent(f: ?Function): null | (() => *) {
|
||||
if (!isFunction(f)) return null;
|
||||
return (snapshot) => {
|
||||
return snapshot => {
|
||||
const _snapshot = Object.assign({}, snapshot);
|
||||
_snapshot.task = this;
|
||||
_snapshot.ref = this.ref;
|
||||
@ -82,9 +88,9 @@ export default class StorageTask {
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
_interceptErrorEvent(f: ?Function): null | (Error) => * {
|
||||
_interceptErrorEvent(f: ?Function): null | (Error => *) {
|
||||
if (!isFunction(f)) return null;
|
||||
return (error) => {
|
||||
return error => {
|
||||
const _error = new Error(error.message);
|
||||
// $FlowFixMe
|
||||
_error.code = error.code;
|
||||
@ -100,7 +106,11 @@ export default class StorageTask {
|
||||
* @returns {function()}
|
||||
* @private
|
||||
*/
|
||||
_subscribe(nextOrObserver: NextOrObserverType, error: FuncErrorType, complete: FuncSnapshotType): Function {
|
||||
_subscribe(
|
||||
nextOrObserver: NextOrObserverType,
|
||||
error: FuncErrorType,
|
||||
complete: FuncSnapshotType
|
||||
): Function {
|
||||
let _error;
|
||||
let _next;
|
||||
let _complete;
|
||||
@ -119,28 +129,31 @@ export default class StorageTask {
|
||||
this.storage._addListener(
|
||||
this.path,
|
||||
StorageStatics.TaskEvent.STATE_CHANGED,
|
||||
_next,
|
||||
_next
|
||||
);
|
||||
}
|
||||
if (_error) {
|
||||
this.storage._addListener(
|
||||
this.path,
|
||||
`${this.type}_failure`,
|
||||
_error,
|
||||
);
|
||||
this.storage._addListener(this.path, `${this.type}_failure`, _error);
|
||||
}
|
||||
if (_complete) {
|
||||
this.storage._addListener(
|
||||
this.path,
|
||||
`${this.type}_success`,
|
||||
_complete,
|
||||
);
|
||||
this.storage._addListener(this.path, `${this.type}_success`, _complete);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (_next) this.storage._removeListener(this.path, StorageStatics.TaskEvent.STATE_CHANGED, _next);
|
||||
if (_error) this.storage._removeListener(this.path, `${this.type}_failure`, _error);
|
||||
if (_complete) this.storage._removeListener(this.path, `${this.type}_success`, _complete);
|
||||
if (_next)
|
||||
this.storage._removeListener(
|
||||
this.path,
|
||||
StorageStatics.TaskEvent.STATE_CHANGED,
|
||||
_next
|
||||
);
|
||||
if (_error)
|
||||
this.storage._removeListener(this.path, `${this.type}_failure`, _error);
|
||||
if (_complete)
|
||||
this.storage._removeListener(
|
||||
this.path,
|
||||
`${this.type}_success`,
|
||||
_complete
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@ -152,13 +165,24 @@ export default class StorageTask {
|
||||
* @param complete
|
||||
* @returns {function()}
|
||||
*/
|
||||
on(event: string = StorageStatics.TaskEvent.STATE_CHANGED, nextOrObserver: NextOrObserverType, error: FuncErrorType, complete: FuncSnapshotType): Function {
|
||||
on(
|
||||
event: string = StorageStatics.TaskEvent.STATE_CHANGED,
|
||||
nextOrObserver: NextOrObserverType,
|
||||
error: FuncErrorType,
|
||||
complete: FuncSnapshotType
|
||||
): Function {
|
||||
if (!event) {
|
||||
throw new Error('StorageTask.on listener is missing required string argument \'event\'.');
|
||||
throw new Error(
|
||||
"StorageTask.on listener is missing required string argument 'event'."
|
||||
);
|
||||
}
|
||||
|
||||
if (event !== StorageStatics.TaskEvent.STATE_CHANGED) {
|
||||
throw new Error(`StorageTask.on event argument must be a string with a value of '${StorageStatics.TaskEvent.STATE_CHANGED}'`);
|
||||
throw new Error(
|
||||
`StorageTask.on event argument must be a string with a value of '${
|
||||
StorageStatics.TaskEvent.STATE_CHANGED
|
||||
}'`
|
||||
);
|
||||
}
|
||||
|
||||
// if only event provided return the subscriber function
|
||||
@ -170,16 +194,22 @@ export default class StorageTask {
|
||||
}
|
||||
|
||||
pause() {
|
||||
throw new Error('.pause() is not currently supported by react-native-firebase');
|
||||
throw new Error(
|
||||
'.pause() is not currently supported by react-native-firebase'
|
||||
);
|
||||
}
|
||||
|
||||
resume() {
|
||||
// todo
|
||||
throw new Error('.resume() is not currently supported by react-native-firebase');
|
||||
throw new Error(
|
||||
'.resume() is not currently supported by react-native-firebase'
|
||||
);
|
||||
}
|
||||
|
||||
cancel() {
|
||||
// todo
|
||||
throw new Error('.cancel() is not currently supported by react-native-firebase');
|
||||
throw new Error(
|
||||
'.cancel() is not currently supported by react-native-firebase'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,8 @@ type GoogleApiAvailabilityType = {
|
||||
isAvailable: boolean,
|
||||
isUserResolvableError?: boolean,
|
||||
hasResolution?: boolean,
|
||||
error?: string
|
||||
}
|
||||
error?: string,
|
||||
};
|
||||
|
||||
export const MODULE_NAME = 'RNFirebaseUtils';
|
||||
export const NAMESPACE = 'utils';
|
||||
@ -36,12 +36,16 @@ export default class RNFirebaseUtils extends ModuleBase {
|
||||
const { status } = this.playServicesAvailability;
|
||||
|
||||
if (!this.playServicesAvailability.isAvailable) {
|
||||
if (INTERNALS.OPTIONS.promptOnMissingPlayServices && this.playServicesAvailability.isUserResolvableError) {
|
||||
if (
|
||||
INTERNALS.OPTIONS.promptOnMissingPlayServices &&
|
||||
this.playServicesAvailability.isUserResolvableError
|
||||
) {
|
||||
this.promptForPlayServices();
|
||||
} else {
|
||||
const error = INTERNALS.STRINGS.ERROR_PLAY_SERVICES(status);
|
||||
if (INTERNALS.OPTIONS.errorOnMissingPlayServices) {
|
||||
if (status === 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);
|
||||
@ -80,7 +84,12 @@ export default class RNFirebaseUtils extends ModuleBase {
|
||||
* @return {RNFirebase.GoogleApiAvailabilityType|{isAvailable: boolean, status: number}}
|
||||
*/
|
||||
get playServicesAvailability(): GoogleApiAvailabilityType {
|
||||
return FirebaseCoreModule.playServicesAvailability || { isAvailable: true, status: 0 };
|
||||
return (
|
||||
FirebaseCoreModule.playServicesAvailability || {
|
||||
isAvailable: true,
|
||||
status: 0,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,5 +111,4 @@ export default class RNFirebaseUtils extends ModuleBase {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const statics = {};
|
||||
|
@ -35,8 +35,8 @@ export type FirebaseError = {
|
||||
stack: string,
|
||||
path: string,
|
||||
details: string,
|
||||
modifiers: string
|
||||
}
|
||||
modifiers: string,
|
||||
};
|
||||
|
||||
export type FirebaseModule = $Subtype<ModuleBase>;
|
||||
|
||||
@ -45,15 +45,36 @@ export type FirebaseModuleConfig = {
|
||||
moduleName: FirebaseModuleName,
|
||||
multiApp: boolean,
|
||||
namespace: FirebaseNamespace,
|
||||
}
|
||||
};
|
||||
|
||||
export type FirebaseModuleName = 'RNFirebaseAdmob' | 'RNFirebaseAnalytics' | 'RNFirebaseAuth'
|
||||
| 'RNFirebaseRemoteConfig' | 'RNFirebaseCrash' | 'RNFirebaseCrashlytics' | 'RNFirebaseDatabase'
|
||||
| 'RNFirebaseFirestore' | 'RNFirebaseLinks' | 'RNFirebaseMessaging' | 'RNFirebasePerformance'
|
||||
| 'RNFirebaseStorage' | 'RNFirebaseUtils';
|
||||
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'
|
||||
export type FirebaseNamespace =
|
||||
| 'admob'
|
||||
| 'analytics'
|
||||
| 'auth'
|
||||
| 'config'
|
||||
| 'crash'
|
||||
| 'crashlytics'
|
||||
| 'database'
|
||||
| 'firestore'
|
||||
| 'links'
|
||||
| 'messaging'
|
||||
| 'perf'
|
||||
| 'storage'
|
||||
| 'utils';
|
||||
|
||||
export type FirebaseOptions = {
|
||||
@ -63,7 +84,7 @@ export type FirebaseOptions = {
|
||||
messagingSenderId: string,
|
||||
projectId: string,
|
||||
storageBucket: string,
|
||||
}
|
||||
};
|
||||
|
||||
export type FirebaseModuleAndStatics<M: FirebaseModule, S: FirebaseStatics> = {
|
||||
(): M,
|
||||
@ -115,14 +136,14 @@ export type DatabaseModule = {
|
||||
} & DatabaseStatics;
|
||||
|
||||
export type DatabaseModifier = {
|
||||
id: string;
|
||||
type: 'orderBy' | 'limit' | 'filter';
|
||||
name?: string;
|
||||
key?: string;
|
||||
limit?: number;
|
||||
value?: any;
|
||||
valueType?: string;
|
||||
}
|
||||
id: string,
|
||||
type: 'orderBy' | 'limit' | 'filter',
|
||||
name?: string,
|
||||
key?: string,
|
||||
limit?: number,
|
||||
value?: any,
|
||||
valueType?: string,
|
||||
};
|
||||
|
||||
/* Fabric types */
|
||||
export type CrashlyticsModule = {
|
||||
@ -132,7 +153,7 @@ export type CrashlyticsModule = {
|
||||
|
||||
export type FabricModule = {
|
||||
crashlytics: CrashlyticsModule,
|
||||
}
|
||||
};
|
||||
|
||||
/* Firestore types */
|
||||
|
||||
@ -146,30 +167,41 @@ export type FirestoreNativeDocumentChange = {
|
||||
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' | 'documentid' | 'fieldvalue' | 'geopoint' | 'null' | 'number' | 'object' | 'reference' | 'string',
|
||||
type:
|
||||
| 'array'
|
||||
| 'boolean'
|
||||
| 'date'
|
||||
| 'documentid'
|
||||
| 'fieldvalue'
|
||||
| 'geopoint'
|
||||
| 'null'
|
||||
| 'number'
|
||||
| 'object'
|
||||
| 'reference'
|
||||
| 'string',
|
||||
value: any,
|
||||
}
|
||||
};
|
||||
|
||||
export type FirestoreWriteOptions = {
|
||||
merge?: boolean,
|
||||
}
|
||||
};
|
||||
|
||||
/* Links types */
|
||||
|
||||
|
@ -29,7 +29,10 @@ export default class ModuleBase {
|
||||
|
||||
// check if native module exists as all native
|
||||
initialiseNativeModule(this, config);
|
||||
initialiseLogger(this, `${app.name}:${moduleName.replace('RNFirebase', '')}`);
|
||||
initialiseLogger(
|
||||
this,
|
||||
`${app.name}:${moduleName.replace('RNFirebase', '')}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,14 @@ export default class ReferenceBase {
|
||||
path: string;
|
||||
|
||||
constructor(path: string) {
|
||||
this.path = path || '/';
|
||||
if (path) {
|
||||
this.path =
|
||||
path.length > 1 && path.endsWith('/')
|
||||
? path.substring(0, path.length - 1)
|
||||
: path;
|
||||
} else {
|
||||
this.path = '/';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -15,6 +22,8 @@ export default class ReferenceBase {
|
||||
* {@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);
|
||||
return this.path === '/'
|
||||
? null
|
||||
: this.path.substring(this.path.lastIndexOf('/') + 1);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import DatabaseSnapshot from '../modules/database/snapshot';
|
||||
import DatabaseReference from '../modules/database/reference';
|
||||
import { isString, nativeToJSError } from '../utils';
|
||||
|
||||
type Listener = (DatabaseSnapshot) => any;
|
||||
type Listener = DatabaseSnapshot => any;
|
||||
|
||||
type Registration = {
|
||||
key: string,
|
||||
@ -19,7 +19,7 @@ type Registration = {
|
||||
listener: Listener,
|
||||
eventRegistrationKey: string,
|
||||
ref: DatabaseReference,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Internally used to manage firebase database realtime event
|
||||
@ -28,16 +28,18 @@ type Registration = {
|
||||
class SyncTree {
|
||||
_nativeEmitter: NativeEventEmitter;
|
||||
_reverseLookup: { [string]: Registration };
|
||||
_tree: { [string]: { [string]: { [string]: Listener }}};
|
||||
_tree: { [string]: { [string]: { [string]: Listener } } };
|
||||
|
||||
constructor() {
|
||||
this._tree = {};
|
||||
this._reverseLookup = {};
|
||||
if (NativeModules.RNFirebaseDatabase) {
|
||||
this._nativeEmitter = new NativeEventEmitter(NativeModules.RNFirebaseDatabase);
|
||||
this._nativeEmitter = new NativeEventEmitter(
|
||||
NativeModules.RNFirebaseDatabase
|
||||
);
|
||||
this._nativeEmitter.addListener(
|
||||
'database_sync_event',
|
||||
this._handleSyncEvent.bind(this),
|
||||
this._handleSyncEvent.bind(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -82,11 +84,10 @@ class SyncTree {
|
||||
return SharedEventEmitter.emit(
|
||||
eventRegistrationKey,
|
||||
new DatabaseSnapshot(registration.ref, snapshot),
|
||||
previousChildName,
|
||||
previousChildName
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Routes native database query listener cancellation events to their js counterparts.
|
||||
*
|
||||
@ -96,7 +97,10 @@ class SyncTree {
|
||||
_handleErrorEvent(event) {
|
||||
// console.log('SyncTree.ERROR >>>', event);
|
||||
const { code, message } = event.error;
|
||||
const { eventRegistrationKey, registrationCancellationKey } = event.registration;
|
||||
const {
|
||||
eventRegistrationKey,
|
||||
registrationCancellationKey,
|
||||
} = event.registration;
|
||||
|
||||
const registration = this.getRegistration(registrationCancellationKey);
|
||||
|
||||
@ -121,7 +125,9 @@ class SyncTree {
|
||||
* @return {null}
|
||||
*/
|
||||
getRegistration(registration: string): Registration | null {
|
||||
return this._reverseLookup[registration] ? Object.assign({}, this._reverseLookup[registration]) : null;
|
||||
return this._reverseLookup[registration]
|
||||
? Object.assign({}, this._reverseLookup[registration])
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,7 +165,9 @@ class SyncTree {
|
||||
|
||||
for (let i = 0, len = registrations.length; i < len; i++) {
|
||||
const registration = registrations[i];
|
||||
const subscriptions = 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];
|
||||
@ -188,7 +196,10 @@ class SyncTree {
|
||||
const eventKeys = Object.keys(this._tree[path] || {});
|
||||
|
||||
for (let i = 0, len = eventKeys.length; i < len; i++) {
|
||||
Array.prototype.push.apply(out, Object.keys(this._tree[path][eventKeys[i]]));
|
||||
Array.prototype.push.apply(
|
||||
out,
|
||||
Object.keys(this._tree[path][eventKeys[i]])
|
||||
);
|
||||
}
|
||||
|
||||
return out;
|
||||
@ -216,11 +227,17 @@ class SyncTree {
|
||||
* @param listener
|
||||
* @return {Array}
|
||||
*/
|
||||
getOneByPathEventListener(path: string, eventType: string, listener: Function): ?string {
|
||||
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]);
|
||||
const registrationsForPathEvent = Object.entries(
|
||||
this._tree[path][eventType]
|
||||
);
|
||||
|
||||
for (let i = 0; i < registrationsForPathEvent.length; i++) {
|
||||
const registration = registrationsForPathEvent[i];
|
||||
@ -230,7 +247,6 @@ class SyncTree {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register a new listener.
|
||||
*
|
||||
@ -256,7 +272,7 @@ class SyncTree {
|
||||
if (once) {
|
||||
SharedEventEmitter.once(
|
||||
eventRegistrationKey,
|
||||
this._onOnceRemoveRegistration(eventRegistrationKey, listener),
|
||||
this._onOnceRemoveRegistration(eventRegistrationKey, listener)
|
||||
);
|
||||
} else {
|
||||
SharedEventEmitter.addListener(eventRegistrationKey, listener);
|
||||
|
@ -18,7 +18,7 @@ import type {
|
||||
const FirebaseCoreModule = NativeModules.RNFirebase;
|
||||
|
||||
const APPS: { [string]: App } = {};
|
||||
const APP_MODULES: { [App]: { [string]: FirebaseModule }} = {};
|
||||
const APP_MODULES: { [App]: { [string]: FirebaseModule } } = {};
|
||||
const DEFAULT_APP_NAME = '[DEFAULT]';
|
||||
|
||||
export default {
|
||||
@ -43,13 +43,21 @@ export default {
|
||||
* @return {function()}
|
||||
* @private
|
||||
*/
|
||||
appModule<M: FirebaseModule>(app: App, namespace: FirebaseNamespace, InstanceClass: Class<M>): () => FirebaseModule {
|
||||
appModule<M: FirebaseModule>(
|
||||
app: App,
|
||||
namespace: FirebaseNamespace,
|
||||
InstanceClass: Class<M>
|
||||
): () => FirebaseModule {
|
||||
return (): M => {
|
||||
if (!APP_MODULES[app]) {
|
||||
APP_MODULES[app] = {};
|
||||
}
|
||||
|
||||
if (isAndroid && namespace !== 'utils' && !INTERNALS.FLAGS.checkedPlayServices) {
|
||||
if (
|
||||
isAndroid &&
|
||||
namespace !== 'utils' &&
|
||||
!INTERNALS.FLAGS.checkedPlayServices
|
||||
) {
|
||||
INTERNALS.FLAGS.checkedPlayServices = true;
|
||||
app.utils().checkPlayServicesAvailability();
|
||||
}
|
||||
@ -148,16 +156,21 @@ export default {
|
||||
* @param InstanceClass
|
||||
* @return {function(App=)}
|
||||
*/
|
||||
moduleAndStatics<M: FirebaseModule, S: FirebaseStatics>(namespace: FirebaseNamespace, statics: S, moduleName: FirebaseModuleName): FirebaseModuleAndStatics<M, S> {
|
||||
moduleAndStatics<M: FirebaseModule, S: FirebaseStatics>(
|
||||
namespace: FirebaseNamespace,
|
||||
statics: S,
|
||||
moduleName: FirebaseModuleName
|
||||
): FirebaseModuleAndStatics<M, S> {
|
||||
const getModule = (app?: App): FirebaseModule => {
|
||||
let _app = app;
|
||||
|
||||
// throw an error if it's not a valid app instance
|
||||
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 (!_app) _app = this.app(DEFAULT_APP_NAME);
|
||||
if (_app && !(_app instanceof App))
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_NOT_APP(namespace));
|
||||
else if (!_app)
|
||||
// default to the 'DEFAULT' app if no arg provided - will throw an error
|
||||
// if default app not initialized
|
||||
_app = this.app(DEFAULT_APP_NAME);
|
||||
if (namespace === 'crashlytics') {
|
||||
return _app.fabric[namespace]();
|
||||
}
|
||||
|
@ -12,11 +12,15 @@ const NATIVE_SUBSCRIPTIONS: { [string]: boolean } = {};
|
||||
|
||||
export const SharedEventEmitter = new EventEmitter();
|
||||
|
||||
export const getAppEventName = (module: ModuleBase, eventName: string): string => {
|
||||
return `${module.app.name}-${eventName}`;
|
||||
};
|
||||
export const getAppEventName = (
|
||||
module: ModuleBase,
|
||||
eventName: string
|
||||
): string => `${module.app.name}-${eventName}`;
|
||||
|
||||
const getNativeEmitter = (moduleName: FirebaseModuleName, module: ModuleBase): NativeEventEmitter => {
|
||||
const getNativeEmitter = (
|
||||
moduleName: FirebaseModuleName,
|
||||
module: ModuleBase
|
||||
): NativeEventEmitter => {
|
||||
const name = `${module.app.name}-${moduleName}`;
|
||||
const nativeModule = NativeModules[moduleName];
|
||||
if (!NATIVE_EMITTERS[name]) {
|
||||
@ -35,10 +39,14 @@ const getNativeEmitter = (moduleName: FirebaseModuleName, module: ModuleBase): N
|
||||
* @param eventName
|
||||
* @private
|
||||
*/
|
||||
const subscribeToNativeModuleEvents = (moduleName: FirebaseModuleName, module: ModuleBase, eventName: string): void => {
|
||||
const subscribeToNativeModuleEvents = (
|
||||
moduleName: FirebaseModuleName,
|
||||
module: ModuleBase,
|
||||
eventName: string
|
||||
): void => {
|
||||
if (!NATIVE_SUBSCRIPTIONS[eventName]) {
|
||||
const nativeEmitter = getNativeEmitter(moduleName, module);
|
||||
nativeEmitter.addListener(eventName, (event) => {
|
||||
nativeEmitter.addListener(eventName, event => {
|
||||
if (event.appName) {
|
||||
// native event has an appName property - auto prefix and internally emit
|
||||
SharedEventEmitter.emit(`${event.appName}-${eventName}`, event);
|
||||
@ -52,7 +60,10 @@ const subscribeToNativeModuleEvents = (moduleName: FirebaseModuleName, module: M
|
||||
}
|
||||
};
|
||||
|
||||
export const initialiseNativeModuleEventEmitter = (module: ModuleBase, config: FirebaseModuleConfig): 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++) {
|
||||
|
@ -4,8 +4,10 @@ import { Platform } from 'react-native';
|
||||
// todo cleanup unused utilities from legacy code
|
||||
|
||||
// modeled after base64 web-safe chars, but ordered by ASCII
|
||||
const PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
|
||||
const AUTO_ID_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
const PUSH_CHARS =
|
||||
'-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
|
||||
const AUTO_ID_CHARS =
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
const { hasOwnProperty } = Object;
|
||||
|
||||
// const DEFAULT_CHUNK_SIZE = 50;
|
||||
@ -18,7 +20,11 @@ const { hasOwnProperty } = Object;
|
||||
* @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;
|
||||
@ -42,7 +48,11 @@ export function deepGet(object: Object, path: string, joiner?: string = '/'): an
|
||||
* @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;
|
||||
@ -64,18 +74,23 @@ export function deepExists(object: Object, path: string, joiner?: string = '/'):
|
||||
* @param obj2
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function areObjectKeysContainedInOther(obj1 : Object, obj2: Object): boolean {
|
||||
export function areObjectKeysContainedInOther(
|
||||
obj1: Object,
|
||||
obj2: Object
|
||||
): boolean {
|
||||
if (!isObject(obj1) || !isObject(obj2)) {
|
||||
return false;
|
||||
}
|
||||
const keys1 = Object.keys(obj1);
|
||||
const keys2 = Object.keys(obj2);
|
||||
if (isArrayContainedInOther(keys1, keys2)) {
|
||||
return keys1.filter((key) => {
|
||||
return isObject(obj1[key]);
|
||||
}).reduce((acc, cur) => {
|
||||
return acc && areObjectKeysContainedInOther(obj1[cur], obj2[cur]);
|
||||
}, true);
|
||||
return keys1
|
||||
.filter(key => isObject(obj1[key]))
|
||||
.reduce(
|
||||
(acc, cur) =>
|
||||
acc && areObjectKeysContainedInOther(obj1[cur], obj2[cur]),
|
||||
true
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -86,13 +101,14 @@ 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;
|
||||
}
|
||||
return arr1.reduce((acc, cur) => {
|
||||
return acc && arr2.includes(cur);
|
||||
}, true);
|
||||
return arr1.reduce((acc, cur) => acc && arr2.includes(cur), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,7 +117,9 @@ export function isArrayContainedInOther(arr1: Array<*>, arr2: Array<*>): boolean
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isObject(item: mixed): boolean %checks {
|
||||
return item ? (typeof item === 'object' && !Array.isArray(item) && item !== null) : false;
|
||||
return item
|
||||
? typeof item === 'object' && !Array.isArray(item) && item !== null
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,7 +144,6 @@ export function isString(value: mixed): boolean %checks {
|
||||
export const isIOS = Platform.OS === 'ios';
|
||||
export const isAndroid = Platform.OS === 'android';
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string
|
||||
@ -153,16 +170,16 @@ export function tryJSONStringify(data: mixed): string | null {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// noinspection Eslint
|
||||
export const windowOrGlobal = (typeof self === 'object' && self.self === self && self) || (typeof global === 'object' && global.global === global && global) || this;
|
||||
export const windowOrGlobal =
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
(typeof self === 'object' && self.self === self && self) ||
|
||||
(typeof global === 'object' && global.global === global && global) ||
|
||||
this;
|
||||
|
||||
/**
|
||||
* No operation func
|
||||
*/
|
||||
export function noop(): void {
|
||||
}
|
||||
|
||||
export function noop(): void {}
|
||||
|
||||
// /**
|
||||
// * Delays chunks based on sizes per event loop.
|
||||
@ -286,7 +303,7 @@ const lastRandChars = [];
|
||||
export function generatePushID(serverTimeOffset?: number = 0): string {
|
||||
const timeStampChars = new Array(8);
|
||||
let now = new Date().getTime() + serverTimeOffset;
|
||||
const duplicateTime = (now === lastPushTime);
|
||||
const duplicateTime = now === lastPushTime;
|
||||
|
||||
lastPushTime = now;
|
||||
|
||||
@ -295,7 +312,8 @@ export function generatePushID(serverTimeOffset?: number = 0): string {
|
||||
now = Math.floor(now / 64);
|
||||
}
|
||||
|
||||
if (now !== 0) throw new Error('We should have converted the entire timestamp.');
|
||||
if (now !== 0)
|
||||
throw new Error('We should have converted the entire timestamp.');
|
||||
|
||||
let id = timeStampChars.join('');
|
||||
|
||||
@ -330,7 +348,11 @@ export function generatePushID(serverTimeOffset?: number = 0): string {
|
||||
* @param additionalProps
|
||||
* @returns {Error}
|
||||
*/
|
||||
export function nativeToJSError(code: string, message: string, additionalProps?: Object = {}) {
|
||||
export function nativeToJSError(
|
||||
code: string,
|
||||
message: string,
|
||||
additionalProps?: Object = {}
|
||||
) {
|
||||
const error: Object = new Error(message);
|
||||
error.code = code;
|
||||
Object.assign(error, additionalProps);
|
||||
@ -362,7 +384,6 @@ export function objectToUniqueId(object: Object): string {
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the existing promise if no callback provided or
|
||||
* exec the promise and callback if optionalCallback is valid.
|
||||
@ -371,23 +392,28 @@ export function objectToUniqueId(object: Object): string {
|
||||
* @param optionalCallback
|
||||
* @return {Promise}
|
||||
*/
|
||||
export function promiseOrCallback(promise: Promise<*>, optionalCallback?: Function): Promise<*> {
|
||||
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 && optionalCallback.length === 1) {
|
||||
optionalCallback(null);
|
||||
} else if (optionalCallback) {
|
||||
optionalCallback(null, result);
|
||||
}
|
||||
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 && optionalCallback.length === 1) {
|
||||
optionalCallback(null);
|
||||
} else if (optionalCallback) {
|
||||
optionalCallback(null, result);
|
||||
}
|
||||
|
||||
return Promise.resolve(result);
|
||||
}).catch((error) => {
|
||||
if (optionalCallback) optionalCallback(error);
|
||||
return Promise.reject(error);
|
||||
});
|
||||
return Promise.resolve(result);
|
||||
})
|
||||
.catch(error => {
|
||||
if (optionalCallback) optionalCallback(error);
|
||||
return Promise.reject(error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -398,7 +424,9 @@ export function firestoreAutoId(): string {
|
||||
let autoId = '';
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
autoId += AUTO_ID_CHARS.charAt(Math.floor(Math.random() * AUTO_ID_CHARS.length));
|
||||
autoId += AUTO_ID_CHARS.charAt(
|
||||
Math.floor(Math.random() * AUTO_ID_CHARS.length)
|
||||
);
|
||||
}
|
||||
return autoId;
|
||||
}
|
||||
|
@ -29,17 +29,20 @@ const PLAY_SERVICES_CODES = {
|
||||
// $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.',
|
||||
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.',
|
||||
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.',
|
||||
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: {
|
||||
@ -49,7 +52,8 @@ const PLAY_SERVICES_CODES = {
|
||||
// $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.',
|
||||
message:
|
||||
"Google Play service doesn't have one or more required permissions.",
|
||||
},
|
||||
};
|
||||
|
||||
@ -66,27 +70,33 @@ export default {
|
||||
},
|
||||
|
||||
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.',
|
||||
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.",
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
get ERROR_MISSING_CORE() {
|
||||
if (Platform.OS === 'ios') {
|
||||
return 'RNFirebase core module was not found natively on iOS, ensure you have ' +
|
||||
return (
|
||||
'RNFirebase core module was not found natively on iOS, ensure you have ' +
|
||||
'correctly included the RNFirebase pod in your projects `Podfile` and have run `pod install`.' +
|
||||
'\r\n\r\n See http://invertase.link/ios for the ios setup guide.';
|
||||
'\r\n\r\n See http://invertase.link/ios for the ios setup guide.'
|
||||
);
|
||||
}
|
||||
|
||||
return 'RNFirebase core module was not found natively on Android, ensure you have ' +
|
||||
return (
|
||||
'RNFirebase core module was not found natively on Android, ensure you have ' +
|
||||
'correctly added the RNFirebase and Firebase gradle dependencies to your `android/app/build.gradle` file.' +
|
||||
'\r\n\r\n See http://invertase.link/android for the android setup guide.';
|
||||
'\r\n\r\n See http://invertase.link/android for the android setup guide.'
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
ERROR_INIT_OBJECT: 'Firebase.initializeApp(options <-- requires a valid configuration object.',
|
||||
ERROR_INIT_STRING_NAME: 'Firebase.initializeApp(options, name <-- requires a valid string value.',
|
||||
ERROR_INIT_OBJECT:
|
||||
'Firebase.initializeApp(options <-- requires a valid configuration object.',
|
||||
ERROR_INIT_STRING_NAME:
|
||||
'Firebase.initializeApp(options, name <-- requires a valid string value.',
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
@ -131,20 +141,28 @@ export default {
|
||||
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}.` +
|
||||
return (
|
||||
`You attempted to use a firebase module that's not installed natively on your iOS project by calling ${snippet}.` +
|
||||
'\r\n\r\nEnsure you have the required Firebase iOS SDK pod for this module included in your Podfile, in this instance ' +
|
||||
`confirm you've added "pod '${NAMESPACE_PODS[namespace]}'" to your Podfile` +
|
||||
'\r\n\r\nSee http://invertase.link/ios for full setup instructions.';
|
||||
`confirm you've added "pod '${
|
||||
NAMESPACE_PODS[namespace]
|
||||
}'" to your Podfile` +
|
||||
'\r\n\r\nSee http://invertase.link/ios for full setup instructions.'
|
||||
);
|
||||
}
|
||||
|
||||
const fbSDKDep = `'com.google.firebase:firebase-${GRADLE_DEPS[namespace] || namespace}'`;
|
||||
const fbSDKDep = `'com.google.firebase:firebase-${GRADLE_DEPS[
|
||||
namespace
|
||||
] || namespace}'`;
|
||||
const rnFirebasePackage = `'io.invertase.firebase.${namespace}.${nativeModule}Package'`;
|
||||
const newInstance = `'new ${nativeModule}Package()'`;
|
||||
return `You attempted to use a firebase module that's not installed on your Android project by calling ${snippet}.` +
|
||||
return (
|
||||
`You attempted to use a firebase module that's not installed on your Android project by calling ${snippet}.` +
|
||||
`\r\n\r\nEnsure you have:\r\n\r\n1) Installed the required Firebase Android SDK dependency ${fbSDKDep} in your 'android/app/build.gradle' ` +
|
||||
`file.\r\n\r\n2) Imported the ${rnFirebasePackage} module in your 'MainApplication.java' file.\r\n\r\n3) Added the ` +
|
||||
`${newInstance} line inside of the RN 'getPackages()' method list.` +
|
||||
'\r\n\r\nSee http://invertase.link/android for full setup instructions.';
|
||||
'\r\n\r\nSee http://invertase.link/android for full setup instructions.'
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -191,29 +209,30 @@ export default {
|
||||
return `firebase.${namespace}().${method}() is unsupported by the native Firebase SDKs.`;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
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.';
|
||||
let start =
|
||||
'Google Play Services is required to run firebase services on android but a valid installation was not found on this device.';
|
||||
|
||||
if (statusCode === 2) {
|
||||
start = 'Google Play Services is out of date and may cause some firebase services like authentication to hang when used. It is recommended that you update it.';
|
||||
start =
|
||||
'Google Play Services is out of date and may cause some firebase services like authentication to hang when used. It is recommended that you update it.';
|
||||
}
|
||||
|
||||
// eslint-disable-next-line prefer-template
|
||||
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})`
|
||||
) +
|
||||
'\r\n-------------------------' +
|
||||
'\r\n\r\n' +
|
||||
'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';
|
||||
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})`
|
||||
}\r\n-------------------------` +
|
||||
`\r\n\r\n` +
|
||||
`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`
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -5,7 +5,7 @@ import { windowOrGlobal } from './';
|
||||
|
||||
import type ModuleBase from './ModuleBase';
|
||||
|
||||
((base) => {
|
||||
(base => {
|
||||
window = base || window;
|
||||
// $FlowFixMe: Why are we using localStorage at all?
|
||||
if (!window.localStorage) window.localStorage = {};
|
||||
@ -15,7 +15,8 @@ import type ModuleBase from './ModuleBase';
|
||||
|
||||
const NATIVE_LOGGERS: { [string]: Object } = {};
|
||||
|
||||
const getModuleKey = (module: ModuleBase): string => `${module.app.name}:${module.namespace}`;
|
||||
const getModuleKey = (module: ModuleBase): string =>
|
||||
`${module.app.name}:${module.namespace}`;
|
||||
|
||||
export const getLogger = (module: ModuleBase) => {
|
||||
const key = getModuleKey(module);
|
||||
@ -25,12 +26,14 @@ export const getLogger = (module: ModuleBase) => {
|
||||
export const initialiseLogger = (module: ModuleBase, logNamespace: string) => {
|
||||
const key = getModuleKey(module);
|
||||
if (!NATIVE_LOGGERS[key]) {
|
||||
// eslint-disable-next-line global-require
|
||||
NATIVE_LOGGERS[key] = require('bows')(`🔥 ${logNamespace.toUpperCase()}`);
|
||||
}
|
||||
};
|
||||
|
||||
export default class Log {
|
||||
static createLogger(namespace: string) {
|
||||
// eslint-disable-next-line global-require
|
||||
return require('bows')(namespace);
|
||||
}
|
||||
|
||||
|
@ -21,28 +21,32 @@ const nativeWithApp = (appName: string, NativeModule: Object): Object => {
|
||||
|
||||
for (let i = 0, len = methods.length; i < len; i++) {
|
||||
const method = methods[i];
|
||||
native[method] = (...args) => {
|
||||
return NativeModule[method](...[appName, ...args]);
|
||||
};
|
||||
native[method] = (...args) => NativeModule[method](...[appName, ...args]);
|
||||
}
|
||||
|
||||
return native;
|
||||
};
|
||||
|
||||
const getModuleKey = (module: ModuleBase): string => `${module.app.name}:${module.namespace}`;
|
||||
const getModuleKey = (module: ModuleBase): string =>
|
||||
`${module.app.name}:${module.namespace}`;
|
||||
|
||||
export const getNativeModule = (module: ModuleBase): Object => {
|
||||
const key = getModuleKey(module);
|
||||
return NATIVE_MODULES[key];
|
||||
};
|
||||
|
||||
export const initialiseNativeModule = (module: ModuleBase, config: FirebaseModuleConfig): Object => {
|
||||
export const initialiseNativeModule = (
|
||||
module: ModuleBase,
|
||||
config: FirebaseModuleConfig
|
||||
): Object => {
|
||||
const { moduleName, multiApp, namespace } = config;
|
||||
const nativeModule = NativeModules[moduleName];
|
||||
const key = getModuleKey(module);
|
||||
|
||||
if (!nativeModule && namespace !== 'utils') {
|
||||
throw new Error(INTERNALS.STRINGS.ERROR_MISSING_MODULE(namespace, moduleName));
|
||||
throw new Error(
|
||||
INTERNALS.STRINGS.ERROR_MISSING_MODULE(namespace, moduleName)
|
||||
);
|
||||
}
|
||||
|
||||
// used by the modules that extend ModuleBase
|
||||
|
626
package-lock.json
generated
626
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-firebase",
|
||||
"version": "3.2.0",
|
||||
"version": "3.2.2",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -102,6 +102,12 @@
|
||||
"integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=",
|
||||
"dev": true
|
||||
},
|
||||
"any-observable": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.2.0.tgz",
|
||||
"integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=",
|
||||
"dev": true
|
||||
},
|
||||
"anymatch": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
|
||||
@ -112,6 +118,12 @@
|
||||
"normalize-path": "2.1.1"
|
||||
}
|
||||
},
|
||||
"app-root-path": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.0.1.tgz",
|
||||
"integrity": "sha1-zWLc+OT9WkF+/GZNLlsQZTxlG0Y=",
|
||||
"dev": true
|
||||
},
|
||||
"are-we-there-yet": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
|
||||
@ -1423,6 +1435,12 @@
|
||||
"readdirp": "2.1.0"
|
||||
}
|
||||
},
|
||||
"ci-info": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.2.tgz",
|
||||
"integrity": "sha512-uTGIPNx/nSpBdsF6xnseRXLLtfr9VLqkz8ZqHXr3Y7b6SftyRxBGjwMtJj1OhNbmlc1wZzLNAlAcvyIiE8a6ZA==",
|
||||
"dev": true
|
||||
},
|
||||
"circular-json": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
|
||||
@ -1438,6 +1456,30 @@
|
||||
"restore-cursor": "1.0.1"
|
||||
}
|
||||
},
|
||||
"cli-spinners": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz",
|
||||
"integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=",
|
||||
"dev": true
|
||||
},
|
||||
"cli-truncate": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz",
|
||||
"integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"slice-ansi": "0.0.4",
|
||||
"string-width": "1.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"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
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli-width": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
|
||||
@ -1723,6 +1765,30 @@
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
||||
"dev": true
|
||||
},
|
||||
"cosmiconfig": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz",
|
||||
"integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-directory": "0.3.1",
|
||||
"js-yaml": "3.10.0",
|
||||
"parse-json": "4.0.0",
|
||||
"require-from-string": "2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"parse-json": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
|
||||
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"error-ex": "1.3.1",
|
||||
"json-parse-better-errors": "1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"crc": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz",
|
||||
@ -1827,6 +1893,12 @@
|
||||
"assert-plus": "1.0.0"
|
||||
}
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "1.29.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz",
|
||||
"integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==",
|
||||
"dev": true
|
||||
},
|
||||
"dateformat": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz",
|
||||
@ -1848,6 +1920,12 @@
|
||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
|
||||
"dev": true
|
||||
},
|
||||
"dedent": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
|
||||
"integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
|
||||
"dev": true
|
||||
},
|
||||
"deep-is": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
|
||||
@ -2034,6 +2112,12 @@
|
||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
|
||||
"dev": true
|
||||
},
|
||||
"elegant-spinner": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz",
|
||||
"integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=",
|
||||
"dev": true
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.5.1.tgz",
|
||||
@ -2294,6 +2378,15 @@
|
||||
"eslint-restricted-globals": "0.1.1"
|
||||
}
|
||||
},
|
||||
"eslint-config-prettier": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz",
|
||||
"integrity": "sha512-ag8YEyBXsm3nmOv1Hz991VtNNDMRa+MNy8cY47Pl4bw6iuzqKbJajXdqUpiw13STdLLrznxgm1hj9NhxeOYq0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"get-stdin": "5.0.1"
|
||||
}
|
||||
},
|
||||
"eslint-import-resolver-node": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz",
|
||||
@ -2368,6 +2461,24 @@
|
||||
"jsx-ast-utils": "1.4.1"
|
||||
}
|
||||
},
|
||||
"eslint-plugin-prettier": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.5.0.tgz",
|
||||
"integrity": "sha512-L06bewYpt2Wb8Uk7os8f/0cL5DjddL38t1M/nOpjw5MqVFBn1RIIBBE6tfr37lHUH7AvAubZsvu/bDmNl4RBKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-diff": "1.1.2",
|
||||
"jest-docblock": "21.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"jest-docblock": {
|
||||
"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
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-plugin-react": {
|
||||
"version": "7.4.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.4.0.tgz",
|
||||
@ -2606,6 +2717,12 @@
|
||||
"integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=",
|
||||
"dev": true
|
||||
},
|
||||
"fast-diff": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
|
||||
"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==",
|
||||
"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",
|
||||
@ -2747,6 +2864,12 @@
|
||||
"parents": "1.0.1"
|
||||
}
|
||||
},
|
||||
"find-parent-dir": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz",
|
||||
"integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=",
|
||||
"dev": true
|
||||
},
|
||||
"find-up": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
|
||||
@ -3910,6 +4033,18 @@
|
||||
"integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
|
||||
"dev": true
|
||||
},
|
||||
"get-own-enumerable-property-symbols": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz",
|
||||
"integrity": "sha512-TtY/sbOemiMKPRUDDanGCSgBYe7Mf0vbRsWnBZ+9yghpZ1MvcpSpuZFjHdEeY/LZjZy0vdLjS77L6HosisFiug==",
|
||||
"dev": true
|
||||
},
|
||||
"get-stdin": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz",
|
||||
"integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=",
|
||||
"dev": true
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
@ -4181,6 +4316,25 @@
|
||||
"sshpk": "1.13.1"
|
||||
}
|
||||
},
|
||||
"husky": {
|
||||
"version": "0.14.3",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-0.14.3.tgz",
|
||||
"integrity": "sha512-e21wivqHpstpoiWA/Yi8eFti8E+sQDSS53cpJsPptPs295QTOQR0ZwnHo2TXy1XOpZFD9rPOd3NpmqTK6uMLJA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-ci": "1.1.0",
|
||||
"normalize-path": "1.0.0",
|
||||
"strip-indent": "2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"normalize-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz",
|
||||
"integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.19",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
|
||||
@ -4204,6 +4358,15 @@
|
||||
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
|
||||
"dev": true
|
||||
},
|
||||
"indent-string": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
|
||||
"integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"repeating": "2.0.1"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
@ -4430,12 +4593,27 @@
|
||||
"integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
|
||||
"dev": true
|
||||
},
|
||||
"is-ci": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz",
|
||||
"integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ci-info": "1.1.2"
|
||||
}
|
||||
},
|
||||
"is-date-object": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
|
||||
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
|
||||
"dev": true
|
||||
},
|
||||
"is-directory": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
|
||||
"integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
|
||||
"dev": true
|
||||
},
|
||||
"is-dotfile": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
|
||||
@ -4499,6 +4677,29 @@
|
||||
"kind-of": "3.2.2"
|
||||
}
|
||||
},
|
||||
"is-obj": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
||||
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
|
||||
"dev": true
|
||||
},
|
||||
"is-observable": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-observable/-/is-observable-0.2.0.tgz",
|
||||
"integrity": "sha1-s2ExHYPG5dcmyr9eJQsCNxBvWuI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"symbol-observable": "0.2.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"symbol-observable": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-0.2.4.tgz",
|
||||
"integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"is-path-cwd": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
|
||||
@ -4549,6 +4750,12 @@
|
||||
"has": "1.0.1"
|
||||
}
|
||||
},
|
||||
"is-regexp": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
|
||||
"integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=",
|
||||
"dev": true
|
||||
},
|
||||
"is-resolvable": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz",
|
||||
@ -4638,6 +4845,12 @@
|
||||
"detect-newline": "2.1.0"
|
||||
}
|
||||
},
|
||||
"jest-get-type": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-21.2.0.tgz",
|
||||
"integrity": "sha512-y2fFw3C+D0yjNSDp7ab1kcd6NUYfy3waPTlD8yWkAtiocJdBRQqNoRqVfMNxgj+IjT0V5cBIHJO0z9vuSSZ43Q==",
|
||||
"dev": true
|
||||
},
|
||||
"jest-haste-map": {
|
||||
"version": "22.0.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-22.0.3.tgz",
|
||||
@ -4652,6 +4865,65 @@
|
||||
"sane": "2.2.0"
|
||||
}
|
||||
},
|
||||
"jest-validate": {
|
||||
"version": "21.2.1",
|
||||
"resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-21.2.1.tgz",
|
||||
"integrity": "sha512-k4HLI1rZQjlU+EC682RlQ6oZvLrE5SCh3brseQc24vbZTxzT/k/3urar5QMCVgjadmSO7lECeGdc6YxnM3yEGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "2.3.0",
|
||||
"jest-get-type": "21.2.0",
|
||||
"leven": "2.1.0",
|
||||
"pretty-format": "21.2.1"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"pretty-format": {
|
||||
"version": "21.2.1",
|
||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-21.2.1.tgz",
|
||||
"integrity": "sha512-ZdWPGYAnYfcVP8yKA3zFjCn8s4/17TeYH28MXuC8vTp0o21eXjbFGcOAXZEaDaOFJjc3h2qa7HQNHNshhvoh2A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "3.0.0",
|
||||
"ansi-styles": "3.2.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"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"jest-worker": {
|
||||
"version": "22.0.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-22.0.3.tgz",
|
||||
@ -4694,6 +4966,12 @@
|
||||
"integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
|
||||
"dev": true
|
||||
},
|
||||
"json-parse-better-errors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz",
|
||||
"integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||
@ -4808,6 +5086,12 @@
|
||||
"integrity": "sha1-0wpzxrggHY99jnlWupYWCHpo4O4=",
|
||||
"dev": true
|
||||
},
|
||||
"leven": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
|
||||
"integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=",
|
||||
"dev": true
|
||||
},
|
||||
"levn": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
|
||||
@ -4818,6 +5102,197 @@
|
||||
"type-check": "0.3.2"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-6.0.1.tgz",
|
||||
"integrity": "sha512-GZnFshBzIpJMHO5aSqXGVJh5G1agKTrKGQOs6cTKA6a62PvZ7l2RawbpOrFdzjzkezxm7+LpKeleNt83gd9yRA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"app-root-path": "2.0.1",
|
||||
"chalk": "2.3.0",
|
||||
"commander": "2.11.0",
|
||||
"cosmiconfig": "4.0.0",
|
||||
"debug": "3.1.0",
|
||||
"dedent": "0.7.0",
|
||||
"execa": "0.8.0",
|
||||
"find-parent-dir": "0.3.0",
|
||||
"is-glob": "4.0.0",
|
||||
"jest-validate": "21.2.1",
|
||||
"listr": "0.13.0",
|
||||
"lodash": "4.17.4",
|
||||
"log-symbols": "2.2.0",
|
||||
"minimatch": "3.0.4",
|
||||
"npm-which": "3.0.1",
|
||||
"p-map": "1.2.0",
|
||||
"path-is-inside": "1.0.2",
|
||||
"pify": "3.0.0",
|
||||
"staged-git-files": "0.0.4",
|
||||
"stringify-object": "3.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"execa": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz",
|
||||
"integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
||||
"dev": true
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
|
||||
"integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-extglob": "2.1.1"
|
||||
}
|
||||
},
|
||||
"pify": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
|
||||
"dev": true
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"listr": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/listr/-/listr-0.13.0.tgz",
|
||||
"integrity": "sha1-ILsLowuuZg7oTMBQPfS+PVYjiH0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "1.1.3",
|
||||
"cli-truncate": "0.2.1",
|
||||
"figures": "1.7.0",
|
||||
"indent-string": "2.1.0",
|
||||
"is-observable": "0.2.0",
|
||||
"is-promise": "2.1.0",
|
||||
"is-stream": "1.1.0",
|
||||
"listr-silent-renderer": "1.1.1",
|
||||
"listr-update-renderer": "0.4.0",
|
||||
"listr-verbose-renderer": "0.4.1",
|
||||
"log-symbols": "1.0.2",
|
||||
"log-update": "1.0.2",
|
||||
"ora": "0.2.3",
|
||||
"p-map": "1.2.0",
|
||||
"rxjs": "5.5.6",
|
||||
"stream-to-observable": "0.2.0",
|
||||
"strip-ansi": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"log-symbols": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
|
||||
"integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "1.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"listr-silent-renderer": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz",
|
||||
"integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=",
|
||||
"dev": true
|
||||
},
|
||||
"listr-update-renderer": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz",
|
||||
"integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "1.1.3",
|
||||
"cli-truncate": "0.2.1",
|
||||
"elegant-spinner": "1.0.1",
|
||||
"figures": "1.7.0",
|
||||
"indent-string": "3.2.0",
|
||||
"log-symbols": "1.0.2",
|
||||
"log-update": "1.0.2",
|
||||
"strip-ansi": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"indent-string": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
|
||||
"integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
|
||||
"dev": true
|
||||
},
|
||||
"log-symbols": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
|
||||
"integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "1.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"listr-verbose-renderer": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz",
|
||||
"integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "1.1.3",
|
||||
"cli-cursor": "1.0.2",
|
||||
"date-fns": "1.29.0",
|
||||
"figures": "1.7.0"
|
||||
}
|
||||
},
|
||||
"load-json-file": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
||||
@ -5074,6 +5549,56 @@
|
||||
"lodash.escape": "3.2.0"
|
||||
}
|
||||
},
|
||||
"log-symbols": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
|
||||
"integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "2.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"log-update": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz",
|
||||
"integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-escapes": "1.4.0",
|
||||
"cli-cursor": "1.0.2"
|
||||
}
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
|
||||
@ -5542,6 +6067,15 @@
|
||||
"remove-trailing-separator": "1.1.0"
|
||||
}
|
||||
},
|
||||
"npm-path": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz",
|
||||
"integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"which": "1.3.0"
|
||||
}
|
||||
},
|
||||
"npm-run-path": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
|
||||
@ -5551,6 +6085,17 @@
|
||||
"path-key": "2.0.1"
|
||||
}
|
||||
},
|
||||
"npm-which": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz",
|
||||
"integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "2.11.0",
|
||||
"npm-path": "2.0.4",
|
||||
"which": "1.3.0"
|
||||
}
|
||||
},
|
||||
"npmlog": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz",
|
||||
@ -5879,6 +6424,18 @@
|
||||
"integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=",
|
||||
"dev": true
|
||||
},
|
||||
"ora": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz",
|
||||
"integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "1.1.3",
|
||||
"cli-cursor": "1.0.2",
|
||||
"cli-spinners": "0.1.2",
|
||||
"object-assign": "4.1.1"
|
||||
}
|
||||
},
|
||||
"os-homedir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
||||
@ -5947,6 +6504,12 @@
|
||||
"p-limit": "1.1.0"
|
||||
}
|
||||
},
|
||||
"p-map": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
|
||||
"integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
|
||||
"dev": true
|
||||
},
|
||||
"parents": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz",
|
||||
@ -6120,6 +6683,12 @@
|
||||
"integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
|
||||
"dev": true
|
||||
},
|
||||
"prettier": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.10.2.tgz",
|
||||
"integrity": "sha512-TcdNoQIWFoHblurqqU6d1ysopjq7UX0oRcT/hJ8qvBAELiYWn+Ugf0AXdnzISEJ7vuhNnQ98N8jR8Sh53x4IZg==",
|
||||
"dev": true
|
||||
},
|
||||
"pretty-format": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-4.3.1.tgz",
|
||||
@ -6646,6 +7215,12 @@
|
||||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
|
||||
"dev": true
|
||||
},
|
||||
"require-from-string": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.1.tgz",
|
||||
"integrity": "sha1-xUUjPp19pmFunVmt+zn8n1iGdv8=",
|
||||
"dev": true
|
||||
},
|
||||
"require-main-filename": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
|
||||
@ -6749,6 +7324,23 @@
|
||||
"rx-lite": "3.1.2"
|
||||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "5.5.6",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz",
|
||||
"integrity": "sha512-v4Q5HDC0FHAQ7zcBX7T2IL6O5ltl1a2GX4ENjPXg6SjDY69Cmx9v4113C99a4wGF16ClPv5Z8mghuYorVkg/kg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"symbol-observable": "1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"symbol-observable": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
|
||||
"integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
||||
@ -7129,6 +7721,12 @@
|
||||
"integrity": "sha1-ATl5IuX2Ls8whFUiyVxP4dJefU4=",
|
||||
"dev": true
|
||||
},
|
||||
"staged-git-files": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-0.0.4.tgz",
|
||||
"integrity": "sha1-15fhtVHKemOd7AI33G60u5vhfTU=",
|
||||
"dev": true
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
|
||||
@ -7176,6 +7774,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"stream-to-observable": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.2.0.tgz",
|
||||
"integrity": "sha1-WdbqOT2HwsDdrBCqDVYbxrpvDhA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"any-observable": "0.2.0"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
@ -7196,6 +7803,17 @@
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"stringify-object": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.2.1.tgz",
|
||||
"integrity": "sha512-jPcQYw/52HUPP8uOE4kkjxl5bB9LfHkKCTptIk3qw7ozP5XMIMlHMLjt00GGSwW6DJAf/njY5EU6Vpwl4LlBKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"get-own-enumerable-property-symbols": "2.0.1",
|
||||
"is-obj": "1.0.1",
|
||||
"is-regexp": "1.0.0"
|
||||
}
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
|
||||
@ -7222,6 +7840,12 @@
|
||||
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
|
||||
"dev": true
|
||||
},
|
||||
"strip-indent": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
|
||||
"integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
|
||||
"dev": true
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
|
25
package.json
25
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-firebase",
|
||||
"version": "3.2.0",
|
||||
"version": "3.2.2",
|
||||
"author": "Invertase <contact@invertase.io> (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",
|
||||
@ -11,7 +11,9 @@
|
||||
"build-lib": "BABEL_ENV=publish babel lib -d dist --ignore __tests__ --copy-files",
|
||||
"clean": "rimraf dist/",
|
||||
"flow": "flow",
|
||||
"lint": "eslint ./src",
|
||||
"format": "eslint --fix ./lib ./tests/src ./tests/lib",
|
||||
"lint": "eslint ./lib ./tests/src ./tests/lib",
|
||||
"precommit": "lint-staged",
|
||||
"prepublish": "npm run clean && npm run build",
|
||||
"postinstall": "postinstall-build dist && opencollective postinstall || exit 0",
|
||||
"test-cli": "node ./bin/test.js",
|
||||
@ -82,13 +84,18 @@
|
||||
"enzyme": "^2.4.1",
|
||||
"eslint": "^4.11.0",
|
||||
"eslint-config-airbnb": "^16.1.0",
|
||||
"eslint-config-prettier": "^2.9.0",
|
||||
"eslint-plugin-flowtype": "^2.39.1",
|
||||
"eslint-plugin-import": "^2.8.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.0.2",
|
||||
"eslint-plugin-prettier": "^2.5.0",
|
||||
"eslint-plugin-react": "^7.4.0",
|
||||
"flow-bin": "^0.61.0",
|
||||
"flow-copy-source": "^1.2.1",
|
||||
"genversion": "^2.0.1",
|
||||
"husky": "^0.14.3",
|
||||
"lint-staged": "^6.0.1",
|
||||
"prettier": "1.10.2",
|
||||
"react": "^16.2.0",
|
||||
"react-dom": "^16.2.0",
|
||||
"react-native": "^0.52.0",
|
||||
@ -116,5 +123,19 @@
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/react-native-firebase",
|
||||
"logo": "https://opencollective.com/opencollective/logo.txt"
|
||||
},
|
||||
"lint-staged": {
|
||||
"lib/**/*.js": [
|
||||
"eslint --fix",
|
||||
"git add"
|
||||
],
|
||||
"tests/src/**/*.js": [
|
||||
"eslint --fix",
|
||||
"git add"
|
||||
],
|
||||
"tests/lib/**/*.js": [
|
||||
"eslint --fix",
|
||||
"git add"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
4
prettier.config.js
Normal file
4
prettier.config.js
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
trailingComma: 'es5',
|
||||
singleQuote: true,
|
||||
};
|
@ -1,42 +1,39 @@
|
||||
{
|
||||
"extends": "airbnb",
|
||||
"extends": [
|
||||
"airbnb",
|
||||
"prettier",
|
||||
"prettier/flowtype",
|
||||
"prettier/react"
|
||||
],
|
||||
"parser": "babel-eslint",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
},
|
||||
"plugins": [
|
||||
"flowtype"
|
||||
"flowtype",
|
||||
"prettier"
|
||||
],
|
||||
"env": {
|
||||
"es6": true,
|
||||
"jasmine": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"no-plusplus": 0,
|
||||
"prettier/prettier": ["error", {
|
||||
"trailingComma": "es5",
|
||||
"singleQuote": true
|
||||
}],
|
||||
|
||||
"react/forbid-prop-types": "warn",
|
||||
"react/jsx-filename-extension": [
|
||||
"off", { "extensions": [".js", ".jsx"] }
|
||||
],
|
||||
|
||||
"class-methods-use-this": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-use-before-define": 0,
|
||||
"arrow-body-style": 0,
|
||||
"import/prefer-default-export": 0,
|
||||
"radix": 0,
|
||||
"new-cap": 0,
|
||||
"max-len": 0,
|
||||
"no-continue": 0,
|
||||
"no-console": 0,
|
||||
"global-require": 0,
|
||||
"import/extensions": 0,
|
||||
"import/no-unresolved": 0,
|
||||
"import/no-extraneous-dependencies": 0,
|
||||
"react/jsx-filename-extension": 0
|
||||
"no-plusplus": 0,
|
||||
"no-undef": 0,
|
||||
"no-underscore-dangle": "off",
|
||||
"no-use-before-define": 0
|
||||
},
|
||||
"globals": {
|
||||
"__DEV__": true,
|
||||
"window": true,
|
||||
"fetch": true,
|
||||
"window": true
|
||||
}
|
||||
}
|
||||
|
@ -2,4 +2,3 @@ import { AppRegistry } from 'react-native';
|
||||
import bootstrap from './src/main';
|
||||
|
||||
AppRegistry.registerComponent('ReactNativeFirebaseDemo', () => bootstrap);
|
||||
|
||||
|
@ -199,7 +199,6 @@ class TestDSL {
|
||||
this.it(description, _options, _testFunction);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines a new focused test. Focused tests are the only
|
||||
* ones that appear and are run when the test suite is executed.
|
||||
@ -240,12 +239,4 @@ class TestDSL {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a test DSL error to the console.
|
||||
* @param {String} error - Message to included in message logged to the console
|
||||
*/
|
||||
function testDSLError(error) {
|
||||
console.error(`ReactNativeFirebaseTests.TestDSLError: ${error}`);
|
||||
console.error('This test was ignored.');
|
||||
}
|
||||
export default TestDSL;
|
||||
|
@ -25,7 +25,6 @@ function cleanStack(stack, maxLines = 5) {
|
||||
return out.join('\r\n');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class that encapsulates synchronously running a suite's tests.
|
||||
*/
|
||||
@ -50,9 +49,13 @@ class TestRun {
|
||||
this.rootContextId = testDefinitions.rootTestContextId;
|
||||
|
||||
this.testContexts = tests.reduce((memo, test) => {
|
||||
const testContextId = test.testContextId;
|
||||
const { testContextId } = test;
|
||||
|
||||
this._recursivelyAddContextsTo(memo, testContextId, testDefinitions.testContexts);
|
||||
this._recursivelyAddContextsTo(
|
||||
memo,
|
||||
testContextId,
|
||||
testDefinitions.testContexts
|
||||
);
|
||||
|
||||
memo[testContextId].tests.unshift(test);
|
||||
|
||||
@ -101,7 +104,7 @@ class TestRun {
|
||||
target[id].childContextIds[childContextId] = true;
|
||||
}
|
||||
|
||||
const parentContextId = testContext.parentContextId;
|
||||
const { parentContextId } = testContext;
|
||||
|
||||
if (parentContextId) {
|
||||
this._recursivelyAddContextsTo(target, parentContextId, source, id);
|
||||
@ -123,7 +126,11 @@ class TestRun {
|
||||
const store = this.testSuite.reduxStore;
|
||||
|
||||
if (!store) {
|
||||
testRuntimeError(`Failed to run ${this.testSuite.name} tests as no Redux store has been provided`);
|
||||
testRuntimeError(
|
||||
`Failed to run ${
|
||||
this.testSuite.name
|
||||
} tests as no Redux store has been provided`
|
||||
);
|
||||
}
|
||||
|
||||
this._updateStatus(EVENTS.TEST_SUITE_STATUS, {
|
||||
@ -152,17 +159,19 @@ class TestRun {
|
||||
progress: 100,
|
||||
|
||||
time: Date.now() - this.runStartTime,
|
||||
message: `${errors.length} test${errors.length > 1 ? 's' : ''} has error(s).`,
|
||||
message: `${errors.length} test${
|
||||
errors.length > 1 ? 's' : ''
|
||||
} has error(s).`,
|
||||
});
|
||||
} else {
|
||||
this._updateStatus(EVENTS.TEST_SUITE_STATUS, ({
|
||||
this._updateStatus(EVENTS.TEST_SUITE_STATUS, {
|
||||
suiteId: this.testSuite.id,
|
||||
status: RunStatus.OK,
|
||||
progress: 100,
|
||||
|
||||
time: Date.now() - this.runStartTime,
|
||||
message: '',
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -179,19 +188,35 @@ class TestRun {
|
||||
* @returns {Promise.<void>} Resolves once all tests and their hooks have run
|
||||
* @private
|
||||
*/
|
||||
async _runTestsInContext(testContext, beforeEachHooks = [], afterEachHooks = []) {
|
||||
async _runTestsInContext(
|
||||
testContext,
|
||||
beforeEachHooks = [],
|
||||
afterEachHooks = []
|
||||
) {
|
||||
const beforeHookRan = await this._runContextHooks(testContext, 'before');
|
||||
|
||||
if (beforeHookRan) {
|
||||
beforeEachHooks.push(testContext.beforeEachHooks || []);
|
||||
afterEachHooks.unshift(testContext.afterEachHooks || []);
|
||||
|
||||
await this._runTests(testContext, testContext.tests, flatten(beforeEachHooks), flatten(afterEachHooks));
|
||||
await this._runTests(
|
||||
testContext,
|
||||
testContext.tests,
|
||||
flatten(beforeEachHooks),
|
||||
flatten(afterEachHooks)
|
||||
);
|
||||
|
||||
await Promise.each(Object.keys(testContext.childContextIds), (childContextId) => {
|
||||
const childContext = this.testContexts[childContextId];
|
||||
return this._runTestsInContext(childContext, beforeEachHooks, afterEachHooks);
|
||||
});
|
||||
await Promise.each(
|
||||
Object.keys(testContext.childContextIds),
|
||||
childContextId => {
|
||||
const childContext = this.testContexts[childContextId];
|
||||
return this._runTestsInContext(
|
||||
childContext,
|
||||
beforeEachHooks,
|
||||
afterEachHooks
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
beforeEachHooks.pop();
|
||||
afterEachHooks.shift();
|
||||
@ -215,21 +240,39 @@ class TestRun {
|
||||
}
|
||||
|
||||
_runHookChain(test, testStart, testContext, hookName, hooks) {
|
||||
return Promise.each(hooks, async (hook) => {
|
||||
const error = await this._safelyRunFunction(hook.callback, hook.timeout, `${hookName} hook`);
|
||||
return Promise.each(hooks, async hook => {
|
||||
const error = await this._safelyRunFunction(
|
||||
hook.callback,
|
||||
hook.timeout,
|
||||
`${hookName} hook`
|
||||
);
|
||||
|
||||
if (error) {
|
||||
const errorPrefix = `Error occurred in "${testContext.name}" ${hookName} Hook: `;
|
||||
const errorPrefix = `Error occurred in "${
|
||||
testContext.name
|
||||
}" ${hookName} Hook: `;
|
||||
|
||||
if (test) {
|
||||
this._reportTestError(test, error, Date.now() - testStart, errorPrefix);
|
||||
this._reportTestError(
|
||||
test,
|
||||
error,
|
||||
Date.now() - testStart,
|
||||
errorPrefix
|
||||
);
|
||||
} else {
|
||||
this._reportAllTestsAsFailed(testContext, error, testStart, errorPrefix);
|
||||
this._reportAllTestsAsFailed(
|
||||
testContext,
|
||||
error,
|
||||
testStart,
|
||||
errorPrefix
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error();
|
||||
}
|
||||
}).then(() => true).catch(() => false);
|
||||
})
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -241,12 +284,17 @@ class TestRun {
|
||||
* @private
|
||||
*/
|
||||
_reportAllTestsAsFailed(testContext, error, testStart, errorPrefix) {
|
||||
testContext.tests.forEach((test) => {
|
||||
testContext.tests.forEach(test => {
|
||||
this._reportTestError(test, error, Date.now() - testStart, errorPrefix);
|
||||
});
|
||||
|
||||
testContext.childContextIds.forEach((contextId) => {
|
||||
this._reportAllTestsAsFailed(this.testContext[contextId], error, testStart, errorPrefix);
|
||||
testContext.childContextIds.forEach(contextId => {
|
||||
this._reportAllTestsAsFailed(
|
||||
this.testContext[contextId],
|
||||
error,
|
||||
testStart,
|
||||
errorPrefix
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -262,7 +310,7 @@ class TestRun {
|
||||
* @private
|
||||
*/
|
||||
async _runTests(testContext, tests, beforeEachHooks, afterEachHooks) {
|
||||
return Promise.each(tests, async (test) => {
|
||||
return Promise.each(tests, async test => {
|
||||
this._updateStatus(EVENTS.TEST_STATUS, {
|
||||
testId: test.id,
|
||||
status: RunStatus.RUNNING,
|
||||
@ -272,16 +320,29 @@ class TestRun {
|
||||
|
||||
const testStart = Date.now();
|
||||
|
||||
const beforeEachRan = await this._runHookChain(test, testStart, testContext, 'beforeEach', beforeEachHooks);
|
||||
const beforeEachRan = await this._runHookChain(
|
||||
test,
|
||||
testStart,
|
||||
testContext,
|
||||
'beforeEach',
|
||||
beforeEachHooks
|
||||
);
|
||||
|
||||
if (beforeEachRan) {
|
||||
const error = await this._safelyRunFunction(test.func.bind(null, [test, this.testSuite.reduxStore.getState()]), test.timeout, 'Test');
|
||||
const error = await this._safelyRunFunction(
|
||||
test.func.bind(null, [test, this.testSuite.reduxStore.getState()]),
|
||||
test.timeout,
|
||||
'Test'
|
||||
);
|
||||
|
||||
// Update test status
|
||||
|
||||
if (error) {
|
||||
this._reportTestError(test, error, Date.now() - testStart);
|
||||
console.groupCollapsed(`%c ❌ Test Failed: ${test.description} (${this.testSuite.name})`, 'color: #f44336;');
|
||||
console.groupCollapsed(
|
||||
`%c ❌ Test Failed: ${test.description} (${this.testSuite.name})`,
|
||||
'color: #f44336;'
|
||||
);
|
||||
console.log(`Test Description: ${test.description}`);
|
||||
console.log(`Test Time Taken: ${Date.now() - testStart}`);
|
||||
console.log(`Suite Name: ${this.testSuite.name}`);
|
||||
@ -299,7 +360,10 @@ class TestRun {
|
||||
message: '',
|
||||
});
|
||||
|
||||
console.groupCollapsed(`%c ✅ Test Passed: ${test.description} (${this.testSuite.name})`, 'color: #4CAF50;');
|
||||
console.groupCollapsed(
|
||||
`%c ✅ Test Passed: ${test.description} (${this.testSuite.name})`,
|
||||
'color: #4CAF50;'
|
||||
);
|
||||
console.log(`Test Description: ${test.description}`);
|
||||
console.log(`Test Time Taken: ${Date.now() - testStart}`);
|
||||
console.log(`Suite Name: ${this.testSuite.name}`);
|
||||
@ -314,14 +378,20 @@ class TestRun {
|
||||
this._updateStatus(EVENTS.TEST_SUITE_STATUS, {
|
||||
suiteId: this.testSuite.id,
|
||||
status: RunStatus.RUNNING,
|
||||
progress: (this.completedTests / this.tests.length) * 100,
|
||||
progress: this.completedTests / this.tests.length * 100,
|
||||
time: Date.now() - this.runStartTime,
|
||||
message: '',
|
||||
});
|
||||
|
||||
await this._runHookChain(test, testStart, testContext, 'afterEach', afterEachHooks);
|
||||
await this._runHookChain(
|
||||
test,
|
||||
testStart,
|
||||
testContext,
|
||||
'afterEach',
|
||||
afterEachHooks
|
||||
);
|
||||
}
|
||||
}).catch((error) => {
|
||||
}).catch(error => {
|
||||
this._updateStatus(EVENTS.TEST_SUITE_STATUS, {
|
||||
suiteId: this.testSuite.id,
|
||||
status: RunStatus.ERR,
|
||||
@ -346,7 +416,9 @@ class TestRun {
|
||||
testId: test.id,
|
||||
status: RunStatus.ERR,
|
||||
time,
|
||||
message: `${errorPrefix}${error.message ? `${error.name}: ${error.message}` : error}`,
|
||||
message: `${errorPrefix}${
|
||||
error.message ? `${error.name}: ${error.message}` : error
|
||||
}`,
|
||||
stackTrace: cleanStack(error.stack),
|
||||
});
|
||||
}
|
||||
@ -368,9 +440,12 @@ class TestRun {
|
||||
}
|
||||
|
||||
// Asynchronous Error
|
||||
return capturePromiseErrors(syncResultOrPromise.result, timeOutDuration, description);
|
||||
return capturePromiseErrors(
|
||||
syncResultOrPromise.result,
|
||||
timeOutDuration,
|
||||
description
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -410,15 +485,10 @@ function capturePromiseErrors(target, timeoutDuration, description) {
|
||||
|
||||
try {
|
||||
returnValue = Promise.resolve(target)
|
||||
.then(() => {
|
||||
return null;
|
||||
}, (error) => {
|
||||
return Promise.resolve(error);
|
||||
})
|
||||
.catch((error) => {
|
||||
return Promise.resolve(error);
|
||||
})
|
||||
.timeout(timeoutDuration,
|
||||
.then(() => null, error => Promise.resolve(error))
|
||||
.catch(error => Promise.resolve(error))
|
||||
.timeout(
|
||||
timeoutDuration,
|
||||
`${description} took longer than ${timeoutDuration}ms. This can be extended with the timeout option.`
|
||||
);
|
||||
} catch (error) {
|
||||
@ -434,9 +504,7 @@ function capturePromiseErrors(target, timeoutDuration, description) {
|
||||
* @returns {*[]} One-dimensional array
|
||||
*/
|
||||
function flatten(list) {
|
||||
return list.reduce((memo, contextHooks) => {
|
||||
return memo.concat(contextHooks);
|
||||
}, []);
|
||||
return list.reduce((memo, contextHooks) => memo.concat(contextHooks), []);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -110,31 +110,41 @@ class TestSuite {
|
||||
* testSuite.run([1, 2]);
|
||||
*/
|
||||
async run(testIds = undefined) {
|
||||
const testsToRun = (() => {
|
||||
return (testIds || Object.keys(this.testDefinitions.tests)).reduce((memo, id) => {
|
||||
const test = this.testDefinitions.tests[id];
|
||||
const testsToRun = (() =>
|
||||
(testIds || Object.keys(this.testDefinitions.tests)).reduce(
|
||||
(memo, id) => {
|
||||
const test = this.testDefinitions.tests[id];
|
||||
|
||||
if (!test) {
|
||||
throw new RangeError(`ReactNativeFirebaseTests.TestRunError: Test with id ${id} not found in test suite ${this.name}`);
|
||||
}
|
||||
if (!test) {
|
||||
throw new RangeError(
|
||||
`ReactNativeFirebaseTests.TestRunError: Test with id ${id} not found in test suite ${
|
||||
this.name
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.testDefinitions.pendingTestIds[id]) {
|
||||
memo.push(test);
|
||||
}
|
||||
if (!this.testDefinitions.pendingTestIds[id]) {
|
||||
memo.push(test);
|
||||
}
|
||||
|
||||
return memo;
|
||||
}, []);
|
||||
})();
|
||||
return memo;
|
||||
},
|
||||
[]
|
||||
))();
|
||||
|
||||
const testRun = new TestRun(this, testsToRun.reverse(), this.testDefinitions);
|
||||
const testRun = new TestRun(
|
||||
this,
|
||||
testsToRun.reverse(),
|
||||
this.testDefinitions
|
||||
);
|
||||
|
||||
testRun.onChange('TEST_SUITE_STATUS', (values) => {
|
||||
testRun.onChange('TEST_SUITE_STATUS', values => {
|
||||
if (this.suiteChangHandler) {
|
||||
this.suiteChangHandler(values);
|
||||
}
|
||||
});
|
||||
|
||||
testRun.onChange('TEST_STATUS', (values) => {
|
||||
testRun.onChange('TEST_STATUS', values => {
|
||||
if (this.testChangHandler) {
|
||||
this.testChangHandler(values);
|
||||
}
|
||||
@ -142,7 +152,6 @@ class TestSuite {
|
||||
|
||||
await testRun.execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default TestSuite;
|
||||
|
@ -41,7 +41,7 @@ function assignContextId() {
|
||||
* @enum {String} ContextOperator
|
||||
*/
|
||||
const CONTEXT_OPERATORS = {
|
||||
/** Perform OR of test value with context chain values **/
|
||||
/** Perform OR of test value with context chain values * */
|
||||
OR: 'OR',
|
||||
};
|
||||
|
||||
@ -132,13 +132,18 @@ class TestSuiteDefinition {
|
||||
const hookAttribute = `${hookName}Hooks`;
|
||||
|
||||
if (callback && typeof callback === 'function') {
|
||||
this.currentTestContext[hookAttribute] = this.currentTestContext[hookAttribute] || [];
|
||||
this.currentTestContext[hookAttribute] =
|
||||
this.currentTestContext[hookAttribute] || [];
|
||||
this.currentTestContext[hookAttribute].push({
|
||||
callback,
|
||||
timeout: options.timeout || 15000,
|
||||
});
|
||||
} else {
|
||||
testDefinitionError(`non-function value ${callback} passed to ${hookName} for '${this.currentTestContext.name}'`);
|
||||
testDefinitionError(
|
||||
`non-function value ${callback} passed to ${hookName} for '${
|
||||
this.currentTestContext.name
|
||||
}'`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +167,10 @@ class TestSuiteDefinition {
|
||||
pushTestContext(name, options = {}) {
|
||||
const testContextId = assignContextId();
|
||||
const parentContext = this.currentTestContext;
|
||||
this.currentTestContext = this._initialiseContext(testContextId, Object.assign({ name, parentContextId: parentContext.id }, options));
|
||||
this.currentTestContext = this._initialiseContext(
|
||||
testContextId,
|
||||
Object.assign({ name, parentContextId: parentContext.id }, options)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,7 +178,7 @@ class TestSuiteDefinition {
|
||||
* current context.
|
||||
*/
|
||||
popTestContext() {
|
||||
const parentContextId = this.currentTestContext.parentContextId;
|
||||
const { parentContextId } = this.currentTestContext;
|
||||
this.currentTestContext = this.testContexts[parentContextId];
|
||||
}
|
||||
|
||||
@ -199,7 +207,9 @@ class TestSuiteDefinition {
|
||||
this._createTest(testId, {
|
||||
testContextId: this.currentTestContext.id,
|
||||
testSuiteId: this.testSuite.id,
|
||||
description: this._testDescriptionContextPrefix(this.currentTestContext) + description,
|
||||
description:
|
||||
this._testDescriptionContextPrefix(this.currentTestContext) +
|
||||
description,
|
||||
func: _testFunction,
|
||||
timeout: _options.timeout || 5000,
|
||||
});
|
||||
@ -237,11 +247,17 @@ class TestSuiteDefinition {
|
||||
* @private
|
||||
*/
|
||||
_testDescriptionContextPrefix({ id, name, parentContextId }, suffix = '') {
|
||||
if (id === this.rootTestContextId || parentContextId === this.rootTestContextId) {
|
||||
if (
|
||||
id === this.rootTestContextId ||
|
||||
parentContextId === this.rootTestContextId
|
||||
) {
|
||||
return suffix;
|
||||
}
|
||||
|
||||
return this._testDescriptionContextPrefix(this.testContexts[parentContextId], `${name} ${suffix}`);
|
||||
return this._testDescriptionContextPrefix(
|
||||
this.testContexts[parentContextId],
|
||||
`${name} ${suffix}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -278,8 +294,18 @@ class TestSuiteDefinition {
|
||||
const newTestContext = {
|
||||
id: testContextId,
|
||||
name,
|
||||
focus: this._incorporateParentValue(parentContext, 'focus', focus, CONTEXT_OPERATORS.OR),
|
||||
pending: this._incorporateParentValue(parentContext, 'pending', pending, CONTEXT_OPERATORS.OR),
|
||||
focus: this._incorporateParentValue(
|
||||
parentContext,
|
||||
'focus',
|
||||
focus,
|
||||
CONTEXT_OPERATORS.OR
|
||||
),
|
||||
pending: this._incorporateParentValue(
|
||||
parentContext,
|
||||
'pending',
|
||||
pending,
|
||||
CONTEXT_OPERATORS.OR
|
||||
),
|
||||
parentContextId,
|
||||
testIds: [],
|
||||
testSuiteId: this.testSuite.id,
|
||||
@ -327,7 +353,10 @@ class TestSuiteDefinition {
|
||||
* @returns {Test} New test matching provided options
|
||||
* @private
|
||||
*/
|
||||
_createTest(testId, { testContextId, description, func, testSuiteId, timeout }) {
|
||||
_createTest(
|
||||
testId,
|
||||
{ testContextId, description, func, testSuiteId, timeout }
|
||||
) {
|
||||
const newTest = {
|
||||
id: testId,
|
||||
testContextId,
|
||||
@ -344,7 +373,6 @@ class TestSuiteDefinition {
|
||||
|
||||
return newTest;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,10 +8,11 @@ export function setNetworkState(isConnected: boolean): Object {
|
||||
};
|
||||
}
|
||||
|
||||
export function setAppState(appState: 'active' | 'background' | 'inactive'): Object {
|
||||
export function setAppState(
|
||||
appState: 'active' | 'background' | 'inactive'
|
||||
): Object {
|
||||
return {
|
||||
type: APP_SET_APP_STATE,
|
||||
appState,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,13 @@ export function setSuiteStatus({ suiteId, status, time, message, progress }) {
|
||||
};
|
||||
}
|
||||
|
||||
export function setTestStatus({ testId, status, stackTrace, time = 0, message = null }) {
|
||||
export function setTestStatus({
|
||||
testId,
|
||||
status,
|
||||
stackTrace,
|
||||
time = 0,
|
||||
message = null,
|
||||
}) {
|
||||
return {
|
||||
type: TEST_SET_STATUS,
|
||||
testId,
|
||||
|
@ -5,10 +5,7 @@ import { StyleSheet, View, Text } from 'react-native';
|
||||
function Banner({ type, children, style, textStyle }) {
|
||||
return (
|
||||
<View style={[styles.banner, styles[type || 'default'], style]}>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
style={[styles.bannerText, textStyle]}
|
||||
>
|
||||
<Text numberOfLines={1} style={[styles.bannerText, textStyle]}>
|
||||
{children}
|
||||
</Text>
|
||||
</View>
|
||||
@ -16,18 +13,14 @@ function Banner({ type, children, style, textStyle }) {
|
||||
}
|
||||
|
||||
Banner.propTypes = {
|
||||
type: PropTypes.oneOf([
|
||||
'success',
|
||||
'warning',
|
||||
'error',
|
||||
'info',
|
||||
]),
|
||||
children: PropTypes.oneOfType([
|
||||
PropTypes.string,
|
||||
PropTypes.array,
|
||||
]).isRequired,
|
||||
/* eslint-disable react/require-default-props */
|
||||
/* eslint-disable react/no-typos */
|
||||
type: PropTypes.oneOf(['success', 'warning', 'error', 'info']),
|
||||
children: PropTypes.oneOfType([PropTypes.string, PropTypes.array]).isRequired,
|
||||
style: View.propTypes.style,
|
||||
textStyle: Text.propTypes.style,
|
||||
/* eslint-enable react/require-default-props */
|
||||
/* eslint-enable react/no-typos */
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
@ -4,6 +4,7 @@ import VectorIcon from 'react-native-vector-icons/MaterialIcons';
|
||||
|
||||
type Props = {
|
||||
name: string,
|
||||
/* eslint-disable react/require-default-props */
|
||||
size?: number,
|
||||
color?: string,
|
||||
allowFontScaling?: boolean,
|
||||
@ -11,11 +12,11 @@ type Props = {
|
||||
rotate?: number,
|
||||
onPress?: () => void,
|
||||
underlayColor?: string,
|
||||
/* eslint-enable react/require-default-props */
|
||||
};
|
||||
|
||||
// TODO Spin?
|
||||
class Icon extends React.Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.measured = false;
|
||||
@ -36,15 +37,24 @@ class Icon extends React.Component {
|
||||
props: Props;
|
||||
|
||||
render() {
|
||||
const { name, size = 24, color = '#757575', allowFontScaling = true, style, rotate, onPress, underlayColor } = this.props;
|
||||
const {
|
||||
name,
|
||||
size = 24,
|
||||
color = '#757575',
|
||||
allowFontScaling = true,
|
||||
style,
|
||||
rotate,
|
||||
onPress,
|
||||
underlayColor,
|
||||
} = this.props;
|
||||
|
||||
const icon = (
|
||||
<View
|
||||
onLayout={(e) => this.setDimensions(e)}
|
||||
onLayout={e => this.setDimensions(e)}
|
||||
style={[
|
||||
style,
|
||||
rotate ? { transform: [{ rotate: `${rotate}deg` }] } : null,
|
||||
]}
|
||||
style,
|
||||
rotate ? { transform: [{ rotate: `${rotate}deg` }] } : null,
|
||||
]}
|
||||
>
|
||||
<VectorIcon
|
||||
name={name.toLowerCase().replace(/\s+/g, '-')}
|
||||
@ -69,7 +79,6 @@ class Icon extends React.Component {
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Icon;
|
||||
|
@ -20,7 +20,10 @@ class OverviewControlButton extends Component {
|
||||
testSuitesAreRunning() {
|
||||
const { testSuites } = this.props;
|
||||
|
||||
return some(Object.values(testSuites), ({ status }) => status === RunStatus.RUNNING);
|
||||
return some(
|
||||
Object.values(testSuites),
|
||||
({ status }) => status === RunStatus.RUNNING
|
||||
);
|
||||
}
|
||||
|
||||
handleOnPress() {
|
||||
@ -31,18 +34,12 @@ class OverviewControlButton extends Component {
|
||||
|
||||
render() {
|
||||
if (this.testSuitesAreRunning()) {
|
||||
return (
|
||||
<Icon
|
||||
color={'#ffffff'}
|
||||
size={28}
|
||||
name="autorenew"
|
||||
/>
|
||||
);
|
||||
return <Icon color="#ffffff" size={28} name="autorenew" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Icon
|
||||
color={'#ffffff'}
|
||||
color="#ffffff"
|
||||
size={28}
|
||||
name="play circle filled"
|
||||
onPress={this.handleOnPress}
|
||||
@ -58,8 +55,12 @@ OverviewControlButton.propTypes = {
|
||||
pendingTestIds: PropTypes.objectOf(PropTypes.bool).isRequired,
|
||||
};
|
||||
|
||||
|
||||
function mapStateToProps({ tests, testSuites, focusedTestIds, pendingTestIds }) {
|
||||
function mapStateToProps({
|
||||
tests,
|
||||
testSuites,
|
||||
focusedTestIds,
|
||||
pendingTestIds,
|
||||
}) {
|
||||
return {
|
||||
tests,
|
||||
testSuites,
|
||||
|
@ -1,44 +1,32 @@
|
||||
import { View, Text } from 'react-native';
|
||||
import React, { Component } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import RunStatus from '../../lib/RunStatus';
|
||||
import Icon from './Icon';
|
||||
|
||||
class StatusIndicator extends Component {
|
||||
|
||||
render() {
|
||||
const { status, progress } = this.props;
|
||||
|
||||
switch (status) {
|
||||
case RunStatus.RUNNING:
|
||||
if (progress > 0) {
|
||||
return (
|
||||
<View style={{ width: 30, flex: 1, justifyContent: 'flex-end' }}>
|
||||
<Text style={{ fontSize: 11, marginBottom: 20 }}>
|
||||
{progress.toFixed(0)}%
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const StatusIndicator = ({ status, progress }) => {
|
||||
switch (status) {
|
||||
case RunStatus.RUNNING:
|
||||
if (progress > 0) {
|
||||
return (
|
||||
<Icon color={'rgba(0, 0, 0, 0.2)'} name="autorenew" />
|
||||
<View style={{ width: 30, flex: 1, justifyContent: 'flex-end' }}>
|
||||
<Text style={{ fontSize: 11, marginBottom: 20 }}>
|
||||
{progress.toFixed(0)}%
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
case RunStatus.OK:
|
||||
return (
|
||||
<Icon name={'done'} />
|
||||
);
|
||||
case RunStatus.ERR:
|
||||
return (
|
||||
<Icon color={'#f44336'} name="clear" />
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return <Icon color="rgba(0, 0, 0, 0.2)" name="autorenew" />;
|
||||
case RunStatus.OK:
|
||||
return <Icon name="done" />;
|
||||
case RunStatus.ERR:
|
||||
return <Icon color="#f44336" name="clear" />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
StatusIndicator.propTypes = {
|
||||
status: PropTypes.oneOf(Object.values(RunStatus)),
|
||||
@ -47,7 +35,7 @@ StatusIndicator.propTypes = {
|
||||
|
||||
StatusIndicator.defaultProps = {
|
||||
status: null,
|
||||
progress: 0
|
||||
progress: 0,
|
||||
};
|
||||
|
||||
module.exports = StatusIndicator;
|
||||
|
@ -21,7 +21,7 @@ class TestControlButton extends Component {
|
||||
}
|
||||
|
||||
handleOnPress() {
|
||||
const { test: { id, description } } = this.props;
|
||||
const { test: { id } } = this.props;
|
||||
|
||||
runTest(id);
|
||||
// Toast.show(`Running ${description}.`);
|
||||
@ -33,7 +33,7 @@ class TestControlButton extends Component {
|
||||
if (status !== RunStatus.STARTED && !this.testIsPending()) {
|
||||
return (
|
||||
<Icon
|
||||
color={'#ffffff'}
|
||||
color="#ffffff"
|
||||
size={28}
|
||||
name="play circle filled"
|
||||
onPress={this.handleOnPress}
|
||||
@ -43,7 +43,6 @@ class TestControlButton extends Component {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TestControlButton.propTypes = {
|
||||
@ -56,9 +55,7 @@ TestControlButton.propTypes = {
|
||||
pendingTestIds: PropTypes.objectOf(PropTypes.bool).isRequired,
|
||||
};
|
||||
|
||||
TestControlButton.defaultProps = {
|
||||
|
||||
};
|
||||
TestControlButton.defaultProps = {};
|
||||
|
||||
function mapStateToProps({ tests, pendingTestIds }, { testId }) {
|
||||
const test = tests[testId];
|
||||
|
@ -13,12 +13,19 @@ class TestSuiteControlButton extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.toggleOnlyShowFailingTests = this.toggleOnlyShowFailingTests.bind(this);
|
||||
this.toggleOnlyShowFailingTests = this.toggleOnlyShowFailingTests.bind(
|
||||
this
|
||||
);
|
||||
this.startTestSuite = this.startTestSuite.bind(this);
|
||||
}
|
||||
|
||||
startTestSuite() {
|
||||
const { testSuite: { name, testIds }, tests, focusedTestIds, pendingTestIds } = this.props;
|
||||
const {
|
||||
testSuite: { testIds },
|
||||
tests,
|
||||
focusedTestIds,
|
||||
pendingTestIds,
|
||||
} = this.props;
|
||||
|
||||
const testSuiteTests = testIds.reduce((memo, testId) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
@ -51,7 +58,7 @@ class TestSuiteControlButton extends Component {
|
||||
} else if (status !== RunStatus.RUNNING) {
|
||||
return (
|
||||
<Icon
|
||||
color={'#ffffff'}
|
||||
color="#ffffff"
|
||||
size={28}
|
||||
name="play circle filled"
|
||||
onPress={this.startTestSuite}
|
||||
@ -61,7 +68,6 @@ class TestSuiteControlButton extends Component {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TestSuiteControlButton.propTypes = {
|
||||
@ -82,8 +88,10 @@ TestSuiteControlButton.defaultProps = {
|
||||
onlyShowFailingTests: false,
|
||||
};
|
||||
|
||||
|
||||
function mapStateToProps({ tests, testSuites, focusedTestIds, pendingTestIds }, { testSuiteId }) {
|
||||
function mapStateToProps(
|
||||
{ tests, testSuites, focusedTestIds, pendingTestIds },
|
||||
{ testSuiteId }
|
||||
) {
|
||||
const testSuite = testSuites[testSuiteId];
|
||||
|
||||
return {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// @flow
|
||||
import React from 'react';
|
||||
import { View, Text, AppState, NetInfo, StatusBar, Platform } from 'react-native';
|
||||
import { AppState, NetInfo, StatusBar, Platform } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import Navigator from '../navigator';
|
||||
@ -11,7 +11,6 @@ type Props = {
|
||||
};
|
||||
|
||||
class CoreContainer extends React.Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._isConnected = false;
|
||||
@ -28,10 +27,13 @@ class CoreContainer extends React.Component {
|
||||
StatusBar.setBarStyle('light-content');
|
||||
}
|
||||
AppState.addEventListener('change', this.handleAppStateChange);
|
||||
NetInfo.isConnected.fetch().then((isConnected) => {
|
||||
NetInfo.isConnected.fetch().then(isConnected => {
|
||||
this.handleAppStateChange('active'); // Force connect (react debugger issue)
|
||||
this.props.dispatch(setNetworkState(isConnected));
|
||||
NetInfo.isConnected.addEventListener('connectionChange', this.handleNetworkChange);
|
||||
NetInfo.isConnected.addEventListener(
|
||||
'connectionChange',
|
||||
this.handleNetworkChange
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -40,7 +42,10 @@ class CoreContainer extends React.Component {
|
||||
*/
|
||||
componentWillUnmount() {
|
||||
AppState.removeEventListener('change', this.handleAppStateChange);
|
||||
NetInfo.isConnected.removeEventListener('connectionChange', this.handleNetworkChange);
|
||||
NetInfo.isConnected.removeEventListener(
|
||||
'connectionChange',
|
||||
this.handleNetworkChange
|
||||
);
|
||||
}
|
||||
|
||||
props: Props;
|
||||
@ -51,7 +56,7 @@ class CoreContainer extends React.Component {
|
||||
* https://facebook.github.io/react-native/docs/appstate.html
|
||||
* @param state
|
||||
*/
|
||||
handleAppStateChange = (state) => {
|
||||
handleAppStateChange = state => {
|
||||
this.props.dispatch(setAppState(state));
|
||||
if (state === 'active' && this._isConnected) {
|
||||
// firestack.database().goOnline();
|
||||
@ -65,7 +70,7 @@ class CoreContainer extends React.Component {
|
||||
* https://facebook.github.io/react-native/docs/netinfo.html
|
||||
* @param isConnected
|
||||
*/
|
||||
handleNetworkChange = (isConnected) => {
|
||||
handleNetworkChange = isConnected => {
|
||||
this._isConnected = isConnected;
|
||||
this.props.dispatch(setNetworkState(isConnected));
|
||||
if (isConnected) {
|
||||
|
@ -17,7 +17,8 @@ const config = {
|
||||
|
||||
const android = {
|
||||
// firebase android sdk completely ignores client id
|
||||
clientId: '305229645282-j8ij0jev9ut24odmlk9i215pas808ugn.apps.googleusercontent.com',
|
||||
clientId:
|
||||
'305229645282-j8ij0jev9ut24odmlk9i215pas808ugn.apps.googleusercontent.com',
|
||||
appId: '1:305229645282:android:efe37851d57e1d05',
|
||||
apiKey: 'AIzaSyDnVqNhxU0Biit9nCo4RorAh5ulQQwko3E',
|
||||
databaseURL: 'https://rnfirebase-b9ad4.firebaseio.com',
|
||||
@ -26,9 +27,9 @@ const android = {
|
||||
projectId: 'rnfirebase-b9ad4',
|
||||
};
|
||||
|
||||
|
||||
const ios = {
|
||||
clientId: '305229645282-22imndi01abc2p6esgtu1i1m9mqrd0ib.apps.googleusercontent.com',
|
||||
clientId:
|
||||
'305229645282-22imndi01abc2p6esgtu1i1m9mqrd0ib.apps.googleusercontent.com',
|
||||
androidClientId: android.clientId,
|
||||
appId: '1:305229645282:ios:7b45748cb1117d2d',
|
||||
apiKey: 'AIzaSyDnVqNhxU0Biit9nCo4RorAh5ulQQwko3E',
|
||||
@ -41,34 +42,52 @@ const ios = {
|
||||
const instances = {
|
||||
web: firebase.initializeApp(config),
|
||||
native: RNfirebase,
|
||||
another: RNfirebase.initializeApp(Platform.OS === 'ios' ? ios : android, 'anotherApp'),
|
||||
another: RNfirebase.initializeApp(
|
||||
Platform.OS === 'ios' ? ios : android,
|
||||
'anotherApp'
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
|
||||
console.log('RNApps -->', RNfirebase.apps);
|
||||
|
||||
// natively initialized apps are already available at app run time,
|
||||
// no need for ready checks
|
||||
instances.native.auth().signInAnonymously().then((user) => {
|
||||
console.log('defaultApp user ->', user.toJSON());
|
||||
});
|
||||
instances.native
|
||||
.auth()
|
||||
.signInAnonymously()
|
||||
.then(user => {
|
||||
console.log('defaultApp user ->', user.toJSON());
|
||||
});
|
||||
|
||||
// dynamically initialized apps need a ready check
|
||||
instances.another.onReady().then((app) => {
|
||||
app.auth().signInAnonymously().then((user) => {
|
||||
console.log('anotherApp user ->', user.toJSON());
|
||||
});
|
||||
instances.another.onReady().then(app => {
|
||||
app
|
||||
.auth()
|
||||
.signInAnonymously()
|
||||
.then(user => {
|
||||
console.log('anotherApp user ->', user.toJSON());
|
||||
});
|
||||
});
|
||||
|
||||
instances.web.database().ref('tests/types').set(DatabaseContents.DEFAULT);
|
||||
instances.web
|
||||
.database()
|
||||
.ref('tests/types')
|
||||
.set(DatabaseContents.DEFAULT);
|
||||
|
||||
instances.web.database().ref('tests/priority').setWithPriority({
|
||||
foo: 'bar',
|
||||
}, 666);
|
||||
|
||||
instances.web.database().ref('tests/query').set(DatabaseContents.QUERY);
|
||||
instances.web
|
||||
.database()
|
||||
.ref('tests/priority')
|
||||
.setWithPriority(
|
||||
{
|
||||
foo: 'bar',
|
||||
},
|
||||
666
|
||||
);
|
||||
|
||||
instances.web
|
||||
.database()
|
||||
.ref('tests/query')
|
||||
.set(DatabaseContents.QUERY);
|
||||
|
||||
// instances.native.messaging().subscribeToTopic('fcm_test');
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
// import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
@ -24,8 +24,7 @@ const unitId = {
|
||||
const firebase = fb.native;
|
||||
|
||||
// Components
|
||||
const Banner = firebase.admob.Banner;
|
||||
const NativeExpress = firebase.admob.NativeExpress;
|
||||
const { Banner, NativeExpress } = firebase.admob;
|
||||
|
||||
// API
|
||||
const interstitial = firebase.admob().interstitial(unitId.interstitial);
|
||||
@ -34,24 +33,19 @@ interstitial.loadAd();
|
||||
const rewarded = firebase.admob().rewarded(unitId.rewarded);
|
||||
rewarded.loadAd();
|
||||
|
||||
|
||||
function bootstrap() {
|
||||
// Remove logging on production
|
||||
if (!__DEV__) {
|
||||
console.log = () => {
|
||||
};
|
||||
console.warn = () => {
|
||||
};
|
||||
console.error = () => {
|
||||
};
|
||||
console.log = () => {};
|
||||
console.warn = () => {};
|
||||
console.error = () => {};
|
||||
console.disableYellowBox = true;
|
||||
}
|
||||
|
||||
class Root extends Component {
|
||||
|
||||
showInterstitial() {
|
||||
interstitial.show();
|
||||
};
|
||||
}
|
||||
|
||||
showRewarded() {
|
||||
rewarded.show();
|
||||
@ -60,22 +54,13 @@ function bootstrap() {
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<Banner
|
||||
unitId={unitId.banner}
|
||||
size={'SMART_BANNER'}
|
||||
/>
|
||||
<Banner unitId={unitId.banner} size="SMART_BANNER" />
|
||||
<NativeExpress
|
||||
unitId={'ca-app-pub-3940256099942544/2793859312'}
|
||||
size={'300x200'}
|
||||
/>
|
||||
<Button
|
||||
title={'Show Interstitial'}
|
||||
onPress={this.showInterstitial}
|
||||
/>
|
||||
<Button
|
||||
title={'Show Rewarded Video'}
|
||||
onPress={this.showRewarded}
|
||||
unitId="ca-app-pub-3940256099942544/2793859312"
|
||||
size="300x200"
|
||||
/>
|
||||
<Button title="Show Interstitial" onPress={this.showInterstitial} />
|
||||
<Button title="Show Rewarded Video" onPress={this.showRewarded} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
@ -6,7 +6,9 @@ import { setupSuites } from './tests/index';
|
||||
|
||||
global.Promise = require('bluebird');
|
||||
|
||||
console.ignoredYellowBox = ['Setting a timer for a long period of time, i.e. multiple minutes'];
|
||||
console.ignoredYellowBox = [
|
||||
'Setting a timer for a long period of time, i.e. multiple minutes',
|
||||
];
|
||||
|
||||
type State = {
|
||||
loading: boolean,
|
||||
@ -16,12 +18,9 @@ type State = {
|
||||
function bootstrap() {
|
||||
// Remove logging on production
|
||||
if (!__DEV__) {
|
||||
console.log = () => {
|
||||
};
|
||||
console.warn = () => {
|
||||
};
|
||||
console.error = () => {
|
||||
};
|
||||
console.log = () => {};
|
||||
console.warn = () => {};
|
||||
console.error = () => {};
|
||||
console.disableYellowBox = true;
|
||||
}
|
||||
|
||||
@ -37,7 +36,7 @@ function bootstrap() {
|
||||
state: State;
|
||||
|
||||
componentDidMount() {
|
||||
setupStore((store) => {
|
||||
setupStore(store => {
|
||||
setupSuites(store);
|
||||
this.setState({
|
||||
store,
|
||||
|
@ -1,15 +1,23 @@
|
||||
import React, { Component } from 'react';
|
||||
import { View, Button, Text, TextInput, Image, ActivityIndicator, Platform } from 'react-native';
|
||||
import {
|
||||
View,
|
||||
Button,
|
||||
Text,
|
||||
TextInput,
|
||||
Image,
|
||||
ActivityIndicator,
|
||||
Platform,
|
||||
} from 'react-native';
|
||||
import fb from './firebase';
|
||||
|
||||
const firebase = fb.native;
|
||||
|
||||
const imageUrl = 'https://www.shareicon.net/data/512x512/2016/07/19/798524_sms_512x512.png';
|
||||
const imageUrl =
|
||||
'https://www.shareicon.net/data/512x512/2016/07/19/798524_sms_512x512.png';
|
||||
|
||||
export default class PhoneAuth extends Component {
|
||||
static getDefaultState() {
|
||||
return {
|
||||
message: '',
|
||||
error: '',
|
||||
codeInput: '',
|
||||
phoneNumber: '+44',
|
||||
@ -39,72 +47,90 @@ export default class PhoneAuth extends Component {
|
||||
*/
|
||||
afterVerify = () => {
|
||||
const { codeInput, verificationId } = this.state;
|
||||
const credential = firebase.auth.PhoneAuthProvider.credential(verificationId, codeInput);
|
||||
const credential = firebase.auth.PhoneAuthProvider.credential(
|
||||
verificationId,
|
||||
codeInput
|
||||
);
|
||||
|
||||
// TODO do something with credential for example:
|
||||
firebase.auth()
|
||||
firebase
|
||||
.auth()
|
||||
.signInWithCredential(credential)
|
||||
.then((user) => {
|
||||
.then(user => {
|
||||
console.log('PHONE AUTH USER ->>>>>', user.toJSON());
|
||||
this.setState({ user: user.toJSON() });
|
||||
}).catch(console.error);
|
||||
})
|
||||
.catch(console.error);
|
||||
};
|
||||
|
||||
signIn = () => {
|
||||
const { phoneNumber } = this.state;
|
||||
this.setState({ message: 'Sending code ...', error: '', started: true, autoVerifyCountDown: this.timeout }, () => {
|
||||
firebase.auth()
|
||||
.verifyPhoneNumber(phoneNumber)
|
||||
.on('state_changed', (phoneAuthSnapshot) => {
|
||||
console.log(phoneAuthSnapshot);
|
||||
switch (phoneAuthSnapshot.state) {
|
||||
case firebase.auth.PhoneAuthState.CODE_SENT: // or 'sent'
|
||||
// update state with code sent and if android start a interval timer
|
||||
// for auto verify - to provide visual feedback
|
||||
this.setState({
|
||||
sent: true,
|
||||
message: 'Code Sent!',
|
||||
verificationId: phoneAuthSnapshot.verificationId,
|
||||
autoVerifyCountDown: this.timeout,
|
||||
}, () => {
|
||||
if (this.state.auto) {
|
||||
this._autoVerifyInterval = setInterval(this._tick.bind(this), 1000);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case firebase.auth.PhoneAuthState.ERROR: // or 'error'
|
||||
// restart the phone flow again on error
|
||||
clearInterval(this._autoVerifyInterval);
|
||||
this.setState({
|
||||
...PhoneAuth.getDefaultState(),
|
||||
error: phoneAuthSnapshot.error.message,
|
||||
});
|
||||
break;
|
||||
this.setState(
|
||||
{
|
||||
error: '',
|
||||
started: true,
|
||||
autoVerifyCountDown: this.timeout,
|
||||
},
|
||||
() => {
|
||||
firebase
|
||||
.auth()
|
||||
.verifyPhoneNumber(phoneNumber)
|
||||
.on('state_changed', phoneAuthSnapshot => {
|
||||
console.log(phoneAuthSnapshot);
|
||||
switch (phoneAuthSnapshot.state) {
|
||||
case firebase.auth.PhoneAuthState.CODE_SENT: // or 'sent'
|
||||
// update state with code sent and if android start a interval timer
|
||||
// for auto verify - to provide visual feedback
|
||||
this.setState(
|
||||
{
|
||||
sent: true,
|
||||
verificationId: phoneAuthSnapshot.verificationId,
|
||||
autoVerifyCountDown: this.timeout,
|
||||
},
|
||||
() => {
|
||||
if (this.state.auto) {
|
||||
this._autoVerifyInterval = setInterval(
|
||||
this._tick.bind(this),
|
||||
1000
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
break;
|
||||
case firebase.auth.PhoneAuthState.ERROR: // or 'error'
|
||||
// restart the phone flow again on error
|
||||
clearInterval(this._autoVerifyInterval);
|
||||
this.setState({
|
||||
...PhoneAuth.getDefaultState(),
|
||||
error: phoneAuthSnapshot.error.message,
|
||||
});
|
||||
break;
|
||||
|
||||
// ---------------------
|
||||
// ANDROID ONLY EVENTS
|
||||
// ---------------------
|
||||
case firebase.auth.PhoneAuthState.AUTO_VERIFY_TIMEOUT: // or 'timeout'
|
||||
clearInterval(this._autoVerifyInterval);
|
||||
this.setState({
|
||||
sent: true,
|
||||
auto: false,
|
||||
verificationId: phoneAuthSnapshot.verificationId,
|
||||
});
|
||||
break;
|
||||
case firebase.auth.PhoneAuthState.AUTO_VERIFIED: // or 'verified'
|
||||
clearInterval(this._autoVerifyInterval);
|
||||
this.setState({
|
||||
sent: true,
|
||||
codeInput: phoneAuthSnapshot.code,
|
||||
verificationId: phoneAuthSnapshot.verificationId,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
// will never get here - just for linting
|
||||
}
|
||||
});
|
||||
});
|
||||
// ---------------------
|
||||
// ANDROID ONLY EVENTS
|
||||
// ---------------------
|
||||
case firebase.auth.PhoneAuthState.AUTO_VERIFY_TIMEOUT: // or 'timeout'
|
||||
clearInterval(this._autoVerifyInterval);
|
||||
this.setState({
|
||||
sent: true,
|
||||
auto: false,
|
||||
verificationId: phoneAuthSnapshot.verificationId,
|
||||
});
|
||||
break;
|
||||
case firebase.auth.PhoneAuthState.AUTO_VERIFIED: // or 'verified'
|
||||
clearInterval(this._autoVerifyInterval);
|
||||
this.setState({
|
||||
sent: true,
|
||||
codeInput: phoneAuthSnapshot.code,
|
||||
verificationId: phoneAuthSnapshot.verificationId,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
// will never get here - just for linting
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
renderInputPhoneNumber() {
|
||||
@ -116,10 +142,14 @@ export default class PhoneAuth extends Component {
|
||||
autoFocus
|
||||
style={{ height: 40, marginTop: 15, marginBottom: 15 }}
|
||||
onChangeText={value => this.setState({ phoneNumber: value })}
|
||||
placeholder={'Phone number ... '}
|
||||
placeholder="Phone number ... "
|
||||
value={phoneNumber}
|
||||
/>
|
||||
<Button title="Begin Verification" color="green" onPress={this.signIn} />
|
||||
<Button
|
||||
title="Begin Verification"
|
||||
color="green"
|
||||
onPress={this.signIn}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@ -129,35 +159,37 @@ export default class PhoneAuth extends Component {
|
||||
|
||||
return (
|
||||
<View style={{ paddingBottom: 15 }}>
|
||||
<Text
|
||||
style={{ paddingBottom: 25 }}
|
||||
>
|
||||
<Text style={{ paddingBottom: 25 }}>
|
||||
{`Sending verification code to '${phoneNumber}'.`}
|
||||
</Text>
|
||||
<ActivityIndicator animating style={{ padding: 50 }} size={'large'} />
|
||||
<ActivityIndicator animating style={{ padding: 50 }} size="large" />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
renderAutoVerifyProgress() {
|
||||
const { autoVerifyCountDown, started, error, sent, phoneNumber } = this.state;
|
||||
const {
|
||||
autoVerifyCountDown,
|
||||
started,
|
||||
error,
|
||||
sent,
|
||||
phoneNumber,
|
||||
} = this.state;
|
||||
if (!sent && started && !error.length) {
|
||||
return this.renderSendingCode();
|
||||
}
|
||||
return (
|
||||
<View style={{ padding: 0 }}>
|
||||
<Text
|
||||
style={{ paddingBottom: 25 }}
|
||||
>
|
||||
<Text style={{ paddingBottom: 25 }}>
|
||||
{`Verification code has been successfully sent to '${phoneNumber}'.`}
|
||||
</Text>
|
||||
<Text
|
||||
style={{ marginBottom: 25 }}
|
||||
>
|
||||
<Text style={{ marginBottom: 25 }}>
|
||||
{`We'll now attempt to automatically verify the code for you. This will timeout in ${autoVerifyCountDown} seconds.`}
|
||||
</Text>
|
||||
<Button
|
||||
style={{ paddingTop: 25 }} title="I have a code already" color="green"
|
||||
style={{ paddingTop: 25 }}
|
||||
title="I have a code already"
|
||||
color="green"
|
||||
onPress={() => this.setState({ auto: false })}
|
||||
/>
|
||||
</View>
|
||||
@ -168,12 +200,15 @@ export default class PhoneAuth extends Component {
|
||||
const { error } = this.state;
|
||||
|
||||
return (
|
||||
<View style={{ padding: 10, borderRadius: 5, margin: 10, backgroundColor: 'rgb(255,0,0)' }}>
|
||||
<Text
|
||||
style={{ color: '#fff' }}
|
||||
>
|
||||
{error}
|
||||
</Text>
|
||||
<View
|
||||
style={{
|
||||
padding: 10,
|
||||
borderRadius: 5,
|
||||
margin: 10,
|
||||
backgroundColor: 'rgb(255,0,0)',
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: '#fff' }}>{error}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@ -181,7 +216,9 @@ export default class PhoneAuth extends Component {
|
||||
render() {
|
||||
const { started, error, codeInput, sent, auto, user } = this.state;
|
||||
return (
|
||||
<View style={{ flex: 1, backgroundColor: user ? 'rgb(0, 200, 0)' : '#fff' }}>
|
||||
<View
|
||||
style={{ flex: 1, backgroundColor: user ? 'rgb(0, 200, 0)' : '#fff' }}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
padding: 5,
|
||||
@ -190,11 +227,23 @@ export default class PhoneAuth extends Component {
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
<Image source={{ uri: imageUrl }} style={{ width: 128, height: 128, marginTop: 25, marginBottom: 15 }} />
|
||||
<Text style={{ fontSize: 25, marginBottom: 20 }}>Phone Auth Example</Text>
|
||||
<Image
|
||||
source={{ uri: imageUrl }}
|
||||
style={{
|
||||
width: 128,
|
||||
height: 128,
|
||||
marginTop: 25,
|
||||
marginBottom: 15,
|
||||
}}
|
||||
/>
|
||||
<Text style={{ fontSize: 25, marginBottom: 20 }}>
|
||||
Phone Auth Example
|
||||
</Text>
|
||||
{error && error.length ? this.renderError() : null}
|
||||
{!started && !sent ? this.renderInputPhoneNumber() : null}
|
||||
{started && auto && !codeInput.length ? this.renderAutoVerifyProgress() : null}
|
||||
{started && auto && !codeInput.length
|
||||
? this.renderAutoVerifyProgress()
|
||||
: null}
|
||||
{!user && started && sent && (codeInput.length || !auto) ? (
|
||||
<View style={{ marginTop: 15 }}>
|
||||
<Text>Enter verification code below:</Text>
|
||||
@ -202,10 +251,14 @@ export default class PhoneAuth extends Component {
|
||||
autoFocus
|
||||
style={{ height: 40, marginTop: 15, marginBottom: 15 }}
|
||||
onChangeText={value => this.setState({ codeInput: value })}
|
||||
placeholder={'Code ... '}
|
||||
placeholder="Code ... "
|
||||
value={codeInput}
|
||||
/>
|
||||
<Button title="Confirm Code" color="#841584" onPress={this.afterVerify} />
|
||||
<Button
|
||||
title="Confirm Code"
|
||||
color="#841584"
|
||||
onPress={this.afterVerify}
|
||||
/>
|
||||
</View>
|
||||
) : null}
|
||||
{user ? (
|
||||
@ -219,7 +272,6 @@ export default class PhoneAuth extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
{ user ? (
|
||||
<View
|
||||
@ -238,7 +290,6 @@ export default class PhoneAuth extends Component {
|
||||
) : null}
|
||||
*/
|
||||
|
||||
|
||||
// Example usage if handling here and not in optionalCompleteCb:
|
||||
// const { verificationId, code } = phoneAuthSnapshot;
|
||||
// const credential = firebase.auth.PhoneAuthProvider.credential(verificationId, code);
|
||||
|
@ -1,4 +1,3 @@
|
||||
import * as fcmTypes from '../actions/FCMActions';
|
||||
import * as appTypes from '../actions/AppActions';
|
||||
|
||||
type State = {
|
||||
@ -14,7 +13,6 @@ const initialState = {
|
||||
};
|
||||
|
||||
function device(state: State = initialState, action: Object): State {
|
||||
|
||||
if (action.type === appTypes.APP_SET_NETWORK_STATE) {
|
||||
return {
|
||||
...state,
|
||||
|
@ -1,17 +1,19 @@
|
||||
import * as testActions from '../actions/TestActions';
|
||||
import { flatten, unflatten } from 'deeps';
|
||||
import * as testActions from '../actions/TestActions';
|
||||
import { initialState } from '../tests/index';
|
||||
|
||||
const initState = initialState();
|
||||
|
||||
function testsReducers(state = initState.testSuites, action: Object): State {
|
||||
|
||||
if (action.type === testActions.TEST_SET_SUITE_STATUS) {
|
||||
const flattened = flatten(state);
|
||||
|
||||
if (action.status) flattened[`${action.suiteId}.status`] = action.status;
|
||||
if (action.message) flattened[`${action.suiteId}.message`] = action.message;
|
||||
if (action.progress) flattened[`${action.suiteId}.progress`] = action.progress;
|
||||
if (action.progress) {
|
||||
flattened[`${action.suiteId}.progress`] = action.progress;
|
||||
}
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
if (!isNaN(action.time)) flattened[`${action.suiteId}.time`] = action.time;
|
||||
|
||||
return unflatten(flattened);
|
||||
|
@ -1,6 +1,12 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { StyleSheet, View, Text, ListView, TouchableHighlight } from 'react-native';
|
||||
import {
|
||||
StyleSheet,
|
||||
View,
|
||||
Text,
|
||||
ListView,
|
||||
TouchableHighlight,
|
||||
} from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import some from 'lodash.some';
|
||||
|
||||
@ -31,10 +37,7 @@ class Overview extends React.Component {
|
||||
*/
|
||||
static renderSeparator(sectionID, rowID) {
|
||||
return (
|
||||
<View
|
||||
key={`separator_${sectionID}_${rowID}`}
|
||||
style={styles.separator}
|
||||
/>
|
||||
<View key={`separator_${sectionID}_${rowID}`} style={styles.separator} />
|
||||
);
|
||||
}
|
||||
|
||||
@ -51,9 +54,10 @@ class Overview extends React.Component {
|
||||
return Object.keys(testSuites).reduce((memo, testSuiteId) => {
|
||||
const testSuite = testSuites[testSuiteId];
|
||||
|
||||
const testSuiteHasFocusedTests = some(testSuite.testIds, (testId) => {
|
||||
return focusedTestIds[testId];
|
||||
});
|
||||
const testSuiteHasFocusedTests = some(
|
||||
testSuite.testIds,
|
||||
testId => focusedTestIds[testId]
|
||||
);
|
||||
|
||||
if (testSuiteHasFocusedTests) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
@ -85,7 +89,6 @@ class Overview extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copies latest test suite status into state so they may be rendered as a ListView
|
||||
* @param {Object} nextProps - next props used to render component
|
||||
@ -94,7 +97,9 @@ class Overview extends React.Component {
|
||||
*/
|
||||
componentWillReceiveProps({ testSuites, focusedTestIds }) {
|
||||
this.setState({
|
||||
dataBlob: this.dataSource.cloneWithRows(Overview.testSuitesToShow({ testSuites, focusedTestIds })),
|
||||
dataBlob: this.dataSource.cloneWithRows(
|
||||
Overview.testSuitesToShow({ testSuites, focusedTestIds })
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
@ -122,19 +127,18 @@ class Overview extends React.Component {
|
||||
return (
|
||||
<TouchableHighlight
|
||||
key={`row_${rowId}`}
|
||||
underlayColor={'rgba(0, 0, 0, 0.054)'}
|
||||
underlayColor="rgba(0, 0, 0, 0.054)"
|
||||
onPress={() => {
|
||||
this.goToTestSuite(testSuite);
|
||||
highlight();
|
||||
}}
|
||||
>
|
||||
<View style={[styles.row, status === RunStatus.ERR ? styles.error : null]}>
|
||||
<View
|
||||
style={[styles.row, status === RunStatus.ERR ? styles.error : null]}
|
||||
>
|
||||
<View>
|
||||
<Text style={styles.title}>{name}</Text>
|
||||
<Text
|
||||
style={styles.description}
|
||||
numberOfLines={1}
|
||||
>
|
||||
<Text style={styles.description} numberOfLines={1}>
|
||||
{description}
|
||||
</Text>
|
||||
</View>
|
||||
@ -157,9 +161,7 @@ class Overview extends React.Component {
|
||||
|
||||
if (pendingTestsCount > 0) {
|
||||
return (
|
||||
<Banner type="warning">
|
||||
{pendingTestsCount} pending test(s).
|
||||
</Banner>
|
||||
<Banner type="warning">{pendingTestsCount} pending test(s).</Banner>
|
||||
);
|
||||
}
|
||||
|
||||
@ -189,24 +191,21 @@ class Overview extends React.Component {
|
||||
|
||||
if (isRunning) {
|
||||
return (
|
||||
<Banner type={isErrors ? 'error' : 'warning'}>Running ({(totalTime / 1000).toFixed(0)}s) {totalProgress.toFixed(2)}%</Banner>
|
||||
<Banner type={isErrors ? 'error' : 'warning'}>
|
||||
Running ({(totalTime / 1000).toFixed(0)}s) {totalProgress.toFixed(2)}%
|
||||
</Banner>
|
||||
);
|
||||
} else if (totalProgress > 0) {
|
||||
if (isErrors) {
|
||||
return (
|
||||
<Banner type={'error'}>Tests Complete with errors</Banner>
|
||||
);
|
||||
return <Banner type="error">Tests Complete with errors</Banner>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Banner type={'success'}>Tests Complete</Banner>
|
||||
);
|
||||
return <Banner type="success">Tests Complete</Banner>;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Renders ListView of test suites that should be visible, taking into consideration
|
||||
* any focused tests
|
||||
@ -215,8 +214,8 @@ class Overview extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{ this.renderPendingTestsBanner() }
|
||||
{ this.renderStatusBanner() }
|
||||
{this.renderPendingTestsBanner()}
|
||||
{this.renderStatusBanner()}
|
||||
<ListView
|
||||
enableEmptySections
|
||||
dataSource={this.state.dataBlob}
|
||||
@ -229,21 +228,27 @@ class Overview extends React.Component {
|
||||
}
|
||||
|
||||
Overview.propTypes = {
|
||||
testSuites: PropTypes.objectOf(PropTypes.shape({
|
||||
id: PropTypes.number.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
status: PropTypes.oneOf(Object.values(RunStatus)),
|
||||
})).isRequired,
|
||||
testSuites: PropTypes.objectOf(
|
||||
PropTypes.shape({
|
||||
id: PropTypes.number.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
status: PropTypes.oneOf(Object.values(RunStatus)),
|
||||
})
|
||||
).isRequired,
|
||||
|
||||
tests: PropTypes.objectOf(PropTypes.shape({
|
||||
testSuiteId: PropTypes.number.isRequired,
|
||||
})).isRequired,
|
||||
// eslint-disable-next-line react/no-unused-prop-types
|
||||
tests: PropTypes.objectOf(
|
||||
PropTypes.shape({
|
||||
testSuiteId: PropTypes.number.isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
|
||||
navigation: PropTypes.shape({
|
||||
navigate: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
|
||||
// eslint-disable-next-line react/no-unused-prop-types
|
||||
running: PropTypes.bool.isRequired,
|
||||
|
||||
pendingTestIds: PropTypes.objectOf(PropTypes.bool).isRequired,
|
||||
@ -283,13 +288,21 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
function mapStateToProps({ testSuites, tests, pendingTestIds, focusedTestIds }) {
|
||||
function mapStateToProps({
|
||||
testSuites,
|
||||
tests,
|
||||
pendingTestIds,
|
||||
focusedTestIds,
|
||||
}) {
|
||||
return {
|
||||
testSuites,
|
||||
tests,
|
||||
pendingTestIds,
|
||||
focusedTestIds,
|
||||
running: Object.values(testSuites).filter(suite => suite.status === RunStatus.RUNNING).length > 0,
|
||||
running:
|
||||
Object.values(testSuites).filter(
|
||||
suite => suite.status === RunStatus.RUNNING
|
||||
).length > 0,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,13 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { StyleSheet, View, Text, ListView, TouchableHighlight } from 'react-native';
|
||||
import {
|
||||
StyleSheet,
|
||||
View,
|
||||
Text,
|
||||
ListView,
|
||||
TouchableHighlight,
|
||||
} from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import RunStatus from '../../lib/RunStatus';
|
||||
@ -12,23 +18,25 @@ import StatusIndicator from '../components/StatusIndicator';
|
||||
import TestSuiteControlButton from '../components/TestSuiteControlButton';
|
||||
|
||||
class Suite extends React.Component {
|
||||
|
||||
static navigationOptions = ({ navigation: { state: { params: { title, testSuiteId, onlyShowFailingTests } }, setParams } }) => {
|
||||
return {
|
||||
title,
|
||||
headerTintColor: '#ffffff',
|
||||
headerStyle: { backgroundColor: '#1976D2' },
|
||||
headerRight: (
|
||||
<View style={{ flexDirection: 'row', marginRight: 8 }}>
|
||||
<TestSuiteControlButton
|
||||
testSuiteId={testSuiteId}
|
||||
onlyShowFailingTests={onlyShowFailingTests}
|
||||
onFilterChange={setParams}
|
||||
/>
|
||||
</View>
|
||||
),
|
||||
};
|
||||
};
|
||||
static navigationOptions = ({
|
||||
navigation: {
|
||||
state: { params: { title, testSuiteId, onlyShowFailingTests } },
|
||||
setParams,
|
||||
},
|
||||
}) => ({
|
||||
title,
|
||||
headerTintColor: '#ffffff',
|
||||
headerStyle: { backgroundColor: '#1976D2' },
|
||||
headerRight: (
|
||||
<View style={{ flexDirection: 'row', marginRight: 8 }}>
|
||||
<TestSuiteControlButton
|
||||
testSuiteId={testSuiteId}
|
||||
onlyShowFailingTests={onlyShowFailingTests}
|
||||
onFilterChange={setParams}
|
||||
/>
|
||||
</View>
|
||||
),
|
||||
});
|
||||
|
||||
/**
|
||||
* Render test group header
|
||||
@ -38,13 +46,8 @@ class Suite extends React.Component {
|
||||
*/
|
||||
static renderHeader(data, title) {
|
||||
return (
|
||||
<View
|
||||
key={`header_${title}`}
|
||||
style={styles.header}
|
||||
>
|
||||
<Text style={styles.headerText}>
|
||||
{title.toUpperCase()}
|
||||
</Text>
|
||||
<View key={`header_${title}`} style={styles.header}>
|
||||
<Text style={styles.headerText}>{title.toUpperCase()}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@ -58,7 +61,9 @@ class Suite extends React.Component {
|
||||
});
|
||||
|
||||
this.state = {
|
||||
dataBlob: this.dataSource.cloneWithRowsAndSections(buildRowsWithSections(props)),
|
||||
dataBlob: this.dataSource.cloneWithRowsAndSections(
|
||||
buildRowsWithSections(props)
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
@ -78,7 +83,7 @@ class Suite extends React.Component {
|
||||
return Object.values(testContexts).reduce((sections, context) => {
|
||||
const { name } = context;
|
||||
|
||||
context.testIds.forEach((testId) => {
|
||||
context.testIds.forEach(testId => {
|
||||
const test = tests[testId];
|
||||
|
||||
if (test && test.status === RunStatus.ERR) {
|
||||
@ -125,16 +130,16 @@ class Suite extends React.Component {
|
||||
return (
|
||||
<TouchableHighlight
|
||||
key={`row_${rowId}`}
|
||||
underlayColor={'rgba(0, 0, 0, 0.054)'}
|
||||
underlayColor="rgba(0, 0, 0, 0.054)"
|
||||
onPress={() => {
|
||||
this.goToTest(test);
|
||||
highlight();
|
||||
}}
|
||||
>
|
||||
<View style={[styles.row, status === RunStatus.ERR ? styles.error : null]}>
|
||||
<View
|
||||
style={[{ flex: 9 }, styles.rowContent]}
|
||||
>
|
||||
<View
|
||||
style={[styles.row, status === RunStatus.ERR ? styles.error : null]}
|
||||
>
|
||||
<View style={[{ flex: 9 }, styles.rowContent]}>
|
||||
<Text
|
||||
numberOfLines={2}
|
||||
style={pendingTestIds[id] ? styles.disabledRow : {}}
|
||||
@ -142,7 +147,9 @@ class Suite extends React.Component {
|
||||
{description}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={[{ flex: 1 }, styles.rowContent, [{ alignItems: 'center' }]]}>
|
||||
<View
|
||||
style={[{ flex: 1 }, styles.rowContent, [{ alignItems: 'center' }]]}
|
||||
>
|
||||
<StatusIndicator status={status} />
|
||||
</View>
|
||||
</View>
|
||||
@ -158,10 +165,7 @@ class Suite extends React.Component {
|
||||
*/
|
||||
renderSeparator(sectionID, rowID) {
|
||||
return (
|
||||
<View
|
||||
key={`separator_${sectionID}_${rowID}`}
|
||||
style={styles.separator}
|
||||
/>
|
||||
<View key={`separator_${sectionID}_${rowID}`} style={styles.separator} />
|
||||
);
|
||||
}
|
||||
|
||||
@ -170,7 +174,7 @@ class Suite extends React.Component {
|
||||
|
||||
let pendingTestsCount = 0;
|
||||
|
||||
testIds.forEach((testId) => {
|
||||
testIds.forEach(testId => {
|
||||
if (pendingTestIds[testId]) {
|
||||
pendingTestsCount += 1;
|
||||
}
|
||||
@ -178,9 +182,7 @@ class Suite extends React.Component {
|
||||
|
||||
if (pendingTestsCount) {
|
||||
return (
|
||||
<Banner type="warning">
|
||||
{pendingTestsCount} pending test(s).
|
||||
</Banner>
|
||||
<Banner type="warning">{pendingTestsCount} pending test(s).</Banner>
|
||||
);
|
||||
}
|
||||
|
||||
@ -192,25 +194,18 @@ class Suite extends React.Component {
|
||||
|
||||
switch (status) {
|
||||
case RunStatus.RUNNING:
|
||||
|
||||
return (
|
||||
<Banner type={'warning'}>
|
||||
Tests are currently running ({ progress.toFixed(2) }%).
|
||||
<Banner type="warning">
|
||||
Tests are currently running ({progress.toFixed(2)}%).
|
||||
</Banner>
|
||||
);
|
||||
|
||||
case RunStatus.OK:
|
||||
|
||||
return (
|
||||
<Banner type={'success'}>
|
||||
Tests passed. ({ time }ms)
|
||||
</Banner>
|
||||
);
|
||||
return <Banner type="success">Tests passed. ({time}ms)</Banner>;
|
||||
|
||||
case RunStatus.ERR:
|
||||
|
||||
return (
|
||||
<Banner type={'error'}>
|
||||
<Banner type="error">
|
||||
{message} ({time}ms)
|
||||
</Banner>
|
||||
);
|
||||
@ -229,9 +224,8 @@ class Suite extends React.Component {
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
|
||||
{ this.renderPendingTestsBanner() }
|
||||
{ this.renderStatusBanner() }
|
||||
{this.renderPendingTestsBanner()}
|
||||
{this.renderStatusBanner()}
|
||||
|
||||
<ListView
|
||||
dataSource={dataBlob}
|
||||
@ -242,7 +236,6 @@ class Suite extends React.Component {
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Suite.propTypes = {
|
||||
@ -262,18 +255,23 @@ Suite.propTypes = {
|
||||
message: PropTypes.string,
|
||||
}).isRequired,
|
||||
|
||||
testContexts: PropTypes.objectOf(PropTypes.shape({
|
||||
name: PropTypes.string.isRequired,
|
||||
testIds: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
})).isRequired,
|
||||
testContexts: PropTypes.objectOf(
|
||||
PropTypes.shape({
|
||||
name: PropTypes.string.isRequired,
|
||||
testIds: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
|
||||
tests: PropTypes.objectOf(PropTypes.shape({
|
||||
id: PropTypes.number,
|
||||
description: PropTypes.string,
|
||||
status: PropTypes.oneOf(Object.values(RunStatus)),
|
||||
})).isRequired,
|
||||
tests: PropTypes.objectOf(
|
||||
PropTypes.shape({
|
||||
id: PropTypes.number,
|
||||
description: PropTypes.string,
|
||||
status: PropTypes.oneOf(Object.values(RunStatus)),
|
||||
})
|
||||
).isRequired,
|
||||
|
||||
pendingTestIds: PropTypes.objectOf(PropTypes.bool).isRequired,
|
||||
// eslint-disable-next-line react/no-unused-prop-types
|
||||
focusedTestIds: PropTypes.objectOf(PropTypes.bool).isRequired,
|
||||
};
|
||||
|
||||
@ -346,11 +344,16 @@ function buildRowsWithSections({ testContexts, tests, focusedTestIds }) {
|
||||
}, []);
|
||||
|
||||
if (contextTestsToShow.length > 0) {
|
||||
const effectiveContext = highestNonRootAncestor(testContext, testContexts);
|
||||
const effectiveContext = highestNonRootAncestor(
|
||||
testContext,
|
||||
testContexts
|
||||
);
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
sections[effectiveContext.name] = sections[effectiveContext.name] || [];
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
sections[effectiveContext.name] = sections[effectiveContext.name].concat(contextTestsToShow);
|
||||
sections[effectiveContext.name] = sections[effectiveContext.name].concat(
|
||||
contextTestsToShow
|
||||
);
|
||||
}
|
||||
|
||||
return sections;
|
||||
@ -358,11 +361,12 @@ function buildRowsWithSections({ testContexts, tests, focusedTestIds }) {
|
||||
}
|
||||
|
||||
function highestNonRootAncestor(testContext, testContexts) {
|
||||
const parentContextId = testContext.parentContextId;
|
||||
const { parentContextId } = testContext;
|
||||
|
||||
if (parentContextId) {
|
||||
const parentContext = testContexts[parentContextId];
|
||||
const parentContextIsNotRoot = parentContext && parentContext.parentContextId;
|
||||
const parentContextIsNotRoot =
|
||||
parentContext && parentContext.parentContextId;
|
||||
|
||||
if (parentContextIsNotRoot) {
|
||||
return highestNonRootAncestor(parentContext, testContexts);
|
||||
@ -372,16 +376,28 @@ function highestNonRootAncestor(testContext, testContexts) {
|
||||
return testContext;
|
||||
}
|
||||
|
||||
function mapStateToProps(state, { navigation: { state: { params: { testSuiteId } } } }) {
|
||||
const { tests, testContexts, testSuites, pendingTestIds, focusedTestIds } = state;
|
||||
function mapStateToProps(
|
||||
state,
|
||||
{ navigation: { state: { params: { testSuiteId } } } }
|
||||
) {
|
||||
const {
|
||||
tests,
|
||||
testContexts,
|
||||
testSuites,
|
||||
pendingTestIds,
|
||||
focusedTestIds,
|
||||
} = state;
|
||||
const testSuite = testSuites[testSuiteId];
|
||||
|
||||
const testSuiteContexts = testSuite.testContextIds.reduce((suiteContexts, contextId) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
suiteContexts[contextId] = testContexts[contextId];
|
||||
const testSuiteContexts = testSuite.testContextIds.reduce(
|
||||
(suiteContexts, contextId) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
suiteContexts[contextId] = testContexts[contextId];
|
||||
|
||||
return suiteContexts;
|
||||
}, {});
|
||||
return suiteContexts;
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
const testSuiteTests = testSuite.testIds.reduce((suiteTests, testId) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
|
@ -10,40 +10,27 @@ import RunStatus from '../../lib/RunStatus';
|
||||
import TestControlButton from '../components/TestControlButton';
|
||||
|
||||
class Test extends React.Component {
|
||||
|
||||
static navigationOptions = ({ navigation: { state: { params: { title, testId } } } }) => {
|
||||
return {
|
||||
title,
|
||||
headerTintColor: '#ffffff',
|
||||
headerStyle: { backgroundColor: '#1976D2' },
|
||||
headerRight: (
|
||||
<View style={{ marginRight: 8 }}>
|
||||
<TestControlButton testId={testId} />
|
||||
</View>
|
||||
),
|
||||
};
|
||||
};
|
||||
static navigationOptions = ({
|
||||
navigation: { state: { params: { title, testId } } },
|
||||
}) => ({
|
||||
title,
|
||||
headerTintColor: '#ffffff',
|
||||
headerStyle: { backgroundColor: '#1976D2' },
|
||||
headerRight: (
|
||||
<View style={{ marginRight: 8 }}>
|
||||
<TestControlButton testId={testId} />
|
||||
</View>
|
||||
),
|
||||
});
|
||||
|
||||
static renderBanner({ status, time }) {
|
||||
switch (status) {
|
||||
case RunStatus.RUNNING:
|
||||
return (
|
||||
<Banner type={'warning'}>
|
||||
Test is currently running.
|
||||
</Banner>
|
||||
);
|
||||
return <Banner type="warning">Test is currently running.</Banner>;
|
||||
case RunStatus.OK:
|
||||
return (
|
||||
<Banner type={'success'}>
|
||||
Test passed. ({time}ms)
|
||||
</Banner>
|
||||
);
|
||||
return <Banner type="success">Test passed. ({time}ms)</Banner>;
|
||||
case RunStatus.ERR:
|
||||
return (
|
||||
<Banner type={'error'}>
|
||||
Test failed. ({time}ms)
|
||||
</Banner>
|
||||
);
|
||||
return <Banner type="error">Test failed. ({time}ms)</Banner>;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@ -56,30 +43,33 @@ class Test extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { test: { stackTrace, message, description, func, status, time }, testContextName } = this.props;
|
||||
const {
|
||||
test: { stackTrace, message, description, func, status, time },
|
||||
testContextName,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{Test.renderBanner({ status, time })}
|
||||
<ScrollView >
|
||||
<ScrollView>
|
||||
<View style={styles.sectionContainer}>
|
||||
<Text style={styles.heading}>{testContextName}</Text>
|
||||
<Text style={styles.description}>{description}</Text>
|
||||
</View>
|
||||
{message ? <View style={styles.sectionContainer}>
|
||||
<Text style={styles.headingWarn}>Test Error Message</Text>
|
||||
<Text style={styles.message}>{message || 'None.'}</Text>
|
||||
</View> : null }
|
||||
{stackTrace ? <View style={styles.sectionContainer}>
|
||||
<Text style={styles.headingWarn}>Test Error Stack</Text>
|
||||
<Text style={styles.description}>
|
||||
{stackTrace || 'None.'}
|
||||
</Text>
|
||||
</View> : null }
|
||||
{message ? (
|
||||
<View style={styles.sectionContainer}>
|
||||
<Text style={styles.headingWarn}>Test Error Message</Text>
|
||||
<Text style={styles.message}>{message || 'None.'}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
{stackTrace ? (
|
||||
<View style={styles.sectionContainer}>
|
||||
<Text style={styles.headingWarn}>Test Error Stack</Text>
|
||||
<Text style={styles.description}>{stackTrace || 'None.'}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
<View style={styles.sectionContainer}>
|
||||
<Text style={styles.heading}>
|
||||
Test Code Preview
|
||||
</Text>
|
||||
<Text style={styles.heading}>Test Code Preview</Text>
|
||||
<Text style={styles.description}>
|
||||
{beautify(removeLastLine(removeFirstLine(func.toString())), {
|
||||
indent_size: 4,
|
||||
@ -103,6 +93,7 @@ Test.propTypes = {
|
||||
description: PropTypes.string,
|
||||
}).isRequired,
|
||||
|
||||
// eslint-disable-next-line react/require-default-props
|
||||
testContextName: PropTypes.string,
|
||||
|
||||
navigation: PropTypes.shape({
|
||||
@ -159,11 +150,17 @@ const styles = StyleSheet.create({
|
||||
|
||||
*/
|
||||
|
||||
function select({ tests, testContexts }, { navigation: { state: { params: { testId } } } }) {
|
||||
function select(
|
||||
{ tests, testContexts },
|
||||
{ navigation: { state: { params: { testId } } } }
|
||||
) {
|
||||
const test = tests[testId];
|
||||
let testContext = testContexts[test.testContextId];
|
||||
|
||||
while (testContext.parentContextId && testContexts[testContext.parentContextId].parentContextId) {
|
||||
while (
|
||||
testContext.parentContextId &&
|
||||
testContexts[testContext.parentContextId].parentContextId
|
||||
) {
|
||||
testContext = testContexts[testContext.parentContextId];
|
||||
}
|
||||
return {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { AsyncStorage } from 'react-native';
|
||||
import { applyMiddleware, createStore, compose } from 'redux';
|
||||
import thunk from 'redux-thunk';
|
||||
import reduxLogger from 'redux-logger';
|
||||
// import reduxLogger from 'redux-logger';
|
||||
import { persistStore, autoRehydrate } from 'redux-persist';
|
||||
|
||||
import whitelist from './whitelist';
|
||||
@ -10,11 +10,11 @@ import reducers from '../reducers';
|
||||
function setup(done) {
|
||||
const isDev = global.isDebuggingInChrome || __DEV__;
|
||||
|
||||
const logger = reduxLogger({
|
||||
/* const logger = reduxLogger({
|
||||
predicate: () => false,
|
||||
collapsed: true,
|
||||
duration: true,
|
||||
});
|
||||
}); */
|
||||
|
||||
// AsyncStorage.clear();
|
||||
|
||||
@ -25,10 +25,14 @@ function setup(done) {
|
||||
|
||||
if (isDev) {
|
||||
// middlewares.push(applyMiddleware(...[logger]));
|
||||
middlewares.push(applyMiddleware(require('redux-immutable-state-invariant')()));
|
||||
middlewares.push(
|
||||
// eslint-disable-next-line global-require
|
||||
applyMiddleware(require('redux-immutable-state-invariant')())
|
||||
);
|
||||
}
|
||||
|
||||
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
||||
const composeEnhancers =
|
||||
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
||||
|
||||
const store = createStore(reducers, {}, composeEnhancers(...middlewares));
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
export default function addTests({ before, fdescribe, describe, it, firebase }) {
|
||||
|
||||
export default function addTests({ before, describe, it, firebase }) {
|
||||
before(() => {
|
||||
firebase.native.admob().initialize('ca-app-pub-3940256099942544~3347511713');
|
||||
firebase.native
|
||||
.admob()
|
||||
.initialize('ca-app-pub-3940256099942544~3347511713');
|
||||
});
|
||||
|
||||
describe('AdMob', () => {
|
||||
it('should return static variables', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('should return static variables', () =>
|
||||
new Promise(resolve => {
|
||||
const statics = firebase.native.admob;
|
||||
|
||||
statics.should.have.property('Banner').and.be.a.Function();
|
||||
@ -14,11 +15,10 @@ export default function addTests({ before, fdescribe, describe, it, firebase })
|
||||
statics.should.have.property('AdRequest').and.be.a.Function();
|
||||
statics.should.have.property('VideoOptions').and.be.a.Function();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('should return instance methods', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('should return instance methods', () =>
|
||||
new Promise(resolve => {
|
||||
const admob = firebase.native.admob();
|
||||
|
||||
admob.should.have.property('initialize').and.be.a.Function();
|
||||
@ -26,14 +26,12 @@ export default function addTests({ before, fdescribe, describe, it, firebase })
|
||||
admob.should.have.property('interstitial').and.be.a.Function();
|
||||
admob.should.have.property('rewarded').and.be.a.Function();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
describe('AdRequest', () => {
|
||||
|
||||
it('should return AdRequest methods', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('should return AdRequest methods', () =>
|
||||
new Promise(resolve => {
|
||||
const request = new firebase.native.admob.AdRequest();
|
||||
|
||||
request.should.have.property('build').and.be.a.Function();
|
||||
@ -44,25 +42,27 @@ export default function addTests({ before, fdescribe, describe, it, firebase })
|
||||
request.should.have.property('setGender').and.be.a.Function();
|
||||
request.should.have.property('setLocation').and.be.a.Function();
|
||||
request.should.have.property('setRequestAgent').and.be.a.Function();
|
||||
request.should.have.property('setIsDesignedForFamilies').and.be.a.Function();
|
||||
request.should.have.property('tagForChildDirectedTreatment').and.be.a.Function();
|
||||
request.should.have
|
||||
.property('setIsDesignedForFamilies')
|
||||
.and.be.a.Function();
|
||||
request.should.have
|
||||
.property('tagForChildDirectedTreatment')
|
||||
.and.be.a.Function();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('should build an empty request', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('should build an empty request', () =>
|
||||
new Promise(resolve => {
|
||||
const request = new firebase.native.admob.AdRequest();
|
||||
const build = request.build();
|
||||
|
||||
build.should.have.property('keywords').and.be.a.Array();
|
||||
build.should.have.property('testDevices').and.be.a.Array();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('should build a full request', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('should build a full request', () =>
|
||||
new Promise(resolve => {
|
||||
const request = new firebase.native.admob.AdRequest();
|
||||
|
||||
request
|
||||
@ -85,39 +85,42 @@ export default function addTests({ before, fdescribe, describe, it, firebase })
|
||||
build.keywords.should.containEql('foo');
|
||||
build.keywords.should.containEql('bar');
|
||||
build.testDevices.should.containEql('foobar');
|
||||
build.should.have.property('contentUrl').and.be.a.equal('http://google.com');
|
||||
build.should.have
|
||||
.property('contentUrl')
|
||||
.and.be.a.equal('http://google.com');
|
||||
build.should.have.property('gender').and.be.a.equal('female');
|
||||
build.should.have.property('requestAgent').and.be.a.equal('foobar');
|
||||
build.should.have.property('isDesignedForFamilies').and.be.a.equal(true);
|
||||
build.should.have.property('tagForChildDirectedTreatment').and.be.a.equal(true);
|
||||
build.should.have
|
||||
.property('isDesignedForFamilies')
|
||||
.and.be.a.equal(true);
|
||||
build.should.have
|
||||
.property('tagForChildDirectedTreatment')
|
||||
.and.be.a.equal(true);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
describe('VideoOptions', () => {
|
||||
it('should return VideoOptions methods', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('should return VideoOptions methods', () =>
|
||||
new Promise(resolve => {
|
||||
const options = new firebase.native.admob.VideoOptions();
|
||||
|
||||
options.should.have.property('build').and.be.a.Function();
|
||||
options.should.have.property('setStartMuted').and.be.a.Function();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('should build an empty request', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('should build an empty request', () =>
|
||||
new Promise(resolve => {
|
||||
const options = new firebase.native.admob.VideoOptions();
|
||||
const build = options.build();
|
||||
|
||||
build.should.have.property('startMuted').and.be.a.equal(true);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('should build all options', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('should build all options', () =>
|
||||
new Promise(resolve => {
|
||||
const options = new firebase.native.admob.VideoOptions();
|
||||
|
||||
options.setStartMuted(false);
|
||||
@ -126,36 +129,35 @@ export default function addTests({ before, fdescribe, describe, it, firebase })
|
||||
|
||||
build.should.have.property('startMuted').and.be.a.equal(false);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
}));
|
||||
});
|
||||
describe('Interstitial', () => {
|
||||
it('should return a new instance with methods', () => {
|
||||
return new Promise((resolve) => {
|
||||
const advert = firebase.native.admob().interstitial('ca-app-pub-3940256099942544/1033173712');
|
||||
it('should return a new instance with methods', () =>
|
||||
new Promise(resolve => {
|
||||
const advert = firebase.native
|
||||
.admob()
|
||||
.interstitial('ca-app-pub-3940256099942544/1033173712');
|
||||
|
||||
advert.should.have.property('loadAd').and.be.a.Function();
|
||||
advert.should.have.property('isLoaded').and.be.a.Function();
|
||||
advert.should.have.property('show').and.be.a.Function();
|
||||
advert.should.have.property('on').and.be.a.Function();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
describe('Rewarded', () => {
|
||||
it('should return a new instance with methods', () => {
|
||||
return new Promise((resolve) => {
|
||||
const advert = firebase.native.admob().rewarded('ca-app-pub-3940256099942544/1033173712');
|
||||
it('should return a new instance with methods', () =>
|
||||
new Promise(resolve => {
|
||||
const advert = firebase.native
|
||||
.admob()
|
||||
.rewarded('ca-app-pub-3940256099942544/1033173712');
|
||||
|
||||
advert.should.have.property('loadAd').and.be.a.Function();
|
||||
advert.should.have.property('isLoaded').and.be.a.Function();
|
||||
advert.should.have.property('show').and.be.a.Function();
|
||||
advert.should.have.property('on').and.be.a.Function();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
@ -1,64 +1,59 @@
|
||||
|
||||
export default function addTests({ fdescribe, describe, it, firebase }) {
|
||||
export default function addTests({ describe, it, firebase }) {
|
||||
describe('Analytics', () => {
|
||||
it('logEvent: it should log a text event without error', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('logEvent: it should log a text event without error', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native.analytics().logEvent('test_event');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('logEvent: it should log a text event with parameters without error', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('logEvent: it should log a text event with parameters without error', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native.analytics().logEvent('test_event', {
|
||||
boolean: true,
|
||||
number: 1,
|
||||
string: 'string',
|
||||
});
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('setAnalyticsCollectionEnabled: it should run without error', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('setAnalyticsCollectionEnabled: it should run without error', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native.analytics().setAnalyticsCollectionEnabled(true);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('setCurrentScreen: it should run without error', () => {
|
||||
return new Promise((resolve) => {
|
||||
firebase.native.analytics().setCurrentScreen('test screen', 'test class override');
|
||||
it('setCurrentScreen: it should run without error', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native
|
||||
.analytics()
|
||||
.setCurrentScreen('test screen', 'test class override');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('setMinimumSessionDuration: it should run without error', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('setMinimumSessionDuration: it should run without error', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native.analytics().setMinimumSessionDuration(10000);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('setSessionTimeoutDuration: it should run without error', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('setSessionTimeoutDuration: it should run without error', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native.analytics().setSessionTimeoutDuration(1800000);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('setUserId: it should run without error', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('setUserId: it should run without error', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native.analytics().setUserId('test-id');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('setUserProperty: it should run without error', () => {
|
||||
return new Promise((resolve) => {
|
||||
firebase.native.analytics().setUserProperty('test-property', 'test-value');
|
||||
it('setUserProperty: it should run without error', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native
|
||||
.analytics()
|
||||
.setUserProperty('test-property', 'test-value');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -15,20 +15,21 @@ function configTests({ before, describe, it, firebase }) {
|
||||
});
|
||||
|
||||
describe('Config', () => {
|
||||
it('it should fetch and activate config', () => {
|
||||
return firebase.native.config().fetch(0)
|
||||
.then(() => {
|
||||
return firebase.native.config().activateFetched();
|
||||
})
|
||||
.then((activated) => {
|
||||
it('it should fetch and activate config', () =>
|
||||
firebase.native
|
||||
.config()
|
||||
.fetch(0)
|
||||
.then(() => firebase.native.config().activateFetched())
|
||||
.then(activated => {
|
||||
activated.should.be.a.Boolean();
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('it should get a single value by key', () => {
|
||||
return firebase.native.config().getValue('foo')
|
||||
.then((snapshot) => {
|
||||
it('it should get a single value by key', () =>
|
||||
firebase.native
|
||||
.config()
|
||||
.getValue('foo')
|
||||
.then(snapshot => {
|
||||
snapshot.should.be.a.Object();
|
||||
snapshot.source.should.be.a.String();
|
||||
snapshot.val.should.be.a.Function();
|
||||
@ -36,12 +37,13 @@ function configTests({ before, describe, it, firebase }) {
|
||||
const value = snapshot.val();
|
||||
value.should.be.equalOneOf('bar', true);
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('it should get multiple values by an array of keys', () => {
|
||||
return firebase.native.config().getValues(['foo', 'bar', 'foobar', 'numvalue'])
|
||||
.then((result) => {
|
||||
it('it should get multiple values by an array of keys', () =>
|
||||
firebase.native
|
||||
.config()
|
||||
.getValues(['foo', 'bar', 'foobar', 'numvalue'])
|
||||
.then(result => {
|
||||
result.should.be.a.Object();
|
||||
result.should.have.keys('foo', 'bar', 'foobar');
|
||||
const fooValue = result.foo.val();
|
||||
@ -55,16 +57,16 @@ function configTests({ before, describe, it, firebase }) {
|
||||
numvalueValue.should.be.equal(0);
|
||||
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('it get all keys as an array', () => {
|
||||
return firebase.native.config().getKeysByPrefix()
|
||||
.then((result) => {
|
||||
it('it get all keys as an array', () =>
|
||||
firebase.native
|
||||
.config()
|
||||
.getKeysByPrefix()
|
||||
.then(result => {
|
||||
result.should.be.Array();
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,8 @@ import RNFirebase from './../../../firebase';
|
||||
|
||||
const androidTestConfig = {
|
||||
// firebase android sdk completely ignores client id
|
||||
clientId: '305229645282-j8ij0jev9ut24odmlk9i215pas808ugn.apps.googleusercontent.com',
|
||||
clientId:
|
||||
'305229645282-j8ij0jev9ut24odmlk9i215pas808ugn.apps.googleusercontent.com',
|
||||
appId: '1:305229645282:android:efe37851d57e1d05',
|
||||
apiKey: 'AIzaSyCzbBYFyX8d6VdSu7T4s10IWYbPc-dguwM',
|
||||
databaseURL: 'https://rnfirebase-b9ad4.firebaseio.com',
|
||||
@ -15,7 +16,8 @@ const androidTestConfig = {
|
||||
};
|
||||
|
||||
const iosTestConfig = {
|
||||
clientId: '305229645282-22imndi01abc2p6esgtu1i1m9mqrd0ib.apps.googleusercontent.com',
|
||||
clientId:
|
||||
'305229645282-22imndi01abc2p6esgtu1i1m9mqrd0ib.apps.googleusercontent.com',
|
||||
androidClientId: androidTestConfig.clientId,
|
||||
appId: '1:305229645282:ios:7b45748cb1117d2d',
|
||||
apiKey: 'AIzaSyAcdVLG5dRzA1ck_fa_xd4Z0cY7cga7S5A',
|
||||
@ -27,7 +29,7 @@ const iosTestConfig = {
|
||||
|
||||
function rand(from = 1, to = 9999) {
|
||||
const r = Math.random();
|
||||
return Math.floor(r * ((to - from) + from));
|
||||
return Math.floor(r * (to - from + from));
|
||||
}
|
||||
|
||||
function coreTests({ describe, it }) {
|
||||
@ -38,18 +40,32 @@ function coreTests({ describe, it }) {
|
||||
});
|
||||
|
||||
it('natively initialized apps should have options available in js', () => {
|
||||
should.equal(RNFirebase.app().options.apiKey, Platform.OS === 'ios' ? iosTestConfig.apiKey : androidTestConfig.apiKey);
|
||||
should.equal(RNFirebase.app().options.appId, Platform.OS === 'ios' ? iosTestConfig.appId : androidTestConfig.appId);
|
||||
should.equal(RNFirebase.app().options.databaseURL, iosTestConfig.databaseURL);
|
||||
should.equal(RNFirebase.app().options.messagingSenderId, iosTestConfig.messagingSenderId);
|
||||
should.equal(
|
||||
RNFirebase.app().options.apiKey,
|
||||
Platform.OS === 'ios' ? iosTestConfig.apiKey : androidTestConfig.apiKey
|
||||
);
|
||||
should.equal(
|
||||
RNFirebase.app().options.appId,
|
||||
Platform.OS === 'ios' ? iosTestConfig.appId : androidTestConfig.appId
|
||||
);
|
||||
should.equal(
|
||||
RNFirebase.app().options.databaseURL,
|
||||
iosTestConfig.databaseURL
|
||||
);
|
||||
should.equal(
|
||||
RNFirebase.app().options.messagingSenderId,
|
||||
iosTestConfig.messagingSenderId
|
||||
);
|
||||
should.equal(RNFirebase.app().options.projectId, iosTestConfig.projectId);
|
||||
should.equal(RNFirebase.app().options.storageBucket, iosTestConfig.storageBucket);
|
||||
should.equal(
|
||||
RNFirebase.app().options.storageBucket,
|
||||
iosTestConfig.storageBucket
|
||||
);
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
it('it should resolve onReady for natively initialized apps', () => {
|
||||
return RNFirebase.app().onReady();
|
||||
});
|
||||
it('it should resolve onReady for natively initialized apps', () =>
|
||||
RNFirebase.app().onReady());
|
||||
|
||||
it('it should provide an array of apps', () => {
|
||||
should.equal(!!RNFirebase.apps.length, true);
|
||||
@ -59,12 +75,16 @@ function coreTests({ describe, it }) {
|
||||
|
||||
it('it should initialize dynamic apps', () => {
|
||||
const name = `testscoreapp${rand()}`;
|
||||
return RNFirebase
|
||||
.initializeApp(Platform.OS === 'ios' ? iosTestConfig : androidTestConfig, name)
|
||||
return RNFirebase.initializeApp(
|
||||
Platform.OS === 'ios' ? iosTestConfig : androidTestConfig,
|
||||
name
|
||||
)
|
||||
.onReady()
|
||||
.then((newApp) => {
|
||||
.then(newApp => {
|
||||
newApp.name.should.equal(name.toUpperCase());
|
||||
newApp.options.apiKey.should.equal((Platform.OS === 'ios' ? iosTestConfig : androidTestConfig).apiKey);
|
||||
newApp.options.apiKey.should.equal(
|
||||
(Platform.OS === 'ios' ? iosTestConfig : androidTestConfig).apiKey
|
||||
);
|
||||
// TODO add back in when android sdk support for deleting apps becomes available
|
||||
// return newApp.delete();
|
||||
return Promise.resolve();
|
||||
|
@ -1,38 +1,35 @@
|
||||
export default function addTests({ describe, it, firebase }) {
|
||||
|
||||
describe('API', () => {
|
||||
it('it should set collection enabled/disabled', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('it should set collection enabled/disabled', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native.crash().setCrashCollectionEnabled(false);
|
||||
firebase.native.crash().setCrashCollectionEnabled(true);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('it should return whether crash reporting is enabled', () => {
|
||||
return new Promise((resolve) => {
|
||||
firebase.native.crash().isCrashCollectionEnabled()
|
||||
.then((enabled) => {
|
||||
it('it should return whether crash reporting is enabled', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native
|
||||
.crash()
|
||||
.isCrashCollectionEnabled()
|
||||
.then(enabled => {
|
||||
enabled.should.be.a.Boolean();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
describe('Log', () => {
|
||||
it('log: it should log without error', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('log: it should log without error', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native.crash().log('Test log');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('logcat: it should log without error', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('logcat: it should log without error', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native.crash().logcat(0, 'LogTest', 'Test log');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
@ -1,52 +1,47 @@
|
||||
export default function addTests({ describe, it, firebase }) {
|
||||
describe('Crashlytics', () => {
|
||||
it('log: it should log without error', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('log: it should log without error', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native.fabric.crashlytics().log('Test log');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('recordError: it should record an error without error', () => {
|
||||
return new Promise((resolve) => {
|
||||
it('recordError: it should record an error without error', () =>
|
||||
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) => {
|
||||
it('setBoolValue: it should set a boolean value without error', () =>
|
||||
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) => {
|
||||
it('setFloatValue: it should set a float value without error', () =>
|
||||
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) => {
|
||||
it('setIntValue: it should set an integer value without error', () =>
|
||||
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');
|
||||
it('setStringValue: it should set a string value without error', () =>
|
||||
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) => {
|
||||
it('setUserIdentifier: it should set the user ID without error', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native.fabric.crashlytics().setUserIdentifier('1234');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
@ -2,7 +2,11 @@ import firebase from '../../firebase';
|
||||
import TestSuite from '../../../lib/TestSuite';
|
||||
import crashlyticsTests from './crashlyticsTests';
|
||||
|
||||
const suite = new TestSuite('Crashlytics', 'firebase.fabric.crashlytics()', firebase);
|
||||
const suite = new TestSuite(
|
||||
'Crashlytics',
|
||||
'firebase.fabric.crashlytics()',
|
||||
firebase
|
||||
);
|
||||
|
||||
// bootstrap tests
|
||||
suite.addTests(crashlyticsTests);
|
||||
|
@ -18,4 +18,3 @@ suite.addTests(refTestGroups);
|
||||
suite.addTests(snapshotTests);
|
||||
|
||||
export default suite;
|
||||
|
||||
|
@ -32,7 +32,7 @@ function childTests({ describe, it, context, firebase }) {
|
||||
});
|
||||
});
|
||||
|
||||
context('when passed a path that doesn\'t exist', () => {
|
||||
context("when passed a path that doesn't exist", () => {
|
||||
it('creates a reference, anyway', () => {
|
||||
// Setup
|
||||
|
||||
|
@ -9,7 +9,6 @@ function factoryTests({ describe, it, firebase }) {
|
||||
|
||||
// Test
|
||||
|
||||
|
||||
// Assertion
|
||||
|
||||
(ref.key === null).should.be.true();
|
||||
@ -24,7 +23,7 @@ function factoryTests({ describe, it, firebase }) {
|
||||
// Test
|
||||
let valueAtRef;
|
||||
|
||||
await ref.once('value', (snapshot) => {
|
||||
await ref.once('value', snapshot => {
|
||||
valueAtRef = snapshot.val();
|
||||
});
|
||||
|
||||
|
@ -22,9 +22,24 @@ import priorityTests from './priorityTests';
|
||||
import DatabaseContents from '../../support/DatabaseContents';
|
||||
|
||||
const testGroups = [
|
||||
issueSpecificTests, factoryTests, keyTests, parentTests, childTests, rootTests,
|
||||
pushTests, onTests, onValueTests, onChildAddedTests, onceTests, updateTests,
|
||||
removeTests, setTests, transactionTests, queryTests, refTests, isEqualTests,
|
||||
issueSpecificTests,
|
||||
factoryTests,
|
||||
keyTests,
|
||||
parentTests,
|
||||
childTests,
|
||||
rootTests,
|
||||
pushTests,
|
||||
onTests,
|
||||
onValueTests,
|
||||
onChildAddedTests,
|
||||
onceTests,
|
||||
updateTests,
|
||||
removeTests,
|
||||
setTests,
|
||||
transactionTests,
|
||||
queryTests,
|
||||
refTests,
|
||||
isEqualTests,
|
||||
priorityTests,
|
||||
offTests,
|
||||
];
|
||||
@ -42,10 +57,9 @@ function registerTestSuite(testSuite) {
|
||||
await this._databaseRef.parent.child('issues').set(DatabaseContents.ISSUES);
|
||||
});
|
||||
|
||||
testGroups.forEach((testGroup) => {
|
||||
testGroups.forEach(testGroup => {
|
||||
testGroup(testSuite);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
module.exports = registerTestSuite;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user